diff --git a/.github/workflows/base.yml b/.github/workflows/base.yml index 752de25fb..4023569e8 100644 --- a/.github/workflows/base.yml +++ b/.github/workflows/base.yml @@ -22,10 +22,10 @@ on: jobs: test: timeout-minutes: 20 - strategy: + strategy: fail-fast: false matrix: - framework: [ net6.0, net7.0, net8.0 ] + framework: [ net8.0, net9.0 ] os: [ ubuntu-latest ] configuration: [ release ] runs-on: ${{ matrix.os }} @@ -33,36 +33,36 @@ jobs: env: CLOUDSMITH_CICD_USER: ${{ secrets.CLOUDSMITH_CICD_USER }} steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Login to Cloudsmith - if: ${{ env.CLOUDSMITH_CICD_USER != '' }} - uses: docker/login-action@v3 - with: - registry: docker.eventstore.com - username: ${{ secrets.CLOUDSMITH_CICD_USER }} - password: ${{ secrets.CLOUDSMITH_CICD_TOKEN }} - - name: Pull EventStore Image - shell: bash - run: | - docker pull docker.eventstore.com/${{ inputs.docker-image }}:${{ inputs.docker-tag }} - - name: Install dotnet SDKs - uses: actions/setup-dotnet@v3 - with: - dotnet-version: | - 6.0.x - 7.0.x - 8.0.x - - name: Run Tests - shell: bash - env: - ES_DOCKER_TAG: ${{ inputs.docker-tag }} - ES_DOCKER_REGISTRY: docker.eventstore.com/${{ inputs.docker-image }} - run: | - sudo ./gencert.sh - dotnet test --configuration ${{ matrix.configuration }} --blame \ - --logger:"GitHubActions;report-warnings=false" --logger:"console;verbosity=normal" \ - --framework ${{ matrix.framework }} \ - test/EventStore.Client.${{ inputs.test }}.Tests + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Login to Cloudsmith + if: ${{ env.CLOUDSMITH_CICD_USER != '' }} + uses: docker/login-action@v3 + with: + registry: docker.eventstore.com + username: ${{ secrets.CLOUDSMITH_CICD_USER }} + password: ${{ secrets.CLOUDSMITH_CICD_TOKEN }} + - name: Pull EventStore Image + shell: bash + run: | + docker pull docker.eventstore.com/${{ inputs.docker-image }}:${{ inputs.docker-tag }} + - name: Install dotnet SDKs + uses: actions/setup-dotnet@v3 + with: + dotnet-version: | + 8.0.x + 9.0.x + - name: Run Tests + shell: bash + env: + ES_DOCKER_TAG: ${{ inputs.docker-tag }} + ES_DOCKER_REGISTRY: docker.eventstore.com/${{ inputs.docker-image }} + run: | + sudo ./gencert.sh + dotnet test --configuration ${{ matrix.configuration }} --blame \ + --logger:"GitHubActions;report-warnings=false" --logger:"console;verbosity=normal" \ + --framework ${{ matrix.framework }} \ + --filter "Category=Target:${{ inputs.test }}" \ + test/Kurrent.Client.Tests diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4b8e1f9b1..ec0af3697 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: fail-fast: false matrix: docker-tag: [ ci, lts, previous-lts ] - test: [ Streams, PersistentSubscriptions, Operations, UserManagement, ProjectionManagement ] + test: [ Streams, PersistentSubscriptions, Operations, ProjectionManagement, UserManagement, Security, Misc ] name: Test CE (${{ matrix.docker-tag }}) with: docker-tag: ${{ matrix.docker-tag }} diff --git a/.github/workflows/dispatch-ce.yml b/.github/workflows/dispatch-ce.yml index 722baaea7..c05c2402f 100644 --- a/.github/workflows/dispatch-ce.yml +++ b/.github/workflows/dispatch-ce.yml @@ -15,10 +15,10 @@ on: jobs: test: uses: ./.github/workflows/base.yml - strategy: + strategy: fail-fast: false matrix: - test: [ Streams, PersistentSubscriptions, Operations, UserManagement, ProjectionManagement ] + test: [ Streams, PersistentSubscriptions, Operations, ProjectionManagement, UserManagement, Security, Misc ] name: Test CE (${{ inputs.docker-tag }}) with: docker-tag: ${{ inputs.docker-tag }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 598be309d..ef6dfb6bc 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,199 +1,201 @@ -name: Publish - -on: - pull_request: - push: - branches: - - master - tags: - - v* - -jobs: - vulnerability-scan: - timeout-minutes: 10 - strategy: - fail-fast: false - matrix: - framework: [ net6.0, net7.0, net8.0 ] - os: [ ubuntu-latest, windows-latest ] - runs-on: ${{ matrix.os }} - name: scan-vulnerabilities/${{ matrix.os }}/${{ matrix.framework }} - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Install dotnet SDKs - uses: actions/setup-dotnet@v3 - with: - dotnet-version: | - 6.0.x - 7.0.x - 8.0.x - - name: Scan for Vulnerabilities - shell: bash - run: | - dotnet nuget list source - dotnet restore - dotnet list package --vulnerable --include-transitive --framework ${{ matrix.framework }} | tee vulnerabilities.txt - ! cat vulnerabilities.txt | grep -q "has the following vulnerable packages" - - build-samples: - timeout-minutes: 5 - name: build-samples/${{ matrix.framework }} - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - framework: [ net8.0 ] - services: - esdb: - image: docker.eventstore.com/eventstore-ce/eventstoredb-ce:lts - env: - EVENTSTORE_INSECURE: true - EVENTSTORE_MEM_DB: false - EVENTSTORE_RUN_PROJECTIONS: all - EVENTSTORE_START_STANDARD_PROJECTIONS: true - ports: - - 2113:2113 - options: --health-cmd "exit 0" - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Install dotnet SDKs - uses: actions/setup-dotnet@v3 - with: - dotnet-version: | - 8.0.x - - name: Compile - shell: bash - run: | - dotnet build samples - - name: Run - shell: bash - run: | - find samples/ -type f -iname "*.csproj" -print0 | xargs -0L1 dotnet run --framework ${{ matrix.framework }} --project - - generate-certificates: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - name: Generate certificates - run: | - mkdir -p certs - docker run --rm --user root --volume "$PWD/certs:/tmp" docker.eventstore.com/eventstore-utils/es-gencert-cli:latest create-ca -out /tmp/ca - docker run --rm --user root --volume "$PWD/certs:/tmp" docker.eventstore.com/eventstore-utils/es-gencert-cli:latest create-node -ca-certificate /tmp/ca/ca.crt -ca-key /tmp/ca/ca.key -out /tmp/node -ip-addresses 127.0.0.1 -dns-names localhost - docker run --rm --user root --volume "$PWD/certs:/tmp" docker.eventstore.com/eventstore-utils/es-gencert-cli:latest create-user -username admin -ca-certificate /tmp/ca/ca.crt -ca-key /tmp/ca/ca.key -out /tmp/user-admin - docker run --rm --user root --volume "$PWD/certs:/tmp" docker.eventstore.com/eventstore-utils/es-gencert-cli:latest create-user -username invalid -ca-certificate /tmp/ca/ca.crt -ca-key /tmp/ca/ca.key -out /tmp/user-invalid - - name: Set permissions on certificates - run: | - sudo chown -R $USER:$USER certs - sudo chmod -R 755 certs - - name: Upload certificates - uses: actions/upload-artifact@v4 - with: - name: certs - path: certs - - test: - needs: generate-certificates - timeout-minutes: 20 - strategy: - fail-fast: false - matrix: - framework: [ net6.0, net7.0, net8.0 ] - os: [ ubuntu-latest, windows-latest ] - configuration: [ release ] - runs-on: ${{ matrix.os }} - name: test/EventStore.Client/${{ matrix.os }}/${{ matrix.framework }} - steps: - - name: Checkout - uses: actions/checkout@v3 - - shell: bash - run: | - git fetch --prune --unshallow - - name: Install dotnet SDKs - uses: actions/setup-dotnet@v3 - with: - dotnet-version: | - 6.0.x - 7.0.x - 8.0.x - - name: Compile - shell: bash - run: | - dotnet build --configuration ${{ matrix.configuration }} --framework ${{ matrix.framework }} src/EventStore.Client - - name: Download certificates - uses: actions/download-artifact@v4 - with: - name: certs - path: certs - - name: Run Tests (Linux) - if: runner.os == 'Linux' - shell: bash - run: | - dotnet test --configuration ${{ matrix.configuration }} --blame \ - --logger:"GitHubActions;report-warnings=false" --logger:"console;verbosity=normal" \ - --framework ${{ matrix.framework }} \ - test/EventStore.Client.Tests - - name: Run Tests (Windows) - if: runner.os == 'Windows' - shell: pwsh - run: | - dotnet test --configuration ${{ matrix.configuration }} --blame ` - --logger:"GitHubActions;report-warnings=false" --logger:"console;verbosity=normal" ` - --framework ${{ matrix.framework }} ` - test/EventStore.Client.Tests - - publish: - timeout-minutes: 5 - needs: [ vulnerability-scan, test, build-samples ] - runs-on: ubuntu-latest - name: publish - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Get Version - id: get_version - run: | - echo "branch=${GITHUB_REF:10}" >> $GITHUB_OUTPUT - dotnet nuget list source - dotnet tool restore - version=$(dotnet tool run minver -- --tag-prefix=v) - echo "version=${version}" >> $GITHUB_OUTPUT - - shell: bash - run: | - git fetch --prune --unshallow - - name: Install dotnet SDKs - uses: actions/setup-dotnet@v3 - with: - dotnet-version: | - 6.0.x - 7.0.x - 8.0.x - - name: Dotnet Pack - shell: bash - run: | - mkdir -p packages - dotnet pack /p:Version=${{ steps.get_version.outputs.version }} --configuration=Release \ - /p:PublishDir=./packages \ - /p:NoWarn=NU5105 \ - /p:RepositoryUrl=https://github.com/EventStore/EventStore-Client-Dotnet \ - /p:RepositoryType=git - - name: Publish Artifacts - uses: actions/upload-artifact@v4 - with: - path: packages - name: nuget-packages - - name: Dotnet Push to Github Packages - shell: bash - if: github.event_name == 'push' - run: | - dotnet tool restore - find . -name "*.nupkg" | xargs -n1 dotnet nuget push --api-key=${{ secrets.github_token }} --source https://nuget.pkg.github.com/EventStore/index.json --skip-duplicate - - name: Dotnet Push to Nuget.org - shell: bash - if: contains(steps.get_version.outputs.branch, 'v') - run: | - dotnet nuget list source - dotnet tool restore - find . -name "*.nupkg" | xargs -n1 dotnet nuget push --api-key=${{ secrets.nuget_key }} --source https://api.nuget.org/v3/index.json --skip-duplicate +#name: Publish +# +#on: +# pull_request: +# push: +# branches: +# - master +# tags: +# - v* +# +#jobs: +# vulnerability-scan: +# timeout-minutes: 10 +# strategy: +# fail-fast: false +# matrix: +# framework: [ net8.0, net9.0 ] +# os: [ ubuntu-latest, windows-latest ] +# runs-on: ${{ matrix.os }} +# name: scan-vulnerabilities/${{ matrix.os }}/${{ matrix.framework }} +# steps: +# - name: Checkout +# uses: actions/checkout@v3 +# - name: Install dotnet SDKs +# uses: actions/setup-dotnet@v3 +# with: +# dotnet-version: | +# 8.0.x +# 9.0.x +# - name: Scan for Vulnerabilities +# shell: bash +# run: | +# dotnet nuget list source +# dotnet restore ./src/Kurrent.Client/Kurrent.Client.csproj +# dotnet restore ./test/Kurrent.Client.Tests/Kurrent.Client.Tests.csproj +# dotnet list package --vulnerable --include-transitive --framework ${{ matrix.framework }} | tee vulnerabilities.txt +# ! cat vulnerabilities.txt | grep -q "has the following vulnerable packages" +# +# build-samples: +# timeout-minutes: 5 +# name: build-samples/${{ matrix.framework }} +# runs-on: ubuntu-latest +# strategy: +# fail-fast: false +# matrix: +# framework: [ net8.0, net9.0 ] +# services: +# esdb: +# image: docker.eventstore.com/eventstore-ce/eventstoredb-ce:lts +# env: +# EVENTSTORE_INSECURE: true +# EVENTSTORE_MEM_DB: false +# EVENTSTORE_RUN_PROJECTIONS: all +# EVENTSTORE_START_STANDARD_PROJECTIONS: true +# ports: +# - 2113:2113 +# options: --health-cmd "exit 0" +# steps: +# - name: Checkout +# uses: actions/checkout@v3 +# - name: Install dotnet SDKs +# uses: actions/setup-dotnet@v3 +# with: +# dotnet-version: | +# 8.0.x +# 9.0.x +# - name: Compile +# shell: bash +# run: | +# dotnet build samples +# - name: Run +# shell: bash +# run: | +# find samples/ -type f -iname "*.csproj" -print0 | xargs -0L1 dotnet run --framework ${{ matrix.framework }} --project +# +# generate-certificates: +# runs-on: ubuntu-latest +# steps: +# - name: Checkout code +# uses: actions/checkout@v4 +# - name: Generate certificates +# run: | +# mkdir -p certs +# docker run --rm --user root --volume "$PWD/certs:/tmp" docker.eventstore.com/eventstore-utils/es-gencert-cli:latest create-ca -out /tmp/ca +# docker run --rm --user root --volume "$PWD/certs:/tmp" docker.eventstore.com/eventstore-utils/es-gencert-cli:latest create-node -ca-certificate /tmp/ca/ca.crt -ca-key /tmp/ca/ca.key -out /tmp/node -ip-addresses 127.0.0.1 -dns-names localhost +# docker run --rm --user root --volume "$PWD/certs:/tmp" docker.eventstore.com/eventstore-utils/es-gencert-cli:latest create-user -username admin -ca-certificate /tmp/ca/ca.crt -ca-key /tmp/ca/ca.key -out /tmp/user-admin +# docker run --rm --user root --volume "$PWD/certs:/tmp" docker.eventstore.com/eventstore-utils/es-gencert-cli:latest create-user -username invalid -ca-certificate /tmp/ca/ca.crt -ca-key /tmp/ca/ca.key -out /tmp/user-invalid +# - name: Set permissions on certificates +# run: | +# sudo chown -R $USER:$USER certs +# sudo chmod -R 755 certs +# - name: Upload certificates +# uses: actions/upload-artifact@v4 +# with: +# name: certs +# path: certs +# +# test: +# needs: generate-certificates +# timeout-minutes: 10 +# strategy: +# fail-fast: false +# matrix: +# framework: [ net8.0, net9.0 ] +# os: [ ubuntu-latest, windows-latest ] +# configuration: [ release ] +# test: [ Streams, PersistentSubscriptions, Operations, ProjectionManagement, UserManagement, Security, Misc ] +# runs-on: ${{ matrix.os }} +# name: ${{ matrix.test }} (${{ matrix.os }}, ${{ matrix.framework }}) +# steps: +# - name: Checkout +# uses: actions/checkout@v3 +# - shell: bash +# run: | +# git fetch --prune --unshallow +# - name: Install dotnet SDKs +# uses: actions/setup-dotnet@v3 +# with: +# dotnet-version: | +# 8.0.x +# 9.0.x +# - name: Compile +# shell: bash +# run: | +# dotnet build --configuration ${{ matrix.configuration }} --framework ${{ matrix.framework }} src/Kurrent.Client +# - name: Download certificates +# uses: actions/download-artifact@v4 +# with: +# name: certs +# path: certs +# - name: Run Tests (Linux) +# if: runner.os == 'Linux' +# shell: bash +# run: | +# dotnet test --configuration ${{ matrix.configuration }} --blame \ +# --logger:"GitHubActions;report-warnings=false" --logger:"console;verbosity=normal" \ +# --framework ${{ matrix.framework }} \ +# --filter "Category=Target:${{ matrix.test }}" \ +# test/Kurrent.Client.Tests +# - name: Run Tests (Windows) +# if: runner.os == 'Windows' +# shell: pwsh +# run: | +# dotnet test --configuration ${{ matrix.configuration }} --blame ` +# --logger:"GitHubActions;report-warnings=false" --logger:"console;verbosity=normal" ` +# --framework ${{ matrix.framework }} ` +# --filter "Category=Target:${{ matrix.test }}" ` +# test/Kurrent.Client.Tests +# +# publish: +# timeout-minutes: 5 +# needs: [ vulnerability-scan, test, build-samples ] +# runs-on: ubuntu-latest +# name: publish +# steps: +# - name: Checkout +# uses: actions/checkout@v3 +# - name: Get Version +# id: get_version +# run: | +# echo "branch=${GITHUB_REF:10}" >> $GITHUB_OUTPUT +# dotnet nuget list source +# dotnet tool restore +# version=$(dotnet tool run minver -- --tag-prefix=v) +# echo "version=${version}" >> $GITHUB_OUTPUT +# - shell: bash +# run: | +# git fetch --prune --unshallow +# - name: Install dotnet SDKs +# uses: actions/setup-dotnet@v3 +# with: +# dotnet-version: | +# 8.0.x +# 9.0.x +# - name: Dotnet Pack +# shell: bash +# run: | +# mkdir -p packages +# dotnet pack /p:Version=${{ steps.get_version.outputs.version }} --configuration=Release \ +# /p:PublishDir=./packages \ +# /p:NoWarn=NU5105 \ +# /p:RepositoryUrl=https://github.com/EventStore/EventStore-Client-Dotnet \ +# /p:RepositoryType=git +# - name: Publish Artifacts +# uses: actions/upload-artifact@v4 +# with: +# path: packages +# name: nuget-packages +# - name: Dotnet Push to Github Packages +# shell: bash +# if: github.event_name == 'push' +# run: | +# dotnet tool restore +# find . -name "*.nupkg" | xargs -n1 dotnet nuget push --api-key=${{ secrets.github_token }} --source https://nuget.pkg.github.com/EventStore/index.json --skip-duplicate +# - name: Dotnet Push to Nuget.org +# shell: bash +# if: contains(steps.get_version.outputs.branch, 'v') +# run: | +# dotnet nuget list source +# dotnet tool restore +# find . -name "*.nupkg" | xargs -n1 dotnet nuget push --api-key=${{ secrets.nuget_key }} --source https://api.nuget.org/v3/index.json --skip-duplicate diff --git a/Directory.Build.props b/Directory.Build.props index dd2dd9339..a22d9632a 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,11 +1,10 @@ - net48;net6.0;net7.0;net8.0 + net48;net8.0;net9.0 true enable enable true - true preview Debug @@ -13,8 +12,6 @@ pdbonly true - 2.60.0 - 2.60.0 diff --git a/EventStore.Client.sln b/EventStore.Client.sln deleted file mode 100644 index 72ec92f54..000000000 --- a/EventStore.Client.sln +++ /dev/null @@ -1,127 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26124.0 -MinimumVisualStudioVersion = 15.0.26124.0 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EA59C1CB-16DA-4F68-AF8A-642A969B4CF8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.UserManagement", "src\EventStore.Client.UserManagement\EventStore.Client.UserManagement.csproj", "{D3744A86-DD35-4104-AAEE-84B79062C4A2}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.Streams", "src\EventStore.Client.Streams\EventStore.Client.Streams.csproj", "{362C0CF9-81C9-400F-94C7-A8B190ECE94A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.Operations", "src\EventStore.Client.Operations\EventStore.Client.Operations.csproj", "{6EFB980F-C72C-40F1-9232-479BE5617580}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.ProjectionManagement", "src\EventStore.Client.ProjectionManagement\EventStore.Client.ProjectionManagement.csproj", "{B275EF4B-80D3-4205-9C7A-337A2A2BD99C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.PersistentSubscriptions", "src\EventStore.Client.PersistentSubscriptions\EventStore.Client.PersistentSubscriptions.csproj", "{66FDEE78-836E-49F0-A4DD-BF7539C34E54}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client", "src\EventStore.Client\EventStore.Client.csproj", "{8853D875-4A8E-450B-A1BE-9CEF8BEDABC3}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{C51F2C69-45A9-4D0D-A708-4FC319D5D340}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.ProjectionManagement.Tests", "test\EventStore.Client.ProjectionManagement.Tests\EventStore.Client.ProjectionManagement.Tests.csproj", "{8F8548D6-694C-4BAE-9EF3-A020140E04C7}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.Operations.Tests", "test\EventStore.Client.Operations.Tests\EventStore.Client.Operations.Tests.csproj", "{4BA2E05E-6B45-47C3-9001-8B039244ECA9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.Streams.Tests", "test\EventStore.Client.Streams.Tests\EventStore.Client.Streams.Tests.csproj", "{082C77F5-4FF5-41D4-A1F1-710F05956E1C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.Tests", "test\EventStore.Client.Tests\EventStore.Client.Tests.csproj", "{FC829F1B-43AD-4C96-9002-23D04BBA3AF3}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.PersistentSubscriptions.Tests", "test\EventStore.Client.PersistentSubscriptions.Tests\EventStore.Client.PersistentSubscriptions.Tests.csproj", "{6CEB731F-72E1-461F-A6B3-54DBF3FD786C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.UserManagement.Tests", "test\EventStore.Client.UserManagement.Tests\EventStore.Client.UserManagement.Tests.csproj", "{22634CEE-4F7B-4679-A48D-38A2A8580ECA}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.Tests.Common", "test\EventStore.Client.Tests.Common\EventStore.Client.Tests.Common.csproj", "{E326832D-DE52-4DE4-9E54-C800908B75F3}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.Extensions.OpenTelemetry", "src\EventStore.Client.Extensions.OpenTelemetry\EventStore.Client.Extensions.OpenTelemetry.csproj", "{3723933C-585A-49BE-98E8-52D3FAD904CE}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.Plugins.Tests", "test\EventStore.Client.Plugins.Tests\EventStore.Client.Plugins.Tests.csproj", "{7D929D45-F1D9-462B-BE49-84BEC11D5039}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D3744A86-DD35-4104-AAEE-84B79062C4A2}.Debug|x64.ActiveCfg = Debug|Any CPU - {D3744A86-DD35-4104-AAEE-84B79062C4A2}.Debug|x64.Build.0 = Debug|Any CPU - {D3744A86-DD35-4104-AAEE-84B79062C4A2}.Release|x64.ActiveCfg = Release|Any CPU - {D3744A86-DD35-4104-AAEE-84B79062C4A2}.Release|x64.Build.0 = Release|Any CPU - {362C0CF9-81C9-400F-94C7-A8B190ECE94A}.Debug|x64.ActiveCfg = Debug|Any CPU - {362C0CF9-81C9-400F-94C7-A8B190ECE94A}.Debug|x64.Build.0 = Debug|Any CPU - {362C0CF9-81C9-400F-94C7-A8B190ECE94A}.Release|x64.ActiveCfg = Release|Any CPU - {362C0CF9-81C9-400F-94C7-A8B190ECE94A}.Release|x64.Build.0 = Release|Any CPU - {6EFB980F-C72C-40F1-9232-479BE5617580}.Debug|x64.ActiveCfg = Debug|Any CPU - {6EFB980F-C72C-40F1-9232-479BE5617580}.Debug|x64.Build.0 = Debug|Any CPU - {6EFB980F-C72C-40F1-9232-479BE5617580}.Release|x64.ActiveCfg = Release|Any CPU - {6EFB980F-C72C-40F1-9232-479BE5617580}.Release|x64.Build.0 = Release|Any CPU - {B275EF4B-80D3-4205-9C7A-337A2A2BD99C}.Debug|x64.ActiveCfg = Debug|Any CPU - {B275EF4B-80D3-4205-9C7A-337A2A2BD99C}.Debug|x64.Build.0 = Debug|Any CPU - {B275EF4B-80D3-4205-9C7A-337A2A2BD99C}.Release|x64.ActiveCfg = Release|Any CPU - {B275EF4B-80D3-4205-9C7A-337A2A2BD99C}.Release|x64.Build.0 = Release|Any CPU - {66FDEE78-836E-49F0-A4DD-BF7539C34E54}.Debug|x64.ActiveCfg = Debug|Any CPU - {66FDEE78-836E-49F0-A4DD-BF7539C34E54}.Debug|x64.Build.0 = Debug|Any CPU - {66FDEE78-836E-49F0-A4DD-BF7539C34E54}.Release|x64.ActiveCfg = Release|Any CPU - {66FDEE78-836E-49F0-A4DD-BF7539C34E54}.Release|x64.Build.0 = Release|Any CPU - {8853D875-4A8E-450B-A1BE-9CEF8BEDABC3}.Debug|x64.ActiveCfg = Debug|Any CPU - {8853D875-4A8E-450B-A1BE-9CEF8BEDABC3}.Debug|x64.Build.0 = Debug|Any CPU - {8853D875-4A8E-450B-A1BE-9CEF8BEDABC3}.Release|x64.ActiveCfg = Release|Any CPU - {8853D875-4A8E-450B-A1BE-9CEF8BEDABC3}.Release|x64.Build.0 = Release|Any CPU - {8F8548D6-694C-4BAE-9EF3-A020140E04C7}.Debug|x64.ActiveCfg = Debug|Any CPU - {8F8548D6-694C-4BAE-9EF3-A020140E04C7}.Debug|x64.Build.0 = Debug|Any CPU - {8F8548D6-694C-4BAE-9EF3-A020140E04C7}.Release|x64.ActiveCfg = Release|Any CPU - {8F8548D6-694C-4BAE-9EF3-A020140E04C7}.Release|x64.Build.0 = Release|Any CPU - {4BA2E05E-6B45-47C3-9001-8B039244ECA9}.Debug|x64.ActiveCfg = Debug|Any CPU - {4BA2E05E-6B45-47C3-9001-8B039244ECA9}.Debug|x64.Build.0 = Debug|Any CPU - {4BA2E05E-6B45-47C3-9001-8B039244ECA9}.Release|x64.ActiveCfg = Release|Any CPU - {4BA2E05E-6B45-47C3-9001-8B039244ECA9}.Release|x64.Build.0 = Release|Any CPU - {082C77F5-4FF5-41D4-A1F1-710F05956E1C}.Debug|x64.ActiveCfg = Debug|Any CPU - {082C77F5-4FF5-41D4-A1F1-710F05956E1C}.Debug|x64.Build.0 = Debug|Any CPU - {082C77F5-4FF5-41D4-A1F1-710F05956E1C}.Release|x64.ActiveCfg = Release|Any CPU - {082C77F5-4FF5-41D4-A1F1-710F05956E1C}.Release|x64.Build.0 = Release|Any CPU - {FC829F1B-43AD-4C96-9002-23D04BBA3AF3}.Debug|x64.ActiveCfg = Debug|Any CPU - {FC829F1B-43AD-4C96-9002-23D04BBA3AF3}.Debug|x64.Build.0 = Debug|Any CPU - {FC829F1B-43AD-4C96-9002-23D04BBA3AF3}.Release|x64.ActiveCfg = Release|Any CPU - {FC829F1B-43AD-4C96-9002-23D04BBA3AF3}.Release|x64.Build.0 = Release|Any CPU - {6CEB731F-72E1-461F-A6B3-54DBF3FD786C}.Debug|x64.ActiveCfg = Debug|Any CPU - {6CEB731F-72E1-461F-A6B3-54DBF3FD786C}.Debug|x64.Build.0 = Debug|Any CPU - {6CEB731F-72E1-461F-A6B3-54DBF3FD786C}.Release|x64.ActiveCfg = Release|Any CPU - {6CEB731F-72E1-461F-A6B3-54DBF3FD786C}.Release|x64.Build.0 = Release|Any CPU - {22634CEE-4F7B-4679-A48D-38A2A8580ECA}.Debug|x64.ActiveCfg = Debug|Any CPU - {22634CEE-4F7B-4679-A48D-38A2A8580ECA}.Debug|x64.Build.0 = Debug|Any CPU - {22634CEE-4F7B-4679-A48D-38A2A8580ECA}.Release|x64.ActiveCfg = Release|Any CPU - {22634CEE-4F7B-4679-A48D-38A2A8580ECA}.Release|x64.Build.0 = Release|Any CPU - {E326832D-DE52-4DE4-9E54-C800908B75F3}.Debug|x64.ActiveCfg = Debug|Any CPU - {E326832D-DE52-4DE4-9E54-C800908B75F3}.Debug|x64.Build.0 = Debug|Any CPU - {E326832D-DE52-4DE4-9E54-C800908B75F3}.Release|x64.ActiveCfg = Release|Any CPU - {E326832D-DE52-4DE4-9E54-C800908B75F3}.Release|x64.Build.0 = Release|Any CPU - {3723933C-585A-49BE-98E8-52D3FAD904CE}.Debug|x64.ActiveCfg = Debug|Any CPU - {3723933C-585A-49BE-98E8-52D3FAD904CE}.Debug|x64.Build.0 = Debug|Any CPU - {3723933C-585A-49BE-98E8-52D3FAD904CE}.Release|x64.ActiveCfg = Release|Any CPU - {3723933C-585A-49BE-98E8-52D3FAD904CE}.Release|x64.Build.0 = Release|Any CPU - {7D929D45-F1D9-462B-BE49-84BEC11D5039}.Debug|x64.ActiveCfg = Debug|Any CPU - {7D929D45-F1D9-462B-BE49-84BEC11D5039}.Debug|x64.Build.0 = Debug|Any CPU - {7D929D45-F1D9-462B-BE49-84BEC11D5039}.Release|x64.ActiveCfg = Release|Any CPU - {7D929D45-F1D9-462B-BE49-84BEC11D5039}.Release|x64.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {D3744A86-DD35-4104-AAEE-84B79062C4A2} = {EA59C1CB-16DA-4F68-AF8A-642A969B4CF8} - {362C0CF9-81C9-400F-94C7-A8B190ECE94A} = {EA59C1CB-16DA-4F68-AF8A-642A969B4CF8} - {6EFB980F-C72C-40F1-9232-479BE5617580} = {EA59C1CB-16DA-4F68-AF8A-642A969B4CF8} - {B275EF4B-80D3-4205-9C7A-337A2A2BD99C} = {EA59C1CB-16DA-4F68-AF8A-642A969B4CF8} - {66FDEE78-836E-49F0-A4DD-BF7539C34E54} = {EA59C1CB-16DA-4F68-AF8A-642A969B4CF8} - {8853D875-4A8E-450B-A1BE-9CEF8BEDABC3} = {EA59C1CB-16DA-4F68-AF8A-642A969B4CF8} - {8F8548D6-694C-4BAE-9EF3-A020140E04C7} = {C51F2C69-45A9-4D0D-A708-4FC319D5D340} - {4BA2E05E-6B45-47C3-9001-8B039244ECA9} = {C51F2C69-45A9-4D0D-A708-4FC319D5D340} - {082C77F5-4FF5-41D4-A1F1-710F05956E1C} = {C51F2C69-45A9-4D0D-A708-4FC319D5D340} - {FC829F1B-43AD-4C96-9002-23D04BBA3AF3} = {C51F2C69-45A9-4D0D-A708-4FC319D5D340} - {6CEB731F-72E1-461F-A6B3-54DBF3FD786C} = {C51F2C69-45A9-4D0D-A708-4FC319D5D340} - {22634CEE-4F7B-4679-A48D-38A2A8580ECA} = {C51F2C69-45A9-4D0D-A708-4FC319D5D340} - {E326832D-DE52-4DE4-9E54-C800908B75F3} = {C51F2C69-45A9-4D0D-A708-4FC319D5D340} - {3723933C-585A-49BE-98E8-52D3FAD904CE} = {EA59C1CB-16DA-4F68-AF8A-642A969B4CF8} - {7D929D45-F1D9-462B-BE49-84BEC11D5039} = {C51F2C69-45A9-4D0D-A708-4FC319D5D340} - EndGlobalSection -EndGlobal diff --git a/Kurrent.Client.sln b/Kurrent.Client.sln new file mode 100644 index 000000000..00544398a --- /dev/null +++ b/Kurrent.Client.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EA59C1CB-16DA-4F68-AF8A-642A969B4CF8}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{C51F2C69-45A9-4D0D-A708-4FC319D5D340}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kurrent.Client.Tests", "test\Kurrent.Client.Tests\Kurrent.Client.Tests.csproj", "{FC829F1B-43AD-4C96-9002-23D04BBA3AF3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kurrent.Client", "src\Kurrent.Client\Kurrent.Client.csproj", "{762EECAA-122E-4B0C-BC50-5AA4F72CA4E0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kurrent.Client.Tests.Common", "test\Kurrent.Client.Tests.Common\Kurrent.Client.Tests.Common.csproj", "{47BF715B-A0BF-4044-B335-717E56422550}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FC829F1B-43AD-4C96-9002-23D04BBA3AF3}.Debug|x64.ActiveCfg = Debug|Any CPU + {FC829F1B-43AD-4C96-9002-23D04BBA3AF3}.Debug|x64.Build.0 = Debug|Any CPU + {FC829F1B-43AD-4C96-9002-23D04BBA3AF3}.Release|x64.ActiveCfg = Release|Any CPU + {FC829F1B-43AD-4C96-9002-23D04BBA3AF3}.Release|x64.Build.0 = Release|Any CPU + {762EECAA-122E-4B0C-BC50-5AA4F72CA4E0}.Debug|x64.ActiveCfg = Debug|Any CPU + {762EECAA-122E-4B0C-BC50-5AA4F72CA4E0}.Debug|x64.Build.0 = Debug|Any CPU + {762EECAA-122E-4B0C-BC50-5AA4F72CA4E0}.Release|x64.ActiveCfg = Release|Any CPU + {762EECAA-122E-4B0C-BC50-5AA4F72CA4E0}.Release|x64.Build.0 = Release|Any CPU + {47BF715B-A0BF-4044-B335-717E56422550}.Debug|x64.ActiveCfg = Debug|Any CPU + {47BF715B-A0BF-4044-B335-717E56422550}.Debug|x64.Build.0 = Debug|Any CPU + {47BF715B-A0BF-4044-B335-717E56422550}.Release|x64.ActiveCfg = Release|Any CPU + {47BF715B-A0BF-4044-B335-717E56422550}.Release|x64.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {FC829F1B-43AD-4C96-9002-23D04BBA3AF3} = {C51F2C69-45A9-4D0D-A708-4FC319D5D340} + {762EECAA-122E-4B0C-BC50-5AA4F72CA4E0} = {EA59C1CB-16DA-4F68-AF8A-642A969B4CF8} + {47BF715B-A0BF-4044-B335-717E56422550} = {C51F2C69-45A9-4D0D-A708-4FC319D5D340} + EndGlobalSection +EndGlobal diff --git a/EventStore.Client.sln.DotSettings b/Kurrent.Client.sln.DotSettings similarity index 99% rename from EventStore.Client.sln.DotSettings rename to Kurrent.Client.sln.DotSettings index f97c72463..e12ac8bcf 100644 --- a/EventStore.Client.sln.DotSettings +++ b/Kurrent.Client.sln.DotSettings @@ -390,6 +390,7 @@ True True True + True True True True diff --git a/samples/Directory.Build.props b/samples/Directory.Build.props index 54497a508..1ab3aed15 100644 --- a/samples/Directory.Build.props +++ b/samples/Directory.Build.props @@ -1,6 +1,6 @@ - net8.0 + net8.0;net9.0 enable enable true @@ -12,4 +12,4 @@ - \ No newline at end of file + diff --git a/samples/Samples.sln b/samples/Samples.sln index 79c979342..ec2611d7b 100644 --- a/samples/Samples.sln +++ b/samples/Samples.sln @@ -7,10 +7,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "quick-start", "quick-start\ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "client", "client", "{EBB93BBC-42A7-48E4-B1EA-0EA3953D347C}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventStore.Client.Streams", "..\src\EventStore.Client.Streams\EventStore.Client.Streams.csproj", "{A32CE3CB-AB71-45C6-A1B2-CD94BE2D2B28}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventStore.Client", "..\src\EventStore.Client\EventStore.Client.csproj", "{A71A13F7-8480-4E48-B88D-A2364F7C95B6}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "connecting-to-a-cluster", "connecting-to-a-cluster\connecting-to-a-cluster.csproj", "{C4CA324A-450D-4621-82F1-B4ECD18216B6}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "appending-events", "appending-events\appending-events.csproj", "{496D9886-AF65-4579-AECE-2C147B9AF3C1}" @@ -29,17 +25,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "server-side-filtering", "se EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "persistent-subscriptions", "persistent-subscriptions\persistent-subscriptions.csproj", "{A5A5EF0D-1AE4-4647-823D-FA172E8858F2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventStore.Client.PersistentSubscriptions", "..\src\EventStore.Client.PersistentSubscriptions\EventStore.Client.PersistentSubscriptions.csproj", "{7200BB01-A405-45D5-A6E8-A8FA8DE39DA0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventStore.Client.ProjectionManagement", "..\src\EventStore.Client.ProjectionManagement\EventStore.Client.ProjectionManagement.csproj", "{79992D7B-C311-4E8A-856F-896C1EA61042}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "projection-management", "projection-management\projection-management.csproj", "{9DEA2684-C38B-465C-91A6-ED2AB67A4338}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "diagnostics", "diagnostics\diagnostics.csproj", "{546496AD-E355-4C20-930C-30D0FC76D26F}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "user-certificates", "user-certificates\user-certificates.csproj", "{28112410-D02D-427A-9D36-3FE3A6DC6B0D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.Extensions.OpenTelemetry", "..\src\EventStore.Client.Extensions.OpenTelemetry\EventStore.Client.Extensions.OpenTelemetry.csproj", "{29E3F07A-6676-45C1-805C-46BDF6CF325B}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kurrent.Client", "..\src\Kurrent.Client\Kurrent.Client.csproj", "{16F61817-6E46-4F52-879F-E4B92A6A90C6}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -51,14 +43,6 @@ Global {521987E5-4394-4EE0-B217-E3DC9DB0D327}.Debug|Any CPU.Build.0 = Debug|Any CPU {521987E5-4394-4EE0-B217-E3DC9DB0D327}.Release|Any CPU.ActiveCfg = Release|Any CPU {521987E5-4394-4EE0-B217-E3DC9DB0D327}.Release|Any CPU.Build.0 = Release|Any CPU - {A32CE3CB-AB71-45C6-A1B2-CD94BE2D2B28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A32CE3CB-AB71-45C6-A1B2-CD94BE2D2B28}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A32CE3CB-AB71-45C6-A1B2-CD94BE2D2B28}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A32CE3CB-AB71-45C6-A1B2-CD94BE2D2B28}.Release|Any CPU.Build.0 = Release|Any CPU - {A71A13F7-8480-4E48-B88D-A2364F7C95B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A71A13F7-8480-4E48-B88D-A2364F7C95B6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A71A13F7-8480-4E48-B88D-A2364F7C95B6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A71A13F7-8480-4E48-B88D-A2364F7C95B6}.Release|Any CPU.Build.0 = Release|Any CPU {C4CA324A-450D-4621-82F1-B4ECD18216B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C4CA324A-450D-4621-82F1-B4ECD18216B6}.Debug|Any CPU.Build.0 = Debug|Any CPU {C4CA324A-450D-4621-82F1-B4ECD18216B6}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -95,14 +79,6 @@ Global {A5A5EF0D-1AE4-4647-823D-FA172E8858F2}.Debug|Any CPU.Build.0 = Debug|Any CPU {A5A5EF0D-1AE4-4647-823D-FA172E8858F2}.Release|Any CPU.ActiveCfg = Release|Any CPU {A5A5EF0D-1AE4-4647-823D-FA172E8858F2}.Release|Any CPU.Build.0 = Release|Any CPU - {7200BB01-A405-45D5-A6E8-A8FA8DE39DA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7200BB01-A405-45D5-A6E8-A8FA8DE39DA0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7200BB01-A405-45D5-A6E8-A8FA8DE39DA0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7200BB01-A405-45D5-A6E8-A8FA8DE39DA0}.Release|Any CPU.Build.0 = Release|Any CPU - {79992D7B-C311-4E8A-856F-896C1EA61042}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {79992D7B-C311-4E8A-856F-896C1EA61042}.Debug|Any CPU.Build.0 = Debug|Any CPU - {79992D7B-C311-4E8A-856F-896C1EA61042}.Release|Any CPU.ActiveCfg = Release|Any CPU - {79992D7B-C311-4E8A-856F-896C1EA61042}.Release|Any CPU.Build.0 = Release|Any CPU {9DEA2684-C38B-465C-91A6-ED2AB67A4338}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9DEA2684-C38B-465C-91A6-ED2AB67A4338}.Debug|Any CPU.Build.0 = Debug|Any CPU {9DEA2684-C38B-465C-91A6-ED2AB67A4338}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -115,20 +91,16 @@ Global {28112410-D02D-427A-9D36-3FE3A6DC6B0D}.Debug|Any CPU.Build.0 = Debug|Any CPU {28112410-D02D-427A-9D36-3FE3A6DC6B0D}.Release|Any CPU.ActiveCfg = Release|Any CPU {28112410-D02D-427A-9D36-3FE3A6DC6B0D}.Release|Any CPU.Build.0 = Release|Any CPU - {29E3F07A-6676-45C1-805C-46BDF6CF325B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {29E3F07A-6676-45C1-805C-46BDF6CF325B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {29E3F07A-6676-45C1-805C-46BDF6CF325B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {29E3F07A-6676-45C1-805C-46BDF6CF325B}.Release|Any CPU.Build.0 = Release|Any CPU + {16F61817-6E46-4F52-879F-E4B92A6A90C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {16F61817-6E46-4F52-879F-E4B92A6A90C6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {16F61817-6E46-4F52-879F-E4B92A6A90C6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {16F61817-6E46-4F52-879F-E4B92A6A90C6}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {A32CE3CB-AB71-45C6-A1B2-CD94BE2D2B28} = {EBB93BBC-42A7-48E4-B1EA-0EA3953D347C} - {A71A13F7-8480-4E48-B88D-A2364F7C95B6} = {EBB93BBC-42A7-48E4-B1EA-0EA3953D347C} - {7200BB01-A405-45D5-A6E8-A8FA8DE39DA0} = {EBB93BBC-42A7-48E4-B1EA-0EA3953D347C} - {79992D7B-C311-4E8A-856F-896C1EA61042} = {EBB93BBC-42A7-48E4-B1EA-0EA3953D347C} - {29E3F07A-6676-45C1-805C-46BDF6CF325B} = {EBB93BBC-42A7-48E4-B1EA-0EA3953D347C} + {16F61817-6E46-4F52-879F-E4B92A6A90C6} = {EBB93BBC-42A7-48E4-B1EA-0EA3953D347C} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {2E7E3A6C-21DA-4DBD-9EB3-68DFC5CDE48F} diff --git a/samples/Samples.sln.DotSettings b/samples/Samples.sln.DotSettings index c341e4095..06c105615 100644 --- a/samples/Samples.sln.DotSettings +++ b/samples/Samples.sln.DotSettings @@ -390,6 +390,7 @@ True True True + True True True True diff --git a/samples/appending-events/Program.cs b/samples/appending-events/Program.cs index 2e1bb758f..98f12fb1a 100644 --- a/samples/appending-events/Program.cs +++ b/samples/appending-events/Program.cs @@ -1,10 +1,10 @@ #pragma warning disable CS8321 // Local function is declared but never used -var settings = EventStoreClientSettings.Create("esdb://localhost:2113?tls=false"); +var settings = KurrentClientSettings.Create("esdb://localhost:2113?tls=false"); settings.OperationOptions.ThrowOnAppendFailure = false; -await using var client = new EventStoreClient(settings); +await using var client = new KurrentClient(settings); await AppendToStream(client); await AppendWithConcurrencyCheck(client); @@ -13,7 +13,7 @@ return; -static async Task AppendToStream(EventStoreClient client) { +static async Task AppendToStream(KurrentClient client) { #region append-to-stream var eventData = new EventData( @@ -33,7 +33,7 @@ await client.AppendToStreamAsync( #endregion append-to-stream } -static async Task AppendWithSameId(EventStoreClient client) { +static async Task AppendWithSameId(KurrentClient client) { #region append-duplicate-event var eventData = new EventData( @@ -62,7 +62,7 @@ await client.AppendToStreamAsync( #endregion append-duplicate-event } -static async Task AppendWithNoStream(EventStoreClient client) { +static async Task AppendWithNoStream(KurrentClient client) { #region append-with-no-stream var eventDataOne = new EventData( @@ -97,7 +97,7 @@ await client.AppendToStreamAsync( #endregion append-with-no-stream } -static async Task AppendWithConcurrencyCheck(EventStoreClient client) { +static async Task AppendWithConcurrencyCheck(KurrentClient client) { await client.AppendToStreamAsync( "concurrency-stream", StreamRevision.None, @@ -148,7 +148,7 @@ await client.AppendToStreamAsync( #endregion append-with-concurrency-check } -static async Task AppendOverridingUserCredentials(EventStoreClient client, CancellationToken cancellationToken) { +static async Task AppendOverridingUserCredentials(KurrentClient client, CancellationToken cancellationToken) { var eventData = new EventData( Uuid.NewUuid(), "TestEvent", diff --git a/samples/appending-events/appending-events.csproj b/samples/appending-events/appending-events.csproj index fb93d800e..c74c70ae9 100644 --- a/samples/appending-events/appending-events.csproj +++ b/samples/appending-events/appending-events.csproj @@ -3,11 +3,7 @@ Exe appending_events - - - - - + diff --git a/samples/connecting-to-a-cluster/Program.cs b/samples/connecting-to-a-cluster/Program.cs index a31666fc6..01b033c6c 100644 --- a/samples/connecting-to-a-cluster/Program.cs +++ b/samples/connecting-to-a-cluster/Program.cs @@ -1,10 +1,12 @@ -#pragma warning disable CS8321 // Local function is declared but never used +using EventStore.Client; + +#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") + using var client = new KurrentClient( + KurrentClientSettings.Create("esdb://localhost:1114,localhost:2114,localhost:3114") ); #endregion connecting-to-a-cluster @@ -13,8 +15,8 @@ static void ConnectingToACluster() { static void ProvidingDefaultCredentials() { #region providing-default-credentials - using var client = new EventStoreClient( - EventStoreClientSettings.Create("esdb://admin:changeit@localhost:1114,localhost:2114,localhost:3114") + using var client = new KurrentClient( + KurrentClientSettings.Create("esdb://admin:changeit@localhost:1114,localhost:2114,localhost:3114") ); #endregion providing-default-credentials @@ -23,11 +25,11 @@ static void ProvidingDefaultCredentials() { static void ConnectingToAClusterComplex() { #region connecting-to-a-cluster-complex - using var client = new EventStoreClient( - EventStoreClientSettings.Create( + using var client = new KurrentClient( + KurrentClientSettings.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-cluster/connecting-to-a-cluster.csproj b/samples/connecting-to-a-cluster/connecting-to-a-cluster.csproj index 4754bd0e2..f7304d3f3 100644 --- a/samples/connecting-to-a-cluster/connecting-to-a-cluster.csproj +++ b/samples/connecting-to-a-cluster/connecting-to-a-cluster.csproj @@ -3,11 +3,7 @@ Exe connecting_to_a_cluster - - - - - + diff --git a/samples/connecting-to-a-single-node/Program.cs b/samples/connecting-to-a-single-node/Program.cs index f50e1689f..63d0b3e98 100644 --- a/samples/connecting-to-a-single-node/Program.cs +++ b/samples/connecting-to-a-single-node/Program.cs @@ -1,11 +1,12 @@ using connecting_to_a_single_node; +using EventStore.Client; #pragma warning disable CS8321 // Local function is declared but never used static void SimpleConnection() { #region creating-simple-connection - using var client = new EventStoreClient(EventStoreClientSettings.Create("esdb://localhost:2113")); + using var client = new KurrentClient(KurrentClientSettings.Create("esdb://localhost:2113")); #endregion creating-simple-connection } @@ -13,7 +14,7 @@ static void SimpleConnection() { static void ProvidingDefaultCredentials() { #region providing-default-credentials - using var client = new EventStoreClient(EventStoreClientSettings.Create("esdb://admin:changeit@localhost:2113")); + using var client = new KurrentClient(KurrentClientSettings.Create("esdb://admin:changeit@localhost:2113")); #endregion providing-default-credentials } @@ -21,8 +22,8 @@ static void ProvidingDefaultCredentials() { static void SpecifyingAConnectionName() { #region setting-the-connection-name - using var client = new EventStoreClient( - EventStoreClientSettings.Create("esdb://admin:changeit@localhost:2113?ConnectionName=SomeConnection") + using var client = new KurrentClient( + KurrentClientSettings.Create("esdb://admin:changeit@localhost:2113?ConnectionName=SomeConnection") ); #endregion setting-the-connection-name @@ -31,8 +32,8 @@ static void SpecifyingAConnectionName() { static void OverridingTheTimeout() { #region overriding-timeout - using var client = new EventStoreClient( - EventStoreClientSettings.Create($"esdb://admin:changeit@localhost:2113?OperationTimeout=30000") + using var client = new KurrentClient( + KurrentClientSettings.Create($"esdb://admin:changeit@localhost:2113?OperationTimeout=30000") ); #endregion overriding-timeout @@ -41,8 +42,8 @@ static void OverridingTheTimeout() { static void CombiningSettings() { #region overriding-timeout - using var client = new EventStoreClient( - EventStoreClientSettings.Create( + using var client = new KurrentClient( + KurrentClientSettings.Create( $"esdb://admin:changeit@localhost:2113?ConnectionName=SomeConnection&OperationTimeout=30000" ) ); @@ -53,7 +54,7 @@ static void CombiningSettings() { static void CreatingAnInterceptor() { #region adding-an-interceptor - var settings = new EventStoreClientSettings { + var settings = new KurrentClientSettings { Interceptors = new[] { new DemoInterceptor() }, ConnectivitySettings = { Address = new Uri("https://localhost:2113") @@ -62,13 +63,13 @@ static void CreatingAnInterceptor() { #endregion adding-an-interceptor - var client = new EventStoreClient(settings); + var client = new KurrentClient(settings); } static void CustomHttpMessageHandler() { #region adding-an-custom-http-message-handler - var settings = new EventStoreClientSettings { + var settings = new KurrentClientSettings { CreateHttpMessageHandler = () => new HttpClientHandler { ServerCertificateCustomValidationCallback = @@ -81,5 +82,5 @@ static void CustomHttpMessageHandler() { #endregion adding-an-custom-http-message-handler - var client = new EventStoreClient(settings); -} \ No newline at end of file + var client = new KurrentClient(settings); +} 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 4ef794ee4..97609c80a 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 @@ -2,11 +2,7 @@ Exe - - - - - + diff --git a/samples/diagnostics/Program.cs b/samples/diagnostics/Program.cs index 5804be7a4..86f9a6e3a 100644 --- a/samples/diagnostics/Program.cs +++ b/samples/diagnostics/Program.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using EventStore.Client; using EventStore.Client.Extensions.OpenTelemetry; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -23,17 +24,17 @@ dotnet add package OpenTelemetry.Extensions.Hosting # endregion import-required-packages **/ -var settings = EventStoreClientSettings.Create("esdb://localhost:2113?tls=false"); +var settings = KurrentClientSettings.Create("esdb://localhost:2113?tls=false"); settings.OperationOptions.ThrowOnAppendFailure = false; -await using var client = new EventStoreClient(settings); +await using var client = new KurrentClient(settings); await TraceAppendToStream(client); return; -static async Task TraceAppendToStream(EventStoreClient client) { +static async Task TraceAppendToStream(KurrentClient client) { const string serviceName = "sample"; var host = Host.CreateDefaultBuilder() @@ -76,7 +77,7 @@ static void ConfigureTracerProviderBuilder(TracerProviderBuilder tracerProviderB #region register-instrumentation tracerProviderBuilder - .AddEventStoreClientInstrumentation(); + .AddKurrentClientInstrumentation(); #endregion register-instrumentation diff --git a/samples/diagnostics/diagnostics.csproj b/samples/diagnostics/diagnostics.csproj index 1763a9d9e..56bd7c49c 100644 --- a/samples/diagnostics/diagnostics.csproj +++ b/samples/diagnostics/diagnostics.csproj @@ -5,18 +5,14 @@ - - - + + + - + - - - - - + diff --git a/samples/persistent-subscriptions/Program.cs b/samples/persistent-subscriptions/Program.cs index e1e9387c6..6d07b7947 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&tlsVerifyCert=false") +await using var client = new KurrentPersistentSubscriptionsClient( + KurrentClientSettings.Create("esdb://localhost:2113?tls=false&tlsVerifyCert=false") ); await DeletePersistentSubscription(client); @@ -36,7 +36,7 @@ return; -static async Task CreatePersistentSubscription(EventStorePersistentSubscriptionsClient client) { +static async Task CreatePersistentSubscription(KurrentPersistentSubscriptionsClient client) { #region create-persistent-subscription-to-stream var userCredentials = new UserCredentials("admin", "changeit"); @@ -54,7 +54,7 @@ await client.CreateToStreamAsync( #endregion create-persistent-subscription-to-stream } -static async Task ConnectToPersistentSubscriptionToStream(EventStorePersistentSubscriptionsClient client, +static async Task ConnectToPersistentSubscriptionToStream(KurrentPersistentSubscriptionsClient client, CancellationToken ct) { #region subscribe-to-persistent-subscription-to-stream @@ -77,7 +77,7 @@ static async Task ConnectToPersistentSubscriptionToStream(EventStorePersistentSu #endregion subscribe-to-persistent-subscription-to-stream } -static async Task CreatePersistentSubscriptionToAll(EventStorePersistentSubscriptionsClient client) { +static async Task CreatePersistentSubscriptionToAll(KurrentPersistentSubscriptionsClient client) { #region create-persistent-subscription-to-all var userCredentials = new UserCredentials("admin", "changeit"); @@ -96,7 +96,7 @@ await client.CreateToAllAsync( #endregion create-persistent-subscription-to-all } -static async Task ConnectToPersistentSubscriptionToAll(EventStorePersistentSubscriptionsClient client, +static async Task ConnectToPersistentSubscriptionToAll(KurrentPersistentSubscriptionsClient client, CancellationToken ct) { #region subscribe-to-persistent-subscription-to-all @@ -118,7 +118,7 @@ static async Task ConnectToPersistentSubscriptionToAll(EventStorePersistentSubsc #endregion subscribe-to-persistent-subscription-to-all } -static async Task ConnectToPersistentSubscriptionWithManualAcks(EventStorePersistentSubscriptionsClient client, +static async Task ConnectToPersistentSubscriptionWithManualAcks(KurrentPersistentSubscriptionsClient client, CancellationToken ct) { #region subscribe-to-persistent-subscription-with-manual-acks @@ -145,7 +145,7 @@ static async Task ConnectToPersistentSubscriptionWithManualAcks(EventStorePersis #endregion subscribe-to-persistent-subscription-with-manual-acks } -static async Task UpdatePersistentSubscription(EventStorePersistentSubscriptionsClient client) { +static async Task UpdatePersistentSubscription(KurrentPersistentSubscriptionsClient client) { #region update-persistent-subscription var userCredentials = new UserCredentials("admin", "changeit"); @@ -163,7 +163,7 @@ await client.UpdateToStreamAsync( #endregion update-persistent-subscription } -static async Task DeletePersistentSubscription(EventStorePersistentSubscriptionsClient client) { +static async Task DeletePersistentSubscription(KurrentPersistentSubscriptionsClient client) { #region delete-persistent-subscription try { @@ -184,7 +184,7 @@ await client.DeleteToStreamAsync( #endregion delete-persistent-subscription } -static async Task DeletePersistentSubscriptionToAll(EventStorePersistentSubscriptionsClient client) { +static async Task DeletePersistentSubscriptionToAll(KurrentPersistentSubscriptionsClient client) { #region delete-persistent-subscription-to-all try { @@ -204,7 +204,7 @@ await client.DeleteToAllAsync( #endregion delete-persistent-subscription-to-all } -static async Task GetPersistentSubscriptionToStreamInfo(EventStorePersistentSubscriptionsClient client) { +static async Task GetPersistentSubscriptionToStreamInfo(KurrentPersistentSubscriptionsClient client) { #region get-persistent-subscription-to-stream-info var userCredentials = new UserCredentials("admin", "changeit"); @@ -219,7 +219,7 @@ static async Task GetPersistentSubscriptionToStreamInfo(EventStorePersistentSubs #endregion get-persistent-subscription-to-stream-info } -static async Task GetPersistentSubscriptionToAllInfo(EventStorePersistentSubscriptionsClient client) { +static async Task GetPersistentSubscriptionToAllInfo(KurrentPersistentSubscriptionsClient client) { #region get-persistent-subscription-to-all-info var userCredentials = new UserCredentials("admin", "changeit"); @@ -233,7 +233,7 @@ static async Task GetPersistentSubscriptionToAllInfo(EventStorePersistentSubscri #endregion get-persistent-subscription-to-all-info } -static async Task ReplayParkedToStream(EventStorePersistentSubscriptionsClient client) { +static async Task ReplayParkedToStream(KurrentPersistentSubscriptionsClient client) { #region replay-parked-of-persistent-subscription-to-stream var userCredentials = new UserCredentials("admin", "changeit"); @@ -249,7 +249,7 @@ await client.ReplayParkedMessagesToStreamAsync( #endregion persistent-subscription-replay-parked-to-stream } -static async Task ReplayParkedToAll(EventStorePersistentSubscriptionsClient client) { +static async Task ReplayParkedToAll(KurrentPersistentSubscriptionsClient client) { #region replay-parked-of-persistent-subscription-to-all var userCredentials = new UserCredentials("admin", "changeit"); @@ -264,7 +264,7 @@ await client.ReplayParkedMessagesToAllAsync( #endregion replay-parked-of-persistent-subscription-to-all } -static async Task ListPersistentSubscriptionsToStream(EventStorePersistentSubscriptionsClient client) { +static async Task ListPersistentSubscriptionsToStream(KurrentPersistentSubscriptionsClient client) { #region list-persistent-subscriptions-to-stream var userCredentials = new UserCredentials("admin", "changeit"); @@ -281,7 +281,7 @@ static async Task ListPersistentSubscriptionsToStream(EventStorePersistentSubscr #endregion list-persistent-subscriptions-to-stream } -static async Task ListPersistentSubscriptionsToAll(EventStorePersistentSubscriptionsClient client) { +static async Task ListPersistentSubscriptionsToAll(KurrentPersistentSubscriptionsClient client) { #region list-persistent-subscriptions-to-all var userCredentials = new UserCredentials("admin", "changeit"); @@ -295,7 +295,7 @@ static async Task ListPersistentSubscriptionsToAll(EventStorePersistentSubscript #endregion list-persistent-subscriptions-to-all } -static async Task ListAllPersistentSubscriptions(EventStorePersistentSubscriptionsClient client) { +static async Task ListAllPersistentSubscriptions(KurrentPersistentSubscriptionsClient client) { #region list-persistent-subscriptions var userCredentials = new UserCredentials("admin", "changeit"); @@ -309,7 +309,7 @@ static async Task ListAllPersistentSubscriptions(EventStorePersistentSubscriptio #endregion list-persistent-subscriptions } -static async Task RestartPersistentSubscriptionSubsystem(EventStorePersistentSubscriptionsClient client) { +static async Task RestartPersistentSubscriptionSubsystem(KurrentPersistentSubscriptionsClient client) { #region restart-persistent-subscription-subsystem var userCredentials = new UserCredentials("admin", "changeit"); diff --git a/samples/persistent-subscriptions/persistent-subscriptions.csproj b/samples/persistent-subscriptions/persistent-subscriptions.csproj index e845bda8e..e296fca91 100644 --- a/samples/persistent-subscriptions/persistent-subscriptions.csproj +++ b/samples/persistent-subscriptions/persistent-subscriptions.csproj @@ -3,10 +3,7 @@ Exe persistent_subscriptions - - - - + diff --git a/samples/projection-management/Program.cs b/samples/projection-management/Program.cs index 0f3d66b70..478b88b10 100644 --- a/samples/projection-management/Program.cs +++ b/samples/projection-management/Program.cs @@ -64,20 +64,20 @@ return; -static EventStoreProjectionManagementClient ManagementClient(string connection) { +static KurrentProjectionManagementClient ManagementClient(string connection) { #region createClient - var settings = EventStoreClientSettings.Create(connection); + var settings = KurrentClientSettings.Create(connection); settings.ConnectionName = "Projection management client"; settings.DefaultCredentials = new UserCredentials("admin", "changeit"); - var managementClient = new EventStoreProjectionManagementClient(settings); + var managementClient = new KurrentProjectionManagementClient(settings); #endregion createClient return managementClient; } -static async Task RestartSubSystem(EventStoreProjectionManagementClient managementClient) { +static async Task RestartSubSystem(KurrentProjectionManagementClient managementClient) { #region RestartSubSystem await managementClient.RestartSubsystemAsync(); @@ -85,7 +85,7 @@ static async Task RestartSubSystem(EventStoreProjectionManagementClient manageme #endregion RestartSubSystem } -static async Task Disable(EventStoreProjectionManagementClient managementClient) { +static async Task Disable(KurrentProjectionManagementClient managementClient) { #region Disable await managementClient.DisableAsync("$by_category"); @@ -93,7 +93,7 @@ static async Task Disable(EventStoreProjectionManagementClient managementClient) #endregion Disable } -static async Task DisableNotFound(EventStoreProjectionManagementClient managementClient) { +static async Task DisableNotFound(KurrentProjectionManagementClient managementClient) { #region DisableNotFound try { @@ -109,7 +109,7 @@ static async Task DisableNotFound(EventStoreProjectionManagementClient managemen #endregion DisableNotFound } -static async Task Enable(EventStoreProjectionManagementClient managementClient) { +static async Task Enable(KurrentProjectionManagementClient managementClient) { #region Enable await managementClient.EnableAsync("$by_category"); @@ -117,7 +117,7 @@ static async Task Enable(EventStoreProjectionManagementClient managementClient) #endregion Enable } -static async Task EnableNotFound(EventStoreProjectionManagementClient managementClient) { +static async Task EnableNotFound(KurrentProjectionManagementClient managementClient) { #region EnableNotFound try { @@ -133,7 +133,7 @@ static async Task EnableNotFound(EventStoreProjectionManagementClient management #endregion EnableNotFound } -static Task Delete(EventStoreProjectionManagementClient managementClient) { +static Task Delete(KurrentProjectionManagementClient managementClient) { #region Delete // this is not yet available in the .net grpc client @@ -143,7 +143,7 @@ static Task Delete(EventStoreProjectionManagementClient managementClient) { return Task.CompletedTask; } -static async Task Abort(EventStoreProjectionManagementClient managementClient) { +static async Task Abort(KurrentProjectionManagementClient managementClient) { try { var js = "fromAll() .when({$init:function(){return {count:0};},$any:function(s, e){s.count += 1;}}).outputState();"; @@ -165,7 +165,7 @@ static async Task Abort(EventStoreProjectionManagementClient managementClient) { #endregion Abort } -static async Task Abort_NotFound(EventStoreProjectionManagementClient managementClient) { +static async Task Abort_NotFound(KurrentProjectionManagementClient managementClient) { #region Abort_NotFound try { @@ -181,7 +181,7 @@ static async Task Abort_NotFound(EventStoreProjectionManagementClient management #endregion Abort_NotFound } -static async Task Reset(EventStoreProjectionManagementClient managementClient) { +static async Task Reset(KurrentProjectionManagementClient managementClient) { try { var js = "fromAll() .when({$init:function(){return {count:0};},$any:function(s, e){s.count += 1;}}).outputState();"; @@ -203,7 +203,7 @@ static async Task Reset(EventStoreProjectionManagementClient managementClient) { #endregion Reset } -static async Task Reset_NotFound(EventStoreProjectionManagementClient managementClient) { +static async Task Reset_NotFound(KurrentProjectionManagementClient managementClient) { #region Reset_NotFound try { @@ -219,14 +219,14 @@ static async Task Reset_NotFound(EventStoreProjectionManagementClient management #endregion Reset_NotFound } -static async Task CreateOneTime(EventStoreProjectionManagementClient managementClient) { +static async Task CreateOneTime(KurrentProjectionManagementClient 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) { +static async Task CreateContinuous(KurrentProjectionManagementClient managementClient) { #region CreateContinuous const string js = @"fromAll() @@ -248,7 +248,7 @@ static async Task CreateContinuous(EventStoreProjectionManagementClient manageme #endregion CreateContinuous } -static async Task CreateContinuous_Conflict(EventStoreProjectionManagementClient managementClient) { +static async Task CreateContinuous_Conflict(KurrentProjectionManagementClient managementClient) { const string js = @"fromAll() .when({ $init: function() { @@ -281,7 +281,7 @@ static async Task CreateContinuous_Conflict(EventStoreProjectionManagementClient #endregion CreateContinuous_Conflict } -static async Task Update(EventStoreProjectionManagementClient managementClient) { +static async Task Update(KurrentProjectionManagementClient managementClient) { #region Update const string js = @"fromAll() @@ -305,7 +305,7 @@ static async Task Update(EventStoreProjectionManagementClient managementClient) #endregion Update } -static async Task Update_NotFound(EventStoreProjectionManagementClient managementClient) { +static async Task Update_NotFound(KurrentProjectionManagementClient managementClient) { #region Update_NotFound try { @@ -321,7 +321,7 @@ static async Task Update_NotFound(EventStoreProjectionManagementClient managemen #endregion Update_NotFound } -static async Task ListAll(EventStoreProjectionManagementClient managementClient) { +static async Task ListAll(KurrentProjectionManagementClient managementClient) { #region ListAll var details = managementClient.ListAllAsync(); @@ -333,7 +333,7 @@ static async Task ListAll(EventStoreProjectionManagementClient managementClient) #endregion ListAll } -static async Task ListContinuous(EventStoreProjectionManagementClient managementClient) { +static async Task ListContinuous(KurrentProjectionManagementClient managementClient) { #region ListContinuous var details = managementClient.ListContinuousAsync(); @@ -345,7 +345,7 @@ static async Task ListContinuous(EventStoreProjectionManagementClient management #endregion ListContinuous } -static async Task GetStatus(EventStoreProjectionManagementClient managementClient) { +static async Task GetStatus(KurrentProjectionManagementClient managementClient) { const string js = "fromAll().when({$init:function(){return {count:0};},$any:function(s, e){s.count += 1;}}).outputState();"; @@ -362,7 +362,7 @@ static async Task GetStatus(EventStoreProjectionManagementClient managementClien #endregion GetStatus } -static async Task GetState(EventStoreProjectionManagementClient managementClient) { +static async Task GetState(KurrentProjectionManagementClient managementClient) { // will have to wait for the client to be fixed before we import in the doc #region GetState @@ -393,7 +393,7 @@ static async Task DocToString(JsonDocument d) { #endregion GetState } -static async Task GetResult(EventStoreProjectionManagementClient managementClient) { +static async Task GetResult(KurrentProjectionManagementClient managementClient) { #region GetResult const string js = @"fromAll() @@ -433,9 +433,9 @@ static string DocToString(JsonDocument d) { } static async Task Populate(string connection, int numberOfEvents) { - var settings = EventStoreClientSettings.Create(connection); + var settings = KurrentClientSettings.Create(connection); settings.DefaultCredentials = new UserCredentials("admin", "changeit"); - var client = new EventStoreClient(settings); + var client = new KurrentClient(settings); var messages = Enumerable.Range(0, numberOfEvents).Select( number => new EventData( @@ -452,4 +452,4 @@ public class Result { public int count { get; set; } public override string ToString() => $"count= {count}"; -}; \ No newline at end of file +}; diff --git a/samples/projection-management/projection-management.csproj b/samples/projection-management/projection-management.csproj index 3b5b2c3c7..f6a6206aa 100644 --- a/samples/projection-management/projection-management.csproj +++ b/samples/projection-management/projection-management.csproj @@ -2,9 +2,7 @@ projection_management - - - + diff --git a/samples/quick-start/Program.cs b/samples/quick-start/Program.cs index 0cd070137..dd763ae42 100644 --- a/samples/quick-start/Program.cs +++ b/samples/quick-start/Program.cs @@ -7,9 +7,9 @@ const string connectionString = "esdb://admin:changeit@localhost:2113?tls=false&tlsVerifyCert=false"; -var settings = EventStoreClientSettings.Create(connectionString); +var settings = KurrentClientSettings.Create(connectionString); -var client = new EventStoreClient(settings); +var client = new KurrentClient(settings); #endregion createClient @@ -67,4 +67,4 @@ await client.AppendToStreamAsync( 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/quick-start.csproj b/samples/quick-start/quick-start.csproj index b33948026..5fe35463c 100644 --- a/samples/quick-start/quick-start.csproj +++ b/samples/quick-start/quick-start.csproj @@ -2,11 +2,7 @@ quick_start - - - - - + diff --git a/samples/reading-events/Program.cs b/samples/reading-events/Program.cs index 854634da8..751086d5c 100644 --- a/samples/reading-events/Program.cs +++ b/samples/reading-events/Program.cs @@ -1,6 +1,6 @@ #pragma warning disable CS8321 // Local function is declared but never used -await using var client = new EventStoreClient(EventStoreClientSettings.Create("esdb://localhost:2113?tls=false")); +await using var client = new KurrentClient(KurrentClientSettings.Create("esdb://localhost:2113?tls=false")); var events = Enumerable.Range(0, 20) .Select( @@ -21,7 +21,7 @@ await client.AppendToStreamAsync( return; -static async Task ReadFromStream(EventStoreClient client) { +static async Task ReadFromStream(KurrentClient client) { #region read-from-stream var events = client.ReadStreamAsync( @@ -46,7 +46,7 @@ static async Task ReadFromStream(EventStoreClient client) { #endregion } -static async Task ReadFromStreamMessages(EventStoreClient client) { +static async Task ReadFromStreamMessages(KurrentClient client) { #region read-from-stream-messages var streamPosition = StreamPosition.Start; @@ -90,7 +90,7 @@ static async Task ReadFromStreamMessages(EventStoreClient client) { #endregion iterate-stream-messages } -static async Task ReadFromStreamPosition(EventStoreClient client) { +static async Task ReadFromStreamPosition(KurrentClient client) { #region read-from-stream-position var events = client.ReadStreamAsync( @@ -109,7 +109,7 @@ static async Task ReadFromStreamPosition(EventStoreClient client) { #endregion iterate-stream } -static async Task ReadFromStreamPositionCheck(EventStoreClient client) { +static async Task ReadFromStreamPositionCheck(KurrentClient client) { #region checking-for-stream-presence var result = client.ReadStreamAsync( @@ -126,7 +126,7 @@ static async Task ReadFromStreamPositionCheck(EventStoreClient client) { #endregion checking-for-stream-presence } -static async Task ReadFromStreamBackwards(EventStoreClient client) { +static async Task ReadFromStreamBackwards(KurrentClient client) { #region reading-backwards var events = client.ReadStreamAsync( @@ -140,7 +140,7 @@ static async Task ReadFromStreamBackwards(EventStoreClient client) { #endregion reading-backwards } -static async Task ReadFromStreamMessagesBackwards(EventStoreClient client) { +static async Task ReadFromStreamMessagesBackwards(KurrentClient client) { #region read-from-stream-messages-backwards var results = client.ReadStreamAsync( @@ -175,7 +175,7 @@ static async Task ReadFromStreamMessagesBackwards(EventStoreClient client) { #endregion iterate-stream-messages-backwards } -static async Task ReadFromAllStream(EventStoreClient client) { +static async Task ReadFromAllStream(KurrentClient client) { #region read-from-all-stream var events = client.ReadAllAsync(Direction.Forwards, Position.Start); @@ -189,7 +189,7 @@ static async Task ReadFromAllStream(EventStoreClient client) { #endregion read-from-all-stream-iterate } -static async Task ReadFromAllStreamMessages(EventStoreClient client) { +static async Task ReadFromAllStreamMessages(KurrentClient client) { #region read-from-all-stream-messages var position = Position.Start; @@ -216,7 +216,7 @@ static async Task ReadFromAllStreamMessages(EventStoreClient client) { #endregion iterate-all-stream-messages } -static async Task IgnoreSystemEvents(EventStoreClient client) { +static async Task IgnoreSystemEvents(KurrentClient client) { #region ignore-system-events var events = client.ReadAllAsync(Direction.Forwards, Position.Start); @@ -230,7 +230,7 @@ static async Task IgnoreSystemEvents(EventStoreClient client) { #endregion ignore-system-events } -static async Task ReadFromAllStreamBackwards(EventStoreClient client) { +static async Task ReadFromAllStreamBackwards(KurrentClient client) { #region read-from-all-stream-backwards var events = client.ReadAllAsync(Direction.Backwards, Position.End); @@ -244,7 +244,7 @@ static async Task ReadFromAllStreamBackwards(EventStoreClient client) { #endregion read-from-all-stream-iterate } -static async Task ReadFromAllStreamBackwardsMessages(EventStoreClient client) { +static async Task ReadFromAllStreamBackwardsMessages(KurrentClient client) { #region read-from-all-stream-messages-backwards var position = Position.End; @@ -272,7 +272,7 @@ static async Task ReadFromAllStreamBackwardsMessages(EventStoreClient client) { #endregion iterate-all-stream-messages-backwards } -static async Task FilteringOutSystemEvents(EventStoreClient client) { +static async Task FilteringOutSystemEvents(KurrentClient client) { var events = client.ReadAllAsync(Direction.Forwards, Position.Start); await foreach (var e in events) @@ -280,7 +280,7 @@ static async Task FilteringOutSystemEvents(EventStoreClient client) { Console.WriteLine(Encoding.UTF8.GetString(e.Event.Data.ToArray())); } -static void ReadStreamOverridingUserCredentials(EventStoreClient client, CancellationToken cancellationToken) { +static void ReadStreamOverridingUserCredentials(KurrentClient client, CancellationToken cancellationToken) { #region overriding-user-credentials var result = client.ReadStreamAsync( @@ -294,7 +294,7 @@ static void ReadStreamOverridingUserCredentials(EventStoreClient client, Cancell #endregion overriding-user-credentials } -static void ReadAllOverridingUserCredentials(EventStoreClient client, CancellationToken cancellationToken) { +static void ReadAllOverridingUserCredentials(KurrentClient client, CancellationToken cancellationToken) { #region read-all-overriding-user-credentials var result = client.ReadAllAsync( @@ -307,7 +307,7 @@ static void ReadAllOverridingUserCredentials(EventStoreClient client, Cancellati #endregion read-all-overriding-user-credentials } -static void ReadAllResolvingLinkTos(EventStoreClient client, CancellationToken cancellationToken) { +static void ReadAllResolvingLinkTos(KurrentClient client, CancellationToken cancellationToken) { #region read-from-all-stream-resolving-link-Tos var result = client.ReadAllAsync( @@ -318,4 +318,4 @@ static void ReadAllResolvingLinkTos(EventStoreClient client, CancellationToken c ); #endregion read-from-all-stream-resolving-link-Tos -} \ No newline at end of file +} diff --git a/samples/reading-events/reading-events.csproj b/samples/reading-events/reading-events.csproj index 436254ea7..d79ede9fc 100644 --- a/samples/reading-events/reading-events.csproj +++ b/samples/reading-events/reading-events.csproj @@ -2,10 +2,7 @@ reading_events - - - - + - \ No newline at end of file + diff --git a/samples/secure-with-tls/Program.cs b/samples/secure-with-tls/Program.cs index 621ee46b1..b2dcd05bb 100644 --- a/samples/secure-with-tls/Program.cs +++ b/samples/secure-with-tls/Program.cs @@ -6,7 +6,7 @@ Console.WriteLine($"Connecting to EventStoreDB at: {connectionString}"); -await using var client = new EventStoreClient(EventStoreClientSettings.Create(connectionString)); +await using var client = new KurrentClient(KurrentClientSettings.Create(connectionString)); var eventData = new EventData(Uuid.NewUuid(), "some-event", "{\"id\": \"1\" \"value\": \"some value\"}"u8.ToArray()); @@ -48,4 +48,4 @@ } Console.WriteLine($"FAILED! {exception}"); -} \ No newline at end of file +} diff --git a/samples/secure-with-tls/secure-with-tls.csproj b/samples/secure-with-tls/secure-with-tls.csproj index 7dd4b7c03..a11ffdb55 100644 --- a/samples/secure-with-tls/secure-with-tls.csproj +++ b/samples/secure-with-tls/secure-with-tls.csproj @@ -14,8 +14,6 @@ - - - + diff --git a/samples/server-side-filtering/Program.cs b/samples/server-side-filtering/Program.cs index b9e5de8c8..b8641905a 100644 --- a/samples/server-side-filtering/Program.cs +++ b/samples/server-side-filtering/Program.cs @@ -6,7 +6,7 @@ var semaphore = new SemaphoreSlim(eventCount); -await using var client = new EventStoreClient(EventStoreClientSettings.Create("esdb://localhost:2113?tls=false")); +await using var client = new KurrentClient(KurrentClientSettings.Create("esdb://localhost:2113?tls=false")); _ = Task.Run(async () => { await using var subscription = client.SubscribeToAll( @@ -46,7 +46,7 @@ await client.AppendToStreamAsync( return; -static async Task ExcludeSystemEvents(EventStoreClient client) { +static async Task ExcludeSystemEvents(KurrentClient client) { #region exclude-system await using var subscription = client.SubscribeToAll( @@ -63,7 +63,7 @@ static async Task ExcludeSystemEvents(EventStoreClient client) { #endregion exclude-system } -static async Task EventTypePrefix(EventStoreClient client) { +static async Task EventTypePrefix(KurrentClient client) { #region event-type-prefix var filterOptions = new SubscriptionFilterOptions(EventTypeFilter.Prefix("customer-")); @@ -80,7 +80,7 @@ static async Task EventTypePrefix(EventStoreClient client) { } } -static async Task EventTypeRegex(EventStoreClient client) { +static async Task EventTypeRegex(KurrentClient client) { #region event-type-regex var filterOptions = new SubscriptionFilterOptions(EventTypeFilter.RegularExpression("^user|^company")); @@ -97,7 +97,7 @@ static async Task EventTypeRegex(EventStoreClient client) { } } -static async Task StreamPrefix(EventStoreClient client) { +static async Task StreamPrefix(KurrentClient client) { #region stream-prefix var filterOptions = new SubscriptionFilterOptions(StreamFilter.Prefix("user-")); @@ -114,7 +114,7 @@ static async Task StreamPrefix(EventStoreClient client) { } } -static async Task StreamRegex(EventStoreClient client) { +static async Task StreamRegex(KurrentClient client) { #region stream-regex var filterOptions = new SubscriptionFilterOptions(StreamFilter.RegularExpression("^account|^savings")); @@ -131,7 +131,7 @@ static async Task StreamRegex(EventStoreClient client) { } } -static async Task CheckpointCallback(EventStoreClient client) { +static async Task CheckpointCallback(KurrentClient client) { #region checkpoint var filterOptions = new SubscriptionFilterOptions(EventTypeFilter.ExcludeSystemEvents()); @@ -151,7 +151,7 @@ static async Task CheckpointCallback(EventStoreClient client) { #endregion checkpoint } -static async Task CheckpointCallbackWithInterval(EventStoreClient client) { +static async Task CheckpointCallbackWithInterval(KurrentClient client) { #region checkpoint-with-interval var filterOptions = new SubscriptionFilterOptions(EventTypeFilter.ExcludeSystemEvents(), 1000); diff --git a/samples/server-side-filtering/server-side-filtering.csproj b/samples/server-side-filtering/server-side-filtering.csproj index b69b90670..f3a5ffc58 100644 --- a/samples/server-side-filtering/server-side-filtering.csproj +++ b/samples/server-side-filtering/server-side-filtering.csproj @@ -2,11 +2,7 @@ server_side_filtering - - - - - + - \ 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 d4c3f4d59..f66c237ce 100644 --- a/samples/setting-up-dependency-injection/Controllers/EventStoreController.cs +++ b/samples/setting-up-dependency-injection/Controllers/EventStoreController.cs @@ -5,15 +5,15 @@ namespace setting_up_dependency_injection.Controllers { [Route("[controller]")] public class EventStoreController : ControllerBase { #region using-dependency - private readonly EventStoreClient _eventStoreClient; + private readonly KurrentClient _KurrentClient; - public EventStoreController(EventStoreClient eventStoreClient) { - _eventStoreClient = eventStoreClient; + public EventStoreController(KurrentClient KurrentClient) { + _KurrentClient = KurrentClient; } [HttpGet] public IAsyncEnumerable Get() { - return _eventStoreClient.ReadAllAsync(Direction.Forwards, Position.Start); + return _KurrentClient.ReadAllAsync(Direction.Forwards, Position.Start); } #endregion using-dependency } diff --git a/samples/setting-up-dependency-injection/Startup.cs b/samples/setting-up-dependency-injection/Startup.cs index a1d618aff..cb8c9fb94 100644 --- a/samples/setting-up-dependency-injection/Startup.cs +++ b/samples/setting-up-dependency-injection/Startup.cs @@ -10,7 +10,7 @@ public void ConfigureServices(IServiceCollection services) { #region setting-up-dependency - services.AddEventStoreClient("esdb://admin:changeit@localhost:2113?tls=false"); + services.AddKurrentClient("esdb://admin:changeit@localhost:2113?tls=false"); #endregion setting-up-dependency } @@ -22,4 +22,4 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } -} \ No newline at end of file +} 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 0e2adfd05..e4f581a89 100644 --- a/samples/setting-up-dependency-injection/setting-up-dependency-injection.csproj +++ b/samples/setting-up-dependency-injection/setting-up-dependency-injection.csproj @@ -4,9 +4,6 @@ - - - - + - \ No newline at end of file + diff --git a/samples/subscribing-to-streams/Program.cs b/samples/subscribing-to-streams/Program.cs index 90fa29737..01990a17e 100644 --- a/samples/subscribing-to-streams/Program.cs +++ b/samples/subscribing-to-streams/Program.cs @@ -3,7 +3,7 @@ // ReSharper disable UnusedParameter.Local // ReSharper disable UnusedVariable -await using var client = new EventStoreClient(EventStoreClientSettings.Create("esdb://localhost:2113?tls=false")); +await using var client = new KurrentClient(KurrentClientSettings.Create("esdb://localhost:2113?tls=false")); await Task.WhenAll(YieldSamples().Select(async sample => { try { @@ -27,7 +27,7 @@ IEnumerable YieldSamples() { yield return OverridingUserCredentials(client, GetCT()); } -static async Task SubscribeToStreamFromPosition(EventStoreClient client, CancellationToken ct) { +static async Task SubscribeToStreamFromPosition(KurrentClient client, CancellationToken ct) { #region subscribe-to-stream-from-position await using var subscription = client.SubscribeToStream( @@ -46,7 +46,7 @@ static async Task SubscribeToStreamFromPosition(EventStoreClient client, Cancell #endregion subscribe-to-stream-from-position } -static async Task SubscribeToStreamLive(EventStoreClient client, CancellationToken ct) { +static async Task SubscribeToStreamLive(KurrentClient client, CancellationToken ct) { #region subscribe-to-stream-live await using var subscription = client.SubscribeToStream( @@ -65,7 +65,7 @@ static async Task SubscribeToStreamLive(EventStoreClient client, CancellationTok #endregion subscribe-to-stream-live } -static async Task SubscribeToStreamResolvingLinkTos(EventStoreClient client, CancellationToken ct) { +static async Task SubscribeToStreamResolvingLinkTos(KurrentClient client, CancellationToken ct) { #region subscribe-to-stream-resolving-linktos await using var subscription = client.SubscribeToStream( @@ -85,7 +85,7 @@ static async Task SubscribeToStreamResolvingLinkTos(EventStoreClient client, Can #endregion subscribe-to-stream-resolving-linktos } -static async Task SubscribeToStreamSubscriptionDropped(EventStoreClient client, CancellationToken ct) { +static async Task SubscribeToStreamSubscriptionDropped(KurrentClient client, CancellationToken ct) { #region subscribe-to-stream-subscription-dropped var checkpoint = await ReadStreamCheckpointAsync() switch { @@ -120,7 +120,7 @@ static async Task SubscribeToStreamSubscriptionDropped(EventStoreClient client, #endregion subscribe-to-stream-subscription-dropped } -static async Task SubscribeToStream(EventStoreClient client, CancellationToken ct) { +static async Task SubscribeToStream(KurrentClient client, CancellationToken ct) { #region subscribe-to-stream await using var subscription = client.SubscribeToStream( @@ -139,7 +139,7 @@ static async Task SubscribeToStream(EventStoreClient client, CancellationToken c #endregion subscribe-to-stream } -static async Task SubscribeToAll(EventStoreClient client, CancellationToken ct) { +static async Task SubscribeToAll(KurrentClient client, CancellationToken ct) { #region subscribe-to-all await using var subscription = client.SubscribeToAll( @@ -157,7 +157,7 @@ static async Task SubscribeToAll(EventStoreClient client, CancellationToken ct) #endregion subscribe-to-all } -static async Task SubscribeToAllFromPosition(EventStoreClient client, CancellationToken ct) { +static async Task SubscribeToAllFromPosition(KurrentClient client, CancellationToken ct) { #region subscribe-to-all-from-position var result = await client.AppendToStreamAsync( @@ -182,7 +182,7 @@ static async Task SubscribeToAllFromPosition(EventStoreClient client, Cancellati #endregion subscribe-to-all-from-position } -static async Task SubscribeToAllLive(EventStoreClient client, CancellationToken ct) { +static async Task SubscribeToAllLive(KurrentClient client, CancellationToken ct) { #region subscribe-to-all-live var subscription = client.SubscribeToAll( @@ -200,7 +200,7 @@ static async Task SubscribeToAllLive(EventStoreClient client, CancellationToken #endregion subscribe-to-all-live } -static async Task SubscribeToAllSubscriptionDropped(EventStoreClient client, CancellationToken ct) { +static async Task SubscribeToAllSubscriptionDropped(KurrentClient client, CancellationToken ct) { #region subscribe-to-all-subscription-dropped var checkpoint = await ReadCheckpointAsync() switch { @@ -237,7 +237,7 @@ static async Task SubscribeToAllSubscriptionDropped(EventStoreClient client, Can #endregion subscribe-to-all-subscription-dropped } -static async Task SubscribeToFiltered(EventStoreClient client, CancellationToken ct) { +static async Task SubscribeToFiltered(KurrentClient client, CancellationToken ct) { #region stream-prefix-filtered-subscription var prefixStreamFilter = new SubscriptionFilterOptions(StreamFilter.Prefix("test-", "other-")); @@ -267,7 +267,7 @@ static async Task SubscribeToFiltered(EventStoreClient client, CancellationToken #endregion stream-regex-filtered-subscription } -static async Task OverridingUserCredentials(EventStoreClient client, CancellationToken ct) { +static async Task OverridingUserCredentials(KurrentClient client, CancellationToken ct) { #region overriding-user-credentials await using var subscription = client.SubscribeToAll( diff --git a/samples/subscribing-to-streams/subscribing-to-streams.csproj b/samples/subscribing-to-streams/subscribing-to-streams.csproj index 397f07197..83a740e45 100644 --- a/samples/subscribing-to-streams/subscribing-to-streams.csproj +++ b/samples/subscribing-to-streams/subscribing-to-streams.csproj @@ -2,11 +2,7 @@ subscribing_to_streams - - - - - + - \ No newline at end of file + diff --git a/samples/user-certificates/Program.cs b/samples/user-certificates/Program.cs index dddbb1c7f..98f9e882e 100644 --- a/samples/user-certificates/Program.cs +++ b/samples/user-certificates/Program.cs @@ -9,11 +9,11 @@ static async Task ClientWithUserCertificates() { const string userCertFile = "/path/to/user.crt"; const string userKeyFile = "/path/to/user.key"; - var settings = EventStoreClientSettings.Create( + var settings = KurrentClientSettings.Create( $"esdb://localhost:2113/?tls=true&tlsVerifyCert=true&userCertFile={userCertFile}&userKeyFile={userKeyFile}" ); - await using var client = new EventStoreClient(settings); + await using var client = new KurrentClient(settings); # endregion client-with-user-certificates } catch (InvalidClientCertificateException) { diff --git a/samples/user-certificates/user-certificates.csproj b/samples/user-certificates/user-certificates.csproj index 7eaa70127..14de7d848 100644 --- a/samples/user-certificates/user-certificates.csproj +++ b/samples/user-certificates/user-certificates.csproj @@ -9,8 +9,7 @@ - - + diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 58ec83eff..38e546298 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,36 +1,21 @@ - - - EventStore.Client - - - - - - - - - $(MSBuildProjectName.Remove(0,18)) - EventStore.Client.Grpc.$(PackageIdSuffix) - ../EventStore.Client/Common/protos/$(PackageIdSuffix.ToLower()).proto + + true + Kurrent.Client + Kurrent.Client - - - - - ouro.png LICENSE.md - https://eventstore.com + https://kurrent.io false - https://eventstore.com/blog/ - eventstore client grpc - Event Store Ltd - Copyright 2012-$([System.DateTime]::Today.Year.ToString()) Event Store Ltd + https://kurrent.io/blog/ + kurrent client grpc + Kurrent Ltd + Copyright 2012-$([System.DateTime]::Today.Year.ToString()) Kurrent Ltd v @@ -38,30 +23,27 @@ - + - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - all - runtime; build; native; contentfiles; analyzers - + + + + + + + + + + - + - - - - - diff --git a/src/EventStore.Client.Extensions.OpenTelemetry/EventStore.Client.Extensions.OpenTelemetry.csproj b/src/EventStore.Client.Extensions.OpenTelemetry/EventStore.Client.Extensions.OpenTelemetry.csproj deleted file mode 100644 index e32bbacc7..000000000 --- a/src/EventStore.Client.Extensions.OpenTelemetry/EventStore.Client.Extensions.OpenTelemetry.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - - EventStore.Client.Extensions.OpenTelemetry - - - - EventStore.Client.Extensions.OpenTelemetry - Extensions used to facilitate instrumentation of the EventStore Client. - - - - - - - diff --git a/src/EventStore.Client.Extensions.OpenTelemetry/TracerProviderBuilderExtensions.cs b/src/EventStore.Client.Extensions.OpenTelemetry/TracerProviderBuilderExtensions.cs deleted file mode 100644 index 6a8b42b96..000000000 --- a/src/EventStore.Client.Extensions.OpenTelemetry/TracerProviderBuilderExtensions.cs +++ /dev/null @@ -1,19 +0,0 @@ -using EventStore.Client.Diagnostics; -using JetBrains.Annotations; -using OpenTelemetry.Trace; - -namespace EventStore.Client.Extensions.OpenTelemetry; - -/// -/// Extension methods used to facilitate tracing instrumentation of the EventStore Client. -/// -[PublicAPI] -public static class TracerProviderBuilderExtensions { - /// - /// Adds the EventStore client ActivitySource name to the list of subscribed sources on the - /// - /// being configured. - /// The instance of to chain configuration. - public static TracerProviderBuilder AddEventStoreClientInstrumentation(this TracerProviderBuilder builder) => - builder.AddSource(EventStoreClientDiagnostics.InstrumentationName); -} \ No newline at end of file diff --git a/src/EventStore.Client.Operations/EventStore.Client.Operations.csproj b/src/EventStore.Client.Operations/EventStore.Client.Operations.csproj deleted file mode 100644 index 37299e1a1..000000000 --- a/src/EventStore.Client.Operations/EventStore.Client.Operations.csproj +++ /dev/null @@ -1,6 +0,0 @@ - - - - The GRPC client API for Event Store Operations, e.g., Scavenging. Get the open source or commercial versions of Event Store server from https://eventstore.com/ - - diff --git a/src/EventStore.Client.PersistentSubscriptions/EventStore.Client.PersistentSubscriptions.csproj b/src/EventStore.Client.PersistentSubscriptions/EventStore.Client.PersistentSubscriptions.csproj deleted file mode 100644 index 405a77405..000000000 --- a/src/EventStore.Client.PersistentSubscriptions/EventStore.Client.PersistentSubscriptions.csproj +++ /dev/null @@ -1,6 +0,0 @@ - - - - The GRPC client API for Event Store Persistent Subscriptions. Get the open source or commercial versions of Event Store server from https://eventstore.com/ - - diff --git a/src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClientCollectionExtensions.cs b/src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClientCollectionExtensions.cs deleted file mode 100644 index f8d491dda..000000000 --- a/src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClientCollectionExtensions.cs +++ /dev/null @@ -1,61 +0,0 @@ -// ReSharper disable CheckNamespace - -using System; -using System.Net.Http; -using EventStore.Client; -using Grpc.Core.Interceptors; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Logging; - -namespace Microsoft.Extensions.DependencyInjection { - /// - /// A set of extension methods for which provide support for an . - /// - public static class EventStorePersistentSubscriptionsClientCollectionExtensions { - /// - /// Adds an to the . - /// - /// - public static IServiceCollection AddEventStorePersistentSubscriptionsClient(this IServiceCollection services, - Uri address, Func? createHttpMessageHandler = null) - => services.AddEventStorePersistentSubscriptionsClient(options => { - options.ConnectivitySettings.Address = address; - options.CreateHttpMessageHandler = createHttpMessageHandler; - }); - - /// - /// Adds an to the . - /// - /// - public static IServiceCollection AddEventStorePersistentSubscriptionsClient(this IServiceCollection services, - Action? configureSettings = null) => - services.AddEventStorePersistentSubscriptionsClient(new EventStoreClientSettings(), - configureSettings); - - /// - /// Adds an to the . - /// - /// - public static IServiceCollection AddEventStorePersistentSubscriptionsClient(this IServiceCollection services, - string connectionString, Action? configureSettings = null) => - services.AddEventStorePersistentSubscriptionsClient(EventStoreClientSettings.Create(connectionString), - configureSettings); - - private static IServiceCollection AddEventStorePersistentSubscriptionsClient(this IServiceCollection services, - EventStoreClientSettings settings, Action? configureSettings) { - if (services == null) { - throw new ArgumentNullException(nameof(services)); - } - - configureSettings?.Invoke(settings); - services.TryAddSingleton(provider => { - settings.LoggerFactory ??= provider.GetService(); - settings.Interceptors ??= provider.GetServices(); - - return new EventStorePersistentSubscriptionsClient(settings); - }); - return services; - } - } -} -// ReSharper restore CheckNamespace diff --git a/src/EventStore.Client.ProjectionManagement/EventStore.Client.ProjectionManagement.csproj b/src/EventStore.Client.ProjectionManagement/EventStore.Client.ProjectionManagement.csproj deleted file mode 100644 index 678656cff..000000000 --- a/src/EventStore.Client.ProjectionManagement/EventStore.Client.ProjectionManagement.csproj +++ /dev/null @@ -1,6 +0,0 @@ - - - - The GRPC client API for managing Event Store Projections. Get the open source or commercial versions of Event Store server from https://eventstore.com/ - - diff --git a/src/EventStore.Client.ProjectionManagement/EventStoreProjectionManagementClient.cs b/src/EventStore.Client.ProjectionManagement/EventStoreProjectionManagementClient.cs deleted file mode 100644 index be0679928..000000000 --- a/src/EventStore.Client.ProjectionManagement/EventStoreProjectionManagementClient.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Collections.Generic; -using Grpc.Core; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Options; - -namespace EventStore.Client { - /// - ///The client used to manage projections on the EventStoreDB. - /// - public sealed partial class EventStoreProjectionManagementClient : EventStoreClientBase { - private readonly ILogger _log; - - /// - /// Constructs a new . This method is not intended to be called directly from your code. - /// - /// - public EventStoreProjectionManagementClient(IOptions options) : this(options.Value) { - } - - /// - /// Constructs a new . - /// - /// - public EventStoreProjectionManagementClient(EventStoreClientSettings? settings) : base(settings, - new Dictionary>()) { - _log = settings?.LoggerFactory?.CreateLogger() ?? - new NullLogger(); - } - } -} diff --git a/src/EventStore.Client.Streams/EventStore.Client.Streams.csproj b/src/EventStore.Client.Streams/EventStore.Client.Streams.csproj deleted file mode 100644 index c878127a5..000000000 --- a/src/EventStore.Client.Streams/EventStore.Client.Streams.csproj +++ /dev/null @@ -1,6 +0,0 @@ - - - - The GRPC client API for Event Store Streams. Get the open source or commercial versions of Event Store server from https://eventstore.com/ - - diff --git a/src/EventStore.Client.UserManagement/EventStore.Client.UserManagement.csproj b/src/EventStore.Client.UserManagement/EventStore.Client.UserManagement.csproj deleted file mode 100644 index 2c9308e2e..000000000 --- a/src/EventStore.Client.UserManagement/EventStore.Client.UserManagement.csproj +++ /dev/null @@ -1,9 +0,0 @@ - - - - The GRPC client API for managing users in Event Store. Get the open source or commercial versions of Event Store server from https://eventstore.com/ - - - - - diff --git a/src/EventStore.Client.UserManagement/EventStore.Client.UserManagement.csproj.DotSettings b/src/EventStore.Client.UserManagement/EventStore.Client.UserManagement.csproj.DotSettings deleted file mode 100644 index 1183b3a73..000000000 --- a/src/EventStore.Client.UserManagement/EventStore.Client.UserManagement.csproj.DotSettings +++ /dev/null @@ -1,2 +0,0 @@ - - True \ No newline at end of file diff --git a/src/EventStore.Client/Common/Diagnostics/EventStoreClientDiagnostics.cs b/src/EventStore.Client/Common/Diagnostics/EventStoreClientDiagnostics.cs deleted file mode 100644 index 6328387ab..000000000 --- a/src/EventStore.Client/Common/Diagnostics/EventStoreClientDiagnostics.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System.Diagnostics; - -namespace EventStore.Client.Diagnostics; - -public static class EventStoreClientDiagnostics { - public const string InstrumentationName = "eventstoredb"; - public static readonly ActivitySource ActivitySource = new ActivitySource(InstrumentationName); -} \ No newline at end of file diff --git a/src/EventStore.Client/Common/Diagnostics/Telemetry/TelemetryTags.cs b/src/EventStore.Client/Common/Diagnostics/Telemetry/TelemetryTags.cs deleted file mode 100644 index ea05d04fa..000000000 --- a/src/EventStore.Client/Common/Diagnostics/Telemetry/TelemetryTags.cs +++ /dev/null @@ -1,12 +0,0 @@ -// ReSharper disable CheckNamespace - -namespace EventStore.Diagnostics.Telemetry; - -static partial class TelemetryTags { - public static class EventStore { - public const string Stream = "db.eventstoredb.stream"; - public const string SubscriptionId = "db.eventstoredb.subscription.id"; - public const string EventId = "db.eventstoredb.event.id"; - public const string EventType = "db.eventstoredb.event.type"; - } -} \ No newline at end of file diff --git a/src/EventStore.Client/EventStore.Client.csproj b/src/EventStore.Client/EventStore.Client.csproj deleted file mode 100644 index 47a116602..000000000 --- a/src/EventStore.Client/EventStore.Client.csproj +++ /dev/null @@ -1,40 +0,0 @@ - - - - EventStore.Client - The base GRPC client library for Event Store. Get the open source or commercial versions of Event Store server from https://eventstore.com/ - EventStore.Client.Grpc - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/EventStore.Client/EventStore.Client.csproj.DotSettings b/src/EventStore.Client/EventStore.Client.csproj.DotSettings deleted file mode 100644 index 9b89548c6..000000000 --- a/src/EventStore.Client/EventStore.Client.csproj.DotSettings +++ /dev/null @@ -1,3 +0,0 @@ - - True - True \ No newline at end of file diff --git a/src/EventStore.Client/Certificates/X509Certificates.cs b/src/Kurrent.Client/Core/Certificates/X509Certificates.cs similarity index 66% rename from src/EventStore.Client/Certificates/X509Certificates.cs rename to src/Kurrent.Client/Core/Certificates/X509Certificates.cs index 78efda04e..9cda47a08 100644 --- a/src/EventStore.Client/Certificates/X509Certificates.cs +++ b/src/Kurrent.Client/Core/Certificates/X509Certificates.cs @@ -2,6 +2,7 @@ using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; +#pragma warning disable SYSLIB0057 #if NET48 using Org.BouncyCastle.Crypto; @@ -13,29 +14,21 @@ namespace EventStore.Client; static class X509Certificates { - // TODO SS: Use .NET 8 X509Certificate2.CreateFromPemFile(certPemFilePath, keyPemFilePath) once the Windows32Exception issue is resolved - public static X509Certificate2 CreateFromPemFile(string certPemFilePath, string keyPemFilePath) { - try { - using var publicCert = new X509Certificate2(certPemFilePath); - using var privateKey = RSA.Create().ImportPrivateKeyFromFile(keyPemFilePath); - using var certificate = publicCert.CopyWithPrivateKey(privateKey); - - return new(certificate.Export(X509ContentType.Pfx)); - } - catch (Exception ex) { - throw new CryptographicException($"Failed to load private key: {ex.Message}"); - } - - // Notes: - // using X509Certificate2.CreateFromPemFile(certPemFilePath, keyPemFilePath) would be the ideal choice here, - // but it's currently causing a Win32Exception specifically on Windows. Alternative implementation is used until the issue is resolved. - // - // Error: The SSL connection could not be established, see inner exception. AuthenticationException: Authentication failed because the platform - // does not support ephemeral keys. Win32Exception: No credentials are available in the security package - // - // public static X509Certificate2 CreateFromPemFile(string certPemFilePath, string keyPemFilePath) => - // X509Certificate2.CreateFromPemFile(certPemFilePath, keyPemFilePath); - } + public static X509Certificate2 CreateFromPemFile(string certPemFilePath, string keyPemFilePath) { + try { +#if NET8_0_OR_GREATER + using var certificate = X509Certificate2.CreateFromPemFile(certPemFilePath, keyPemFilePath); +#else + using var publicCert = new X509Certificate2(certPemFilePath); + using var privateKey = RSA.Create().ImportPrivateKeyFromFile(keyPemFilePath); + using var certificate = publicCert.CopyWithPrivateKey(privateKey); +#endif + + return new X509Certificate2(certificate.Export(X509ContentType.Pfx)); + } catch (Exception ex) { + throw new CryptographicException($"Failed to load private key: {ex.Message}"); + } + } } public static class RsaExtensions { @@ -104,4 +97,4 @@ public static string ParseKeyLabel(string pemFileHeader) { return label; } -} \ No newline at end of file +} diff --git a/src/EventStore.Client/ChannelBaseExtensions.cs b/src/Kurrent.Client/Core/ChannelBaseExtensions.cs similarity index 99% rename from src/EventStore.Client/ChannelBaseExtensions.cs rename to src/Kurrent.Client/Core/ChannelBaseExtensions.cs index 3edbf59fd..9c44addef 100644 --- a/src/EventStore.Client/ChannelBaseExtensions.cs +++ b/src/Kurrent.Client/Core/ChannelBaseExtensions.cs @@ -7,4 +7,4 @@ 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/Kurrent.Client/Core/ChannelCache.cs similarity index 96% rename from src/EventStore.Client/ChannelCache.cs rename to src/Kurrent.Client/Core/ChannelCache.cs index a3369e25f..09f7c2b86 100644 --- a/src/EventStore.Client/ChannelCache.cs +++ b/src/Kurrent.Client/Core/ChannelCache.cs @@ -8,13 +8,13 @@ namespace EventStore.Client { internal class ChannelCache : IAsyncDisposable { - private readonly EventStoreClientSettings _settings; + private readonly KurrentClientSettings _settings; private readonly Random _random; private readonly Dictionary _channels; private readonly object _lock = new(); private bool _disposed; - public ChannelCache(EventStoreClientSettings settings) { + public ChannelCache(KurrentClientSettings settings) { _settings = settings; _random = new Random(0); _channels = new Dictionary( diff --git a/src/EventStore.Client/ChannelFactory.cs b/src/Kurrent.Client/Core/ChannelFactory.cs similarity index 93% rename from src/EventStore.Client/ChannelFactory.cs rename to src/Kurrent.Client/Core/ChannelFactory.cs index 0dc28ee8e..c63605bb4 100644 --- a/src/EventStore.Client/ChannelFactory.cs +++ b/src/Kurrent.Client/Core/ChannelFactory.cs @@ -9,7 +9,7 @@ namespace EventStore.Client { internal static class ChannelFactory { private const int MaxReceiveMessageLength = 17 * 1024 * 1024; - public static TChannel CreateChannel(EventStoreClientSettings settings, EndPoint endPoint) { + public static TChannel CreateChannel(KurrentClientSettings settings, EndPoint endPoint) { var address = endPoint.ToUri(!settings.ConnectivitySettings.Insecure); if (settings.ConnectivitySettings.Insecure) { @@ -37,7 +37,7 @@ public static TChannel CreateChannel(EventStoreClientSettings settings, EndPoint #if NET48 - static HttpMessageHandler CreateHandler(EventStoreClientSettings settings) { + static HttpMessageHandler CreateHandler(KurrentClientSettings settings) { if (settings.CreateHttpMessageHandler is not null) return settings.CreateHttpMessageHandler.Invoke(); @@ -67,7 +67,7 @@ static HttpMessageHandler CreateHandler(EventStoreClientSettings settings) { return handler; } #else - static HttpMessageHandler CreateHandler(EventStoreClientSettings settings) { + static HttpMessageHandler CreateHandler(KurrentClientSettings settings) { if (settings.CreateHttpMessageHandler is not null) return settings.CreateHttpMessageHandler.Invoke(); diff --git a/src/EventStore.Client/ChannelInfo.cs b/src/Kurrent.Client/Core/ChannelInfo.cs similarity index 100% rename from src/EventStore.Client/ChannelInfo.cs rename to src/Kurrent.Client/Core/ChannelInfo.cs diff --git a/src/EventStore.Client/ChannelSelector.cs b/src/Kurrent.Client/Core/ChannelSelector.cs similarity index 94% rename from src/EventStore.Client/ChannelSelector.cs rename to src/Kurrent.Client/Core/ChannelSelector.cs index 354c0a9f5..af0fa3031 100644 --- a/src/EventStore.Client/ChannelSelector.cs +++ b/src/Kurrent.Client/Core/ChannelSelector.cs @@ -8,7 +8,7 @@ internal class ChannelSelector : IChannelSelector { private readonly IChannelSelector _inner; public ChannelSelector( - EventStoreClientSettings settings, + KurrentClientSettings settings, ChannelCache channelCache) { _inner = settings.ConnectivitySettings.IsSingleNode ? new SingleNodeChannelSelector(settings, channelCache) diff --git a/src/EventStore.Client/ClusterMessage.cs b/src/Kurrent.Client/Core/ClusterMessage.cs similarity index 100% rename from src/EventStore.Client/ClusterMessage.cs rename to src/Kurrent.Client/Core/ClusterMessage.cs diff --git a/src/EventStore.Client/Common/AsyncStreamReaderExtensions.cs b/src/Kurrent.Client/Core/Common/AsyncStreamReaderExtensions.cs similarity index 100% rename from src/EventStore.Client/Common/AsyncStreamReaderExtensions.cs rename to src/Kurrent.Client/Core/Common/AsyncStreamReaderExtensions.cs diff --git a/src/EventStore.Client/Common/Constants.cs b/src/Kurrent.Client/Core/Common/Constants.cs similarity index 100% rename from src/EventStore.Client/Common/Constants.cs rename to src/Kurrent.Client/Core/Common/Constants.cs diff --git a/src/EventStore.Client/Common/Diagnostics/ActivitySourceExtensions.cs b/src/Kurrent.Client/Core/Common/Diagnostics/ActivitySourceExtensions.cs similarity index 72% rename from src/EventStore.Client/Common/Diagnostics/ActivitySourceExtensions.cs rename to src/Kurrent.Client/Core/Common/Diagnostics/ActivitySourceExtensions.cs index 71f4372da..ab914d8c9 100644 --- a/src/EventStore.Client/Common/Diagnostics/ActivitySourceExtensions.cs +++ b/src/Kurrent.Client/Core/Common/Diagnostics/ActivitySourceExtensions.cs @@ -1,9 +1,9 @@ // ReSharper disable ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract using System.Diagnostics; -using EventStore.Diagnostics; -using EventStore.Diagnostics.Telemetry; -using EventStore.Diagnostics.Tracing; +using Kurrent.Diagnostics; +using Kurrent.Diagnostics.Telemetry; +using Kurrent.Diagnostics.Tracing; namespace EventStore.Client.Diagnostics; @@ -12,13 +12,8 @@ public static async ValueTask TraceClientOperation( this ActivitySource source, Func> tracedOperation, string operationName, - Func? tagsFactory = null + ActivityTagsCollection? tags = null ) { - if (source.HasNoActiveListeners()) - return await tracedOperation().ConfigureAwait(false); - - var tags = tagsFactory?.Invoke(); - using var activity = StartActivity(source, operationName, ActivityKind.Client, tags, Activity.Current?.Context); try { @@ -36,7 +31,7 @@ public static void TraceSubscriptionEvent( string? subscriptionId, ResolvedEvent resolvedEvent, ChannelInfo channelInfo, - EventStoreClientSettings settings, + KurrentClientSettings settings, UserCredentials? userCredentials ) { if (source.HasNoActiveListeners() || resolvedEvent.Event is null) @@ -47,12 +42,12 @@ public static void TraceSubscriptionEvent( if (parentContext == default(ActivityContext)) return; var tags = new ActivityTagsCollection() - .WithRequiredTag(TelemetryTags.EventStore.Stream, resolvedEvent.OriginalEvent.EventStreamId) - .WithOptionalTag(TelemetryTags.EventStore.SubscriptionId, subscriptionId) - .WithRequiredTag(TelemetryTags.EventStore.EventId, resolvedEvent.OriginalEvent.EventId.ToString()) - .WithRequiredTag(TelemetryTags.EventStore.EventType, resolvedEvent.OriginalEvent.EventType) + .WithRequiredTag(TelemetryTags.Kurrent.Stream, resolvedEvent.OriginalEvent.EventStreamId) + .WithOptionalTag(TelemetryTags.Kurrent.SubscriptionId, subscriptionId) + .WithRequiredTag(TelemetryTags.Kurrent.EventId, resolvedEvent.OriginalEvent.EventId.ToString()) + .WithRequiredTag(TelemetryTags.Kurrent.EventType, resolvedEvent.OriginalEvent.EventType) // Ensure consistent server.address attribute when connecting to cluster via dns discovery - .WithGrpcChannelServerTags(settings, channelInfo) + .WithGrpcChannelServerTags(channelInfo) .WithClientSettingsServerTags(settings) .WithOptionalTag( TelemetryTags.Database.User, @@ -72,7 +67,7 @@ public static void TraceSubscriptionEvent( return null; (tags ??= new ActivityTagsCollection()) - .WithRequiredTag(TelemetryTags.Database.System, "eventstoredb") + .WithRequiredTag(TelemetryTags.Database.System, "kurrent") .WithRequiredTag(TelemetryTags.Database.Operation, operationName); return source diff --git a/src/EventStore.Client/Common/Diagnostics/ActivityTagsCollectionExtensions.cs b/src/Kurrent.Client/Core/Common/Diagnostics/ActivityTagsCollectionExtensions.cs similarity index 51% rename from src/EventStore.Client/Common/Diagnostics/ActivityTagsCollectionExtensions.cs rename to src/Kurrent.Client/Core/Common/Diagnostics/ActivityTagsCollectionExtensions.cs index bc3c2aa75..fd6ad661a 100644 --- a/src/EventStore.Client/Common/Diagnostics/ActivityTagsCollectionExtensions.cs +++ b/src/Kurrent.Client/Core/Common/Diagnostics/ActivityTagsCollectionExtensions.cs @@ -1,30 +1,25 @@ using System.Diagnostics; using System.Runtime.CompilerServices; -using EventStore.Diagnostics; -using EventStore.Diagnostics.Telemetry; +using Kurrent.Diagnostics; +using Kurrent.Diagnostics.Telemetry; namespace EventStore.Client.Diagnostics; static class ActivityTagsCollectionExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ActivityTagsCollection WithGrpcChannelServerTags(this ActivityTagsCollection tags, EventStoreClientSettings settings, ChannelInfo? channelInfo) { + public static ActivityTagsCollection WithGrpcChannelServerTags(this ActivityTagsCollection tags, ChannelInfo? channelInfo) { if (channelInfo is null) return tags; + + var authorityParts = channelInfo.Channel.Target.Split(':'); - var authorityParts = channelInfo.Channel.Target.Split([':'], StringSplitOptions.RemoveEmptyEntries); - - string host = authorityParts[0]; - int port = authorityParts.Length == 1 - ? settings.ConnectivitySettings.Insecure ? 80 : 443 - : int.Parse(authorityParts[1]); - - return tags - .WithRequiredTag(TelemetryTags.Server.Address, host) - .WithRequiredTag(TelemetryTags.Server.Port, port); - } + return tags + .WithRequiredTag(TelemetryTags.Server.Address, authorityParts[0]) + .WithRequiredTag(TelemetryTags.Server.Port, int.Parse(authorityParts[1])); + } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ActivityTagsCollection WithClientSettingsServerTags(this ActivityTagsCollection source, EventStoreClientSettings settings) { + public static ActivityTagsCollection WithClientSettingsServerTags(this ActivityTagsCollection source, KurrentClientSettings settings) { if (settings.ConnectivitySettings.DnsGossipSeeds?.Length != 1) return source; diff --git a/src/EventStore.Client/Common/Diagnostics/Core/ActivityExtensions.cs b/src/Kurrent.Client/Core/Common/Diagnostics/Core/ActivityExtensions.cs similarity index 94% rename from src/EventStore.Client/Common/Diagnostics/Core/ActivityExtensions.cs rename to src/Kurrent.Client/Core/Common/Diagnostics/Core/ActivityExtensions.cs index 4594d1000..4b6404f60 100644 --- a/src/EventStore.Client/Common/Diagnostics/Core/ActivityExtensions.cs +++ b/src/Kurrent.Client/Core/Common/Diagnostics/Core/ActivityExtensions.cs @@ -2,10 +2,10 @@ using System.Diagnostics; using System.Runtime.CompilerServices; -using EventStore.Diagnostics.Telemetry; -using EventStore.Diagnostics.Tracing; +using Kurrent.Diagnostics.Telemetry; +using Kurrent.Diagnostics.Tracing; -namespace EventStore.Diagnostics; +namespace Kurrent.Diagnostics; static class ActivityExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -49,4 +49,4 @@ static Activity SetActivityStatus(this Activity activity, ActivityStatus status) return activity.IsAllDataRequested ? activity.RecordException(status.Exception) : activity; } -} \ No newline at end of file +} diff --git a/src/EventStore.Client/Common/Diagnostics/Core/ActivityStatus.cs b/src/Kurrent.Client/Core/Common/Diagnostics/Core/ActivityStatus.cs similarity index 93% rename from src/EventStore.Client/Common/Diagnostics/Core/ActivityStatus.cs rename to src/Kurrent.Client/Core/Common/Diagnostics/Core/ActivityStatus.cs index a25b7326f..bab790b6c 100644 --- a/src/EventStore.Client/Common/Diagnostics/Core/ActivityStatus.cs +++ b/src/Kurrent.Client/Core/Common/Diagnostics/Core/ActivityStatus.cs @@ -2,7 +2,7 @@ using System.Diagnostics; -namespace EventStore.Diagnostics; +namespace Kurrent.Diagnostics; record ActivityStatus(ActivityStatusCode StatusCode, string? Description, Exception? Exception) { public static ActivityStatus Ok(string? description = null) => diff --git a/src/EventStore.Client/Common/Diagnostics/Core/ActivityStatusCodeHelper.cs b/src/Kurrent.Client/Core/Common/Diagnostics/Core/ActivityStatusCodeHelper.cs similarity index 95% rename from src/EventStore.Client/Common/Diagnostics/Core/ActivityStatusCodeHelper.cs rename to src/Kurrent.Client/Core/Common/Diagnostics/Core/ActivityStatusCodeHelper.cs index 77810aa6c..592501d11 100644 --- a/src/EventStore.Client/Common/Diagnostics/Core/ActivityStatusCodeHelper.cs +++ b/src/Kurrent.Client/Core/Common/Diagnostics/Core/ActivityStatusCodeHelper.cs @@ -6,7 +6,7 @@ using static System.Diagnostics.ActivityStatusCode; using static System.StringComparison; -namespace EventStore.Diagnostics; +namespace Kurrent.Diagnostics; static class ActivityStatusCodeHelper { public const string UnsetStatusCodeTagValue = "UNSET"; @@ -21,4 +21,4 @@ static class ActivityStatusCodeHelper { Ok => OkStatusCodeTagValue, _ => null }; -} \ No newline at end of file +} diff --git a/src/EventStore.Client/Common/Diagnostics/Core/ActivityTagsCollectionExtensions.cs b/src/Kurrent.Client/Core/Common/Diagnostics/Core/ActivityTagsCollectionExtensions.cs similarity index 97% rename from src/EventStore.Client/Common/Diagnostics/Core/ActivityTagsCollectionExtensions.cs rename to src/Kurrent.Client/Core/Common/Diagnostics/Core/ActivityTagsCollectionExtensions.cs index 15aa0662e..2c8c8b291 100644 --- a/src/EventStore.Client/Common/Diagnostics/Core/ActivityTagsCollectionExtensions.cs +++ b/src/Kurrent.Client/Core/Common/Diagnostics/Core/ActivityTagsCollectionExtensions.cs @@ -3,7 +3,7 @@ using System.Diagnostics; using System.Runtime.CompilerServices; -namespace EventStore.Diagnostics; +namespace Kurrent.Diagnostics; static class ActivityTagsCollectionExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/EventStore.Client/Common/Diagnostics/Core/ExceptionExtensions.cs b/src/Kurrent.Client/Core/Common/Diagnostics/Core/ExceptionExtensions.cs similarity index 95% rename from src/EventStore.Client/Common/Diagnostics/Core/ExceptionExtensions.cs rename to src/Kurrent.Client/Core/Common/Diagnostics/Core/ExceptionExtensions.cs index 8403c3c01..7eb397251 100644 --- a/src/EventStore.Client/Common/Diagnostics/Core/ExceptionExtensions.cs +++ b/src/Kurrent.Client/Core/Common/Diagnostics/Core/ExceptionExtensions.cs @@ -2,7 +2,7 @@ using System.Globalization; -namespace EventStore.Diagnostics; +namespace Kurrent.Diagnostics; static class ExceptionExtensions { /// @@ -22,4 +22,4 @@ public static string ToInvariantString(this Exception exception) { Thread.CurrentThread.CurrentUICulture = originalUiCulture; } } -} \ No newline at end of file +} diff --git a/src/EventStore.Client/Common/Diagnostics/Core/Telemetry/TelemetryTags.cs b/src/Kurrent.Client/Core/Common/Diagnostics/Core/Telemetry/TelemetryTags.cs similarity index 97% rename from src/EventStore.Client/Common/Diagnostics/Core/Telemetry/TelemetryTags.cs rename to src/Kurrent.Client/Core/Common/Diagnostics/Core/Telemetry/TelemetryTags.cs index f7d5e4b17..54487e3bd 100644 --- a/src/EventStore.Client/Common/Diagnostics/Core/Telemetry/TelemetryTags.cs +++ b/src/Kurrent.Client/Core/Common/Diagnostics/Core/Telemetry/TelemetryTags.cs @@ -1,6 +1,6 @@ // ReSharper disable CheckNamespace -namespace EventStore.Diagnostics.Telemetry; +namespace Kurrent.Diagnostics.Telemetry; // The attributes below match the specification of v1.24.0 of the Open Telemetry semantic conventions. // Some attributes are ignored where not required or relevant. @@ -32,4 +32,4 @@ public static class Otel { public const string StatusCode = "otel.status_code"; public const string StatusDescription = "otel.status_description"; } -} \ No newline at end of file +} diff --git a/src/EventStore.Client/Common/Diagnostics/Core/Tracing/TracingConstants.cs b/src/Kurrent.Client/Core/Common/Diagnostics/Core/Tracing/TracingConstants.cs similarity index 83% rename from src/EventStore.Client/Common/Diagnostics/Core/Tracing/TracingConstants.cs rename to src/Kurrent.Client/Core/Common/Diagnostics/Core/Tracing/TracingConstants.cs index 26aa2be21..1e94c9ef0 100644 --- a/src/EventStore.Client/Common/Diagnostics/Core/Tracing/TracingConstants.cs +++ b/src/Kurrent.Client/Core/Common/Diagnostics/Core/Tracing/TracingConstants.cs @@ -1,10 +1,10 @@ // ReSharper disable CheckNamespace -namespace EventStore.Diagnostics.Tracing; +namespace Kurrent.Diagnostics.Tracing; static partial class TracingConstants { public static class Metadata { public const string TraceId = "$traceId"; public const string SpanId = "$spanId"; } -} \ No newline at end of file +} diff --git a/src/EventStore.Client/Common/Diagnostics/Core/Tracing/TracingMetadata.cs b/src/Kurrent.Client/Core/Common/Diagnostics/Core/Tracing/TracingMetadata.cs similarity index 95% rename from src/EventStore.Client/Common/Diagnostics/Core/Tracing/TracingMetadata.cs rename to src/Kurrent.Client/Core/Common/Diagnostics/Core/Tracing/TracingMetadata.cs index ecb9c68c6..7580753a7 100644 --- a/src/EventStore.Client/Common/Diagnostics/Core/Tracing/TracingMetadata.cs +++ b/src/Kurrent.Client/Core/Common/Diagnostics/Core/Tracing/TracingMetadata.cs @@ -3,7 +3,7 @@ using System.Diagnostics; using System.Text.Json.Serialization; -namespace EventStore.Diagnostics.Tracing; +namespace Kurrent.Diagnostics.Tracing; readonly record struct TracingMetadata( [property: JsonPropertyName(TracingConstants.Metadata.TraceId)] diff --git a/src/EventStore.Client/Common/Diagnostics/EventMetadataExtensions.cs b/src/Kurrent.Client/Core/Common/Diagnostics/EventMetadataExtensions.cs similarity index 97% rename from src/EventStore.Client/Common/Diagnostics/EventMetadataExtensions.cs rename to src/Kurrent.Client/Core/Common/Diagnostics/EventMetadataExtensions.cs index 4245d5bb7..d45b53156 100644 --- a/src/EventStore.Client/Common/Diagnostics/EventMetadataExtensions.cs +++ b/src/Kurrent.Client/Core/Common/Diagnostics/EventMetadataExtensions.cs @@ -1,8 +1,8 @@ using System.Diagnostics; using System.Runtime.CompilerServices; using System.Text.Json; -using EventStore.Diagnostics; -using EventStore.Diagnostics.Tracing; +using Kurrent.Diagnostics; +using Kurrent.Diagnostics.Tracing; namespace EventStore.Client.Diagnostics; diff --git a/src/Kurrent.Client/Core/Common/Diagnostics/KurrentClientDiagnostics.cs b/src/Kurrent.Client/Core/Common/Diagnostics/KurrentClientDiagnostics.cs new file mode 100644 index 000000000..48e437463 --- /dev/null +++ b/src/Kurrent.Client/Core/Common/Diagnostics/KurrentClientDiagnostics.cs @@ -0,0 +1,8 @@ +using System.Diagnostics; + +namespace EventStore.Client.Diagnostics; + +public static class KurrentClientDiagnostics { + public const string InstrumentationName = "kurrent"; + public static readonly ActivitySource ActivitySource = new(InstrumentationName); +} diff --git a/src/Kurrent.Client/Core/Common/Diagnostics/Telemetry/TelemetryTags.cs b/src/Kurrent.Client/Core/Common/Diagnostics/Telemetry/TelemetryTags.cs new file mode 100644 index 000000000..e4e0b11f9 --- /dev/null +++ b/src/Kurrent.Client/Core/Common/Diagnostics/Telemetry/TelemetryTags.cs @@ -0,0 +1,12 @@ +// ReSharper disable CheckNamespace + +namespace Kurrent.Diagnostics.Telemetry; + +static partial class TelemetryTags { + public static class Kurrent { + public const string Stream = "db.kurrent.stream"; + public const string SubscriptionId = "db.kurrent.subscription.id"; + public const string EventId = "db.kurrent.event.id"; + public const string EventType = "db.kurrent.event.type"; + } +} diff --git a/src/EventStore.Client/Common/Diagnostics/Tracing/TracingConstants.cs b/src/Kurrent.Client/Core/Common/Diagnostics/Tracing/TracingConstants.cs similarity index 85% rename from src/EventStore.Client/Common/Diagnostics/Tracing/TracingConstants.cs rename to src/Kurrent.Client/Core/Common/Diagnostics/Tracing/TracingConstants.cs index e43102ebe..357654570 100644 --- a/src/EventStore.Client/Common/Diagnostics/Tracing/TracingConstants.cs +++ b/src/Kurrent.Client/Core/Common/Diagnostics/Tracing/TracingConstants.cs @@ -1,10 +1,10 @@ // ReSharper disable CheckNamespace -namespace EventStore.Diagnostics.Tracing; +namespace Kurrent.Diagnostics.Tracing; static partial class TracingConstants { public static class Operations { public const string Append = "streams.append"; public const string Subscribe = "streams.subscribe"; } -} \ No newline at end of file +} diff --git a/src/EventStore.Client/Common/EnumerableTaskExtensions.cs b/src/Kurrent.Client/Core/Common/EnumerableTaskExtensions.cs similarity index 99% rename from src/EventStore.Client/Common/EnumerableTaskExtensions.cs rename to src/Kurrent.Client/Core/Common/EnumerableTaskExtensions.cs index eb4517006..5be066ab5 100644 --- a/src/EventStore.Client/Common/EnumerableTaskExtensions.cs +++ b/src/Kurrent.Client/Core/Common/EnumerableTaskExtensions.cs @@ -8,4 +8,4 @@ static class EnumerableTaskExtensions { [DebuggerStepThrough] public static Task WhenAll(this IEnumerable> source) => Task.WhenAll(source); -} \ No newline at end of file +} diff --git a/src/EventStore.Client/Common/EpochExtensions.cs b/src/Kurrent.Client/Core/Common/EpochExtensions.cs similarity index 99% rename from src/EventStore.Client/Common/EpochExtensions.cs rename to src/Kurrent.Client/Core/Common/EpochExtensions.cs index db59e620d..0643bcecb 100644 --- a/src/EventStore.Client/Common/EpochExtensions.cs +++ b/src/Kurrent.Client/Core/Common/EpochExtensions.cs @@ -22,4 +22,4 @@ static class EpochExtensions { public static DateTime FromTicksSinceEpoch(this long value) => new(UnixEpoch.Ticks + value, DateTimeKind.Utc); public static long ToTicksSinceEpoch(this DateTime value) => (value - UnixEpoch).Ticks; -} \ No newline at end of file +} diff --git a/src/EventStore.Client/Common/EventStoreCallOptions.cs b/src/Kurrent.Client/Core/Common/KurrentCallOptions.cs similarity index 89% rename from src/EventStore.Client/Common/EventStoreCallOptions.cs rename to src/Kurrent.Client/Core/Common/KurrentCallOptions.cs index e6058a170..0644cffea 100644 --- a/src/EventStore.Client/Common/EventStoreCallOptions.cs +++ b/src/Kurrent.Client/Core/Common/KurrentCallOptions.cs @@ -3,10 +3,10 @@ namespace EventStore.Client; -static class EventStoreCallOptions { +static class KurrentCallOptions { // deadline falls back to infinity public static CallOptions CreateStreaming( - EventStoreClientSettings settings, + KurrentClientSettings settings, TimeSpan? deadline = null, UserCredentials? userCredentials = null, CancellationToken cancellationToken = default ) => @@ -14,7 +14,7 @@ public static CallOptions CreateStreaming( // deadline falls back to connection DefaultDeadline public static CallOptions CreateNonStreaming( - EventStoreClientSettings settings, + KurrentClientSettings settings, CancellationToken cancellationToken ) => Create( @@ -25,7 +25,7 @@ CancellationToken cancellationToken ); public static CallOptions CreateNonStreaming( - EventStoreClientSettings settings, TimeSpan? deadline, + KurrentClientSettings settings, TimeSpan? deadline, UserCredentials? userCredentials, CancellationToken cancellationToken ) => Create( @@ -36,7 +36,7 @@ public static CallOptions CreateNonStreaming( ); static CallOptions Create( - EventStoreClientSettings settings, TimeSpan? deadline, + KurrentClientSettings settings, TimeSpan? deadline, UserCredentials? userCredentials, CancellationToken cancellationToken ) => new( @@ -71,4 +71,4 @@ static CallOptions Create( : timeoutAfter.Value == TimeSpan.MaxValue || timeoutAfter.Value == InfiniteTimeSpan ? DateTime.MaxValue : DateTime.UtcNow.Add(timeoutAfter.Value); -} \ No newline at end of file +} diff --git a/src/EventStore.Client/Common/MetadataExtensions.cs b/src/Kurrent.Client/Core/Common/MetadataExtensions.cs similarity index 99% rename from src/EventStore.Client/Common/MetadataExtensions.cs rename to src/Kurrent.Client/Core/Common/MetadataExtensions.cs index e547970fd..e7311c37f 100644 --- a/src/EventStore.Client/Common/MetadataExtensions.cs +++ b/src/Kurrent.Client/Core/Common/MetadataExtensions.cs @@ -26,4 +26,4 @@ public static int GetIntValueOrDefault(this Metadata metadata, string key) => metadata.TryGetValue(key, out var s) && int.TryParse(s, out var value) ? value : default; -} \ No newline at end of file +} diff --git a/src/EventStore.Client/Common/Shims/Index.cs b/src/Kurrent.Client/Core/Common/Shims/Index.cs similarity index 100% rename from src/EventStore.Client/Common/Shims/Index.cs rename to src/Kurrent.Client/Core/Common/Shims/Index.cs diff --git a/src/EventStore.Client/Common/Shims/IsExternalInit.cs b/src/Kurrent.Client/Core/Common/Shims/IsExternalInit.cs similarity index 100% rename from src/EventStore.Client/Common/Shims/IsExternalInit.cs rename to src/Kurrent.Client/Core/Common/Shims/IsExternalInit.cs diff --git a/src/EventStore.Client/Common/Shims/Range.cs b/src/Kurrent.Client/Core/Common/Shims/Range.cs similarity index 100% rename from src/EventStore.Client/Common/Shims/Range.cs rename to src/Kurrent.Client/Core/Common/Shims/Range.cs diff --git a/src/EventStore.Client/Common/Shims/TaskCompletionSource.cs b/src/Kurrent.Client/Core/Common/Shims/TaskCompletionSource.cs similarity index 100% rename from src/EventStore.Client/Common/Shims/TaskCompletionSource.cs rename to src/Kurrent.Client/Core/Common/Shims/TaskCompletionSource.cs diff --git a/src/EventStore.Client/DefaultRequestVersionHandler.cs b/src/Kurrent.Client/Core/DefaultRequestVersionHandler.cs similarity index 100% rename from src/EventStore.Client/DefaultRequestVersionHandler.cs rename to src/Kurrent.Client/Core/DefaultRequestVersionHandler.cs diff --git a/src/EventStore.Client/EndPointExtensions.cs b/src/Kurrent.Client/Core/EndPointExtensions.cs similarity index 100% rename from src/EventStore.Client/EndPointExtensions.cs rename to src/Kurrent.Client/Core/EndPointExtensions.cs diff --git a/src/EventStore.Client/EventData.cs b/src/Kurrent.Client/Core/EventData.cs similarity index 100% rename from src/EventStore.Client/EventData.cs rename to src/Kurrent.Client/Core/EventData.cs diff --git a/src/EventStore.Client/EventRecord.cs b/src/Kurrent.Client/Core/EventRecord.cs similarity index 97% rename from src/EventStore.Client/EventRecord.cs rename to src/Kurrent.Client/Core/EventRecord.cs index 67a7b04cf..531362661 100644 --- a/src/EventStore.Client/EventRecord.cs +++ b/src/Kurrent.Client/Core/EventRecord.cs @@ -1,6 +1,3 @@ -using System; -using System.Collections.Generic; - namespace EventStore.Client { /// /// Represents a previously written event. diff --git a/src/EventStore.Client/EventTypeFilter.cs b/src/Kurrent.Client/Core/EventTypeFilter.cs similarity index 100% rename from src/EventStore.Client/EventTypeFilter.cs rename to src/Kurrent.Client/Core/EventTypeFilter.cs diff --git a/src/EventStore.Client/Exceptions/AccessDeniedException.cs b/src/Kurrent.Client/Core/Exceptions/AccessDeniedException.cs similarity index 100% rename from src/EventStore.Client/Exceptions/AccessDeniedException.cs rename to src/Kurrent.Client/Core/Exceptions/AccessDeniedException.cs diff --git a/src/EventStore.Client/Exceptions/ConnectionString/ConnectionStringParseException.cs b/src/Kurrent.Client/Core/Exceptions/ConnectionString/ConnectionStringParseException.cs similarity index 85% rename from src/EventStore.Client/Exceptions/ConnectionString/ConnectionStringParseException.cs rename to src/Kurrent.Client/Core/Exceptions/ConnectionString/ConnectionStringParseException.cs index cb79f161d..2cb8c1ac5 100644 --- a/src/EventStore.Client/Exceptions/ConnectionString/ConnectionStringParseException.cs +++ b/src/Kurrent.Client/Core/Exceptions/ConnectionString/ConnectionStringParseException.cs @@ -2,7 +2,7 @@ namespace EventStore.Client { /// - /// The base exception that is thrown when an EventStoreDB connection string could not be parsed. + /// The base exception that is thrown when an KurrentDB connection string could not be parsed. /// public class ConnectionStringParseException : Exception { /// diff --git a/src/EventStore.Client/Exceptions/ConnectionString/DuplicateKeyException.cs b/src/Kurrent.Client/Core/Exceptions/ConnectionString/DuplicateKeyException.cs similarity index 77% rename from src/EventStore.Client/Exceptions/ConnectionString/DuplicateKeyException.cs rename to src/Kurrent.Client/Core/Exceptions/ConnectionString/DuplicateKeyException.cs index 4027d08e8..5cc3c3812 100644 --- a/src/EventStore.Client/Exceptions/ConnectionString/DuplicateKeyException.cs +++ b/src/Kurrent.Client/Core/Exceptions/ConnectionString/DuplicateKeyException.cs @@ -1,6 +1,6 @@ namespace EventStore.Client { /// - /// The exception that is thrown when a key in the EventStoreDB connection string is duplicated. + /// The exception that is thrown when a key in the KurrentDB connection string is duplicated. /// public class DuplicateKeyException : ConnectionStringParseException { /// diff --git a/src/EventStore.Client/Exceptions/ConnectionString/InvalidClientCertificateException.cs b/src/Kurrent.Client/Core/Exceptions/ConnectionString/InvalidClientCertificateException.cs similarity index 90% rename from src/EventStore.Client/Exceptions/ConnectionString/InvalidClientCertificateException.cs rename to src/Kurrent.Client/Core/Exceptions/ConnectionString/InvalidClientCertificateException.cs index 8415742f8..1caf9f9fb 100644 --- a/src/EventStore.Client/Exceptions/ConnectionString/InvalidClientCertificateException.cs +++ b/src/Kurrent.Client/Core/Exceptions/ConnectionString/InvalidClientCertificateException.cs @@ -1,6 +1,6 @@ namespace EventStore.Client { /// - /// The exception that is thrown when a certificate is invalid or not found in the EventStoreDB connection string. + /// The exception that is thrown when a certificate is invalid or not found in the KurrentDB connection string. /// public class InvalidClientCertificateException : ConnectionStringParseException { /// @@ -11,4 +11,4 @@ public class InvalidClientCertificateException : ConnectionStringParseException public InvalidClientCertificateException(string message, Exception? innerException = null) : base(message, innerException) { } } -} \ No newline at end of file +} diff --git a/src/EventStore.Client/Exceptions/ConnectionString/InvalidHostException.cs b/src/Kurrent.Client/Core/Exceptions/ConnectionString/InvalidHostException.cs similarity index 91% rename from src/EventStore.Client/Exceptions/ConnectionString/InvalidHostException.cs rename to src/Kurrent.Client/Core/Exceptions/ConnectionString/InvalidHostException.cs index 27ba8f615..696a81c32 100644 --- a/src/EventStore.Client/Exceptions/ConnectionString/InvalidHostException.cs +++ b/src/Kurrent.Client/Core/Exceptions/ConnectionString/InvalidHostException.cs @@ -1,6 +1,6 @@ namespace EventStore.Client { /// - /// The exception that is thrown when there is an invalid host in the EventStoreDB connection string. + /// The exception that is thrown when there is an invalid host in the KurrentDB connection string. /// public class InvalidHostException : ConnectionStringParseException { /// diff --git a/src/EventStore.Client/Exceptions/ConnectionString/InvalidKeyValuePairException.cs b/src/Kurrent.Client/Core/Exceptions/ConnectionString/InvalidKeyValuePairException.cs similarity index 90% rename from src/EventStore.Client/Exceptions/ConnectionString/InvalidKeyValuePairException.cs rename to src/Kurrent.Client/Core/Exceptions/ConnectionString/InvalidKeyValuePairException.cs index 2e6fc58df..d00e08445 100644 --- a/src/EventStore.Client/Exceptions/ConnectionString/InvalidKeyValuePairException.cs +++ b/src/Kurrent.Client/Core/Exceptions/ConnectionString/InvalidKeyValuePairException.cs @@ -1,6 +1,6 @@ namespace EventStore.Client { /// - /// The exception that is thrown when an invalid key value pair is found in an EventStoreDB connection string. + /// The exception that is thrown when an invalid key value pair is found in an KurrentDB connection string. /// public class InvalidKeyValuePairException : ConnectionStringParseException { /// diff --git a/src/EventStore.Client/Exceptions/ConnectionString/InvalidSchemeException.cs b/src/Kurrent.Client/Core/Exceptions/ConnectionString/InvalidSchemeException.cs similarity index 92% rename from src/EventStore.Client/Exceptions/ConnectionString/InvalidSchemeException.cs rename to src/Kurrent.Client/Core/Exceptions/ConnectionString/InvalidSchemeException.cs index 766c13f37..3b5cf2b18 100644 --- a/src/EventStore.Client/Exceptions/ConnectionString/InvalidSchemeException.cs +++ b/src/Kurrent.Client/Core/Exceptions/ConnectionString/InvalidSchemeException.cs @@ -1,6 +1,6 @@ namespace EventStore.Client { /// - /// The exception that is thrown when an invalid scheme is defined in the EventStoreDB connection string. + /// The exception that is thrown when an invalid scheme is defined in the KurrentDB connection string. /// public class InvalidSchemeException : ConnectionStringParseException { /// diff --git a/src/EventStore.Client/Exceptions/ConnectionString/InvalidSettingException.cs b/src/Kurrent.Client/Core/Exceptions/ConnectionString/InvalidSettingException.cs similarity index 90% rename from src/EventStore.Client/Exceptions/ConnectionString/InvalidSettingException.cs rename to src/Kurrent.Client/Core/Exceptions/ConnectionString/InvalidSettingException.cs index 0bb5da667..71dcc6edc 100644 --- a/src/EventStore.Client/Exceptions/ConnectionString/InvalidSettingException.cs +++ b/src/Kurrent.Client/Core/Exceptions/ConnectionString/InvalidSettingException.cs @@ -1,6 +1,6 @@ namespace EventStore.Client { /// - /// The exception that is thrown when an invalid setting is found in an EventStoreDB connection string. + /// The exception that is thrown when an invalid setting is found in an KurrentDB connection string. /// public class InvalidSettingException : ConnectionStringParseException { /// diff --git a/src/EventStore.Client/Exceptions/ConnectionString/InvalidUserCredentialsException.cs b/src/Kurrent.Client/Core/Exceptions/ConnectionString/InvalidUserCredentialsException.cs similarity index 86% rename from src/EventStore.Client/Exceptions/ConnectionString/InvalidUserCredentialsException.cs rename to src/Kurrent.Client/Core/Exceptions/ConnectionString/InvalidUserCredentialsException.cs index bd515fee4..1d4544a61 100644 --- a/src/EventStore.Client/Exceptions/ConnectionString/InvalidUserCredentialsException.cs +++ b/src/Kurrent.Client/Core/Exceptions/ConnectionString/InvalidUserCredentialsException.cs @@ -1,6 +1,6 @@ namespace EventStore.Client { /// - /// The exception that is thrown when an invalid is specified in the EventStoreDB connection string. + /// The exception that is thrown when an invalid is specified in the KurrentDB connection string. /// public class InvalidUserCredentialsException : ConnectionStringParseException { /// diff --git a/src/EventStore.Client/Exceptions/ConnectionString/NoSchemeException.cs b/src/Kurrent.Client/Core/Exceptions/ConnectionString/NoSchemeException.cs similarity index 90% rename from src/EventStore.Client/Exceptions/ConnectionString/NoSchemeException.cs rename to src/Kurrent.Client/Core/Exceptions/ConnectionString/NoSchemeException.cs index 7551ad467..08432be97 100644 --- a/src/EventStore.Client/Exceptions/ConnectionString/NoSchemeException.cs +++ b/src/Kurrent.Client/Core/Exceptions/ConnectionString/NoSchemeException.cs @@ -1,6 +1,6 @@ namespace EventStore.Client { /// - /// The exception that is thrown when no scheme was specified in the EventStoreDB connection string. + /// The exception that is thrown when no scheme was specified in the KurrentDB connection string. /// public class NoSchemeException : ConnectionStringParseException { /// diff --git a/src/EventStore.Client/Exceptions/DiscoveryException.cs b/src/Kurrent.Client/Core/Exceptions/DiscoveryException.cs similarity index 100% rename from src/EventStore.Client/Exceptions/DiscoveryException.cs rename to src/Kurrent.Client/Core/Exceptions/DiscoveryException.cs diff --git a/src/EventStore.Client/Exceptions/NotAuthenticatedException.cs b/src/Kurrent.Client/Core/Exceptions/NotAuthenticatedException.cs similarity index 100% rename from src/EventStore.Client/Exceptions/NotAuthenticatedException.cs rename to src/Kurrent.Client/Core/Exceptions/NotAuthenticatedException.cs diff --git a/src/EventStore.Client/Exceptions/NotLeaderException.cs b/src/Kurrent.Client/Core/Exceptions/NotLeaderException.cs similarity index 100% rename from src/EventStore.Client/Exceptions/NotLeaderException.cs rename to src/Kurrent.Client/Core/Exceptions/NotLeaderException.cs diff --git a/src/EventStore.Client/Exceptions/RequiredMetadataPropertyMissingException.cs b/src/Kurrent.Client/Core/Exceptions/RequiredMetadataPropertyMissingException.cs similarity index 100% rename from src/EventStore.Client/Exceptions/RequiredMetadataPropertyMissingException.cs rename to src/Kurrent.Client/Core/Exceptions/RequiredMetadataPropertyMissingException.cs diff --git a/src/EventStore.Client/Exceptions/ScavengeNotFoundException.cs b/src/Kurrent.Client/Core/Exceptions/ScavengeNotFoundException.cs similarity index 100% rename from src/EventStore.Client/Exceptions/ScavengeNotFoundException.cs rename to src/Kurrent.Client/Core/Exceptions/ScavengeNotFoundException.cs diff --git a/src/EventStore.Client/Exceptions/StreamDeletedException.cs b/src/Kurrent.Client/Core/Exceptions/StreamDeletedException.cs similarity index 100% rename from src/EventStore.Client/Exceptions/StreamDeletedException.cs rename to src/Kurrent.Client/Core/Exceptions/StreamDeletedException.cs diff --git a/src/EventStore.Client/Exceptions/StreamNotFoundException.cs b/src/Kurrent.Client/Core/Exceptions/StreamNotFoundException.cs similarity index 100% rename from src/EventStore.Client/Exceptions/StreamNotFoundException.cs rename to src/Kurrent.Client/Core/Exceptions/StreamNotFoundException.cs diff --git a/src/EventStore.Client/Exceptions/UserNotFoundException.cs b/src/Kurrent.Client/Core/Exceptions/UserNotFoundException.cs similarity index 100% rename from src/EventStore.Client/Exceptions/UserNotFoundException.cs rename to src/Kurrent.Client/Core/Exceptions/UserNotFoundException.cs diff --git a/src/EventStore.Client/Exceptions/WrongExpectedVersionException.cs b/src/Kurrent.Client/Core/Exceptions/WrongExpectedVersionException.cs similarity index 100% rename from src/EventStore.Client/Exceptions/WrongExpectedVersionException.cs rename to src/Kurrent.Client/Core/Exceptions/WrongExpectedVersionException.cs diff --git a/src/EventStore.Client/FromAll.cs b/src/Kurrent.Client/Core/FromAll.cs similarity index 100% rename from src/EventStore.Client/FromAll.cs rename to src/Kurrent.Client/Core/FromAll.cs diff --git a/src/EventStore.Client/FromStream.cs b/src/Kurrent.Client/Core/FromStream.cs similarity index 100% rename from src/EventStore.Client/FromStream.cs rename to src/Kurrent.Client/Core/FromStream.cs diff --git a/src/EventStore.Client/GossipChannelSelector.cs b/src/Kurrent.Client/Core/GossipChannelSelector.cs similarity index 97% rename from src/EventStore.Client/GossipChannelSelector.cs rename to src/Kurrent.Client/Core/GossipChannelSelector.cs index 633ab0d84..5471120b6 100644 --- a/src/EventStore.Client/GossipChannelSelector.cs +++ b/src/Kurrent.Client/Core/GossipChannelSelector.cs @@ -10,14 +10,14 @@ namespace EventStore.Client { // Thread safe internal class GossipChannelSelector : IChannelSelector { - private readonly EventStoreClientSettings _settings; + private readonly KurrentClientSettings _settings; private readonly ChannelCache _channels; private readonly IGossipClient _gossipClient; private readonly ILogger _log; private readonly NodeSelector _nodeSelector; public GossipChannelSelector( - EventStoreClientSettings settings, + KurrentClientSettings settings, ChannelCache channelCache, IGossipClient gossipClient) { diff --git a/src/EventStore.Client/GrpcGossipClient.cs b/src/Kurrent.Client/Core/GrpcGossipClient.cs similarity index 81% rename from src/EventStore.Client/GrpcGossipClient.cs rename to src/Kurrent.Client/Core/GrpcGossipClient.cs index 655d05b5f..5291bfe6c 100644 --- a/src/EventStore.Client/GrpcGossipClient.cs +++ b/src/Kurrent.Client/Core/GrpcGossipClient.cs @@ -6,9 +6,9 @@ namespace EventStore.Client { internal class GrpcGossipClient : IGossipClient { - private readonly EventStoreClientSettings _settings; + private readonly KurrentClientSettings _settings; - public GrpcGossipClient(EventStoreClientSettings settings) { + public GrpcGossipClient(KurrentClientSettings settings) { _settings = settings; } @@ -16,7 +16,7 @@ public GrpcGossipClient(EventStoreClientSettings settings) { var client = new Gossip.Gossip.GossipClient(channel); using var call = client.ReadAsync( new Empty(), - EventStoreCallOptions.CreateNonStreaming(_settings, ct)); + KurrentCallOptions.CreateNonStreaming(_settings, ct)); var result = await call.ResponseAsync.ConfigureAwait(false); return new(result.Members.Select(x => diff --git a/src/EventStore.Client/GrpcServerCapabilitiesClient.cs b/src/Kurrent.Client/Core/GrpcServerCapabilitiesClient.cs similarity index 93% rename from src/EventStore.Client/GrpcServerCapabilitiesClient.cs rename to src/Kurrent.Client/Core/GrpcServerCapabilitiesClient.cs index 02cd41222..1dc29dce0 100644 --- a/src/EventStore.Client/GrpcServerCapabilitiesClient.cs +++ b/src/Kurrent.Client/Core/GrpcServerCapabilitiesClient.cs @@ -5,9 +5,9 @@ namespace EventStore.Client { internal class GrpcServerCapabilitiesClient : IServerCapabilitiesClient { - private readonly EventStoreClientSettings _settings; + private readonly KurrentClientSettings _settings; - public GrpcServerCapabilitiesClient(EventStoreClientSettings settings) { + public GrpcServerCapabilitiesClient(KurrentClientSettings settings) { _settings = settings; } @@ -18,7 +18,7 @@ public async Task GetAsync( var client = new ServerFeatures.ServerFeatures.ServerFeaturesClient(callInvoker); using var call = client.GetSupportedMethodsAsync( new(), - EventStoreCallOptions.CreateNonStreaming( + KurrentCallOptions.CreateNonStreaming( _settings, _settings.ConnectivitySettings.GossipTimeout, null, @@ -31,7 +31,7 @@ public async Task GetAsync( var supportsPersistentSubscriptionsRestartSubsystem = false; var supportsPersistentSubscriptionsReplayParked = false; var supportsPersistentSubscriptionsList = false; - + var response = await call.ResponseAsync.ConfigureAwait(false); foreach (var supportedMethod in response.Methods) { diff --git a/src/EventStore.Client/HashCode.cs b/src/Kurrent.Client/Core/HashCode.cs similarity index 100% rename from src/EventStore.Client/HashCode.cs rename to src/Kurrent.Client/Core/HashCode.cs diff --git a/src/EventStore.Client/HttpFallback.cs b/src/Kurrent.Client/Core/HttpFallback.cs similarity index 98% rename from src/EventStore.Client/HttpFallback.cs rename to src/Kurrent.Client/Core/HttpFallback.cs index 3e5420e9a..0f2bfe02d 100644 --- a/src/EventStore.Client/HttpFallback.cs +++ b/src/Kurrent.Client/Core/HttpFallback.cs @@ -13,7 +13,7 @@ internal class HttpFallback : IDisposable { private readonly UserCredentials? _defaultCredentials; private readonly string _addressScheme; - internal HttpFallback(EventStoreClientSettings settings) { + internal HttpFallback(KurrentClientSettings settings) { _addressScheme = settings.ConnectivitySettings.ResolvedAddressOrDefault.Scheme; _defaultCredentials = settings.DefaultCredentials; diff --git a/src/EventStore.Client/IChannelSelector.cs b/src/Kurrent.Client/Core/IChannelSelector.cs similarity index 100% rename from src/EventStore.Client/IChannelSelector.cs rename to src/Kurrent.Client/Core/IChannelSelector.cs diff --git a/src/EventStore.Client/IEventFilter.cs b/src/Kurrent.Client/Core/IEventFilter.cs similarity index 100% rename from src/EventStore.Client/IEventFilter.cs rename to src/Kurrent.Client/Core/IEventFilter.cs diff --git a/src/EventStore.Client/IGossipClient.cs b/src/Kurrent.Client/Core/IGossipClient.cs similarity index 100% rename from src/EventStore.Client/IGossipClient.cs rename to src/Kurrent.Client/Core/IGossipClient.cs diff --git a/src/EventStore.Client/IPosition.cs b/src/Kurrent.Client/Core/IPosition.cs similarity index 100% rename from src/EventStore.Client/IPosition.cs rename to src/Kurrent.Client/Core/IPosition.cs diff --git a/src/EventStore.Client/IServerCapabilitiesClient.cs b/src/Kurrent.Client/Core/IServerCapabilitiesClient.cs similarity index 100% rename from src/EventStore.Client/IServerCapabilitiesClient.cs rename to src/Kurrent.Client/Core/IServerCapabilitiesClient.cs diff --git a/src/EventStore.Client/Interceptors/ConnectionNameInterceptor.cs b/src/Kurrent.Client/Core/Interceptors/ConnectionNameInterceptor.cs similarity index 100% rename from src/EventStore.Client/Interceptors/ConnectionNameInterceptor.cs rename to src/Kurrent.Client/Core/Interceptors/ConnectionNameInterceptor.cs diff --git a/src/EventStore.Client/Interceptors/ReportLeaderInterceptor.cs b/src/Kurrent.Client/Core/Interceptors/ReportLeaderInterceptor.cs similarity index 100% rename from src/EventStore.Client/Interceptors/ReportLeaderInterceptor.cs rename to src/Kurrent.Client/Core/Interceptors/ReportLeaderInterceptor.cs diff --git a/src/EventStore.Client/Interceptors/TypedExceptionInterceptor.cs b/src/Kurrent.Client/Core/Interceptors/TypedExceptionInterceptor.cs similarity index 100% rename from src/EventStore.Client/Interceptors/TypedExceptionInterceptor.cs rename to src/Kurrent.Client/Core/Interceptors/TypedExceptionInterceptor.cs diff --git a/src/EventStore.Client/EventStoreClientBase.cs b/src/Kurrent.Client/Core/KurrentClientBase.cs similarity index 93% rename from src/EventStore.Client/EventStoreClientBase.cs rename to src/Kurrent.Client/Core/KurrentClientBase.cs index 2b4a5b2f6..923c6f334 100644 --- a/src/EventStore.Client/EventStoreClientBase.cs +++ b/src/Kurrent.Client/Core/KurrentClientBase.cs @@ -5,9 +5,9 @@ namespace EventStore.Client { /// - /// The base class used by clients used to communicate with the EventStoreDB. + /// The base class used by clients used to communicate with the KurrentDB. /// - public abstract class EventStoreClientBase : + public abstract class KurrentClientBase : IDisposable, // for grpc.net we can dispose synchronously, but not for grpc.core IAsyncDisposable { private readonly Dictionary> _exceptionMap; @@ -19,15 +19,15 @@ public abstract class EventStoreClientBase : /// The name of the connection. public string ConnectionName { get; } - /// The . - protected EventStoreClientSettings Settings { get; } + /// The . + protected KurrentClientSettings Settings { get; } - /// Constructs a new . - protected EventStoreClientBase( - EventStoreClientSettings? settings, + /// Constructs a new . + protected KurrentClientBase( + KurrentClientSettings? settings, Dictionary> exceptionMap ) { - Settings = settings ?? new EventStoreClientSettings(); + Settings = settings ?? new KurrentClientSettings(); _exceptionMap = exceptionMap; _cts = new CancellationTokenSource(); _channelCache = new(Settings); diff --git a/src/EventStore.Client/EventStoreClientConnectivitySettings.cs b/src/Kurrent.Client/Core/KurrentClientConnectivitySettings.cs similarity index 89% rename from src/EventStore.Client/EventStoreClientConnectivitySettings.cs rename to src/Kurrent.Client/Core/KurrentClientConnectivitySettings.cs index 92890d2f2..4ea90dcaf 100644 --- a/src/EventStore.Client/EventStoreClientConnectivitySettings.cs +++ b/src/Kurrent.Client/Core/KurrentClientConnectivitySettings.cs @@ -4,15 +4,15 @@ namespace EventStore.Client { /// - /// A class used to describe how to connect to an instance of EventStoreDB. + /// A class used to describe how to connect to an instance of KurrentDB. /// - public class EventStoreClientConnectivitySettings { + public class KurrentClientConnectivitySettings { private const int DefaultPort = 2113; private bool _insecure; private Uri? _address; /// - /// The of the EventStoreDB. Use this when connecting to a single node. + /// The of the KurrentDB. Use this when connecting to a single node. /// public Uri? Address { get => IsSingleNode ? _address : null; @@ -84,7 +84,7 @@ public Uri? Address { public TimeSpan KeepAliveTimeout { get; set; } = TimeSpan.FromSeconds(10); /// - /// True if pointing to a single EventStoreDB node. + /// True if pointing to a single KurrentDB node. /// public bool IsSingleNode => GossipSeeds.Length == 0; @@ -113,9 +113,9 @@ public bool Insecure { public X509Certificate2? ClientCertificate { get; set; } /// - /// The default . + /// The default . /// - public static EventStoreClientConnectivitySettings Default => new EventStoreClientConnectivitySettings { + public static KurrentClientConnectivitySettings Default => new KurrentClientConnectivitySettings { MaxDiscoverAttempts = 10, GossipTimeout = TimeSpan.FromSeconds(5), DiscoveryInterval = TimeSpan.FromMilliseconds(100), diff --git a/src/EventStore.Client/EventStoreClientOperationOptions.cs b/src/Kurrent.Client/Core/KurrentClientOperationOptions.cs similarity index 78% rename from src/EventStore.Client/EventStoreClientOperationOptions.cs rename to src/Kurrent.Client/Core/KurrentClientOperationOptions.cs index 94561e213..36c8d5869 100644 --- a/src/EventStore.Client/EventStoreClientOperationOptions.cs +++ b/src/Kurrent.Client/Core/KurrentClientOperationOptions.cs @@ -6,7 +6,7 @@ namespace EventStore.Client { /// /// A class representing the options to apply to an individual operation. /// - public class EventStoreClientOperationOptions { + public class KurrentClientOperationOptions { /// /// Whether or not to immediately throw a when an append fails. /// @@ -24,9 +24,9 @@ public class EventStoreClientOperationOptions { null!; /// - /// The default . + /// The default . /// - public static EventStoreClientOperationOptions Default => new() { + public static KurrentClientOperationOptions Default => new() { ThrowOnAppendFailure = true, GetAuthenticationHeaderValue = (userCredentials, _) => new ValueTask(userCredentials.ToString()), BatchAppendSize = 3 * 1024 * 1024 @@ -34,10 +34,10 @@ public class EventStoreClientOperationOptions { /// - /// Clones a copy of the current . + /// Clones a copy of the current . /// /// - public EventStoreClientOperationOptions Clone() => new() { + public KurrentClientOperationOptions Clone() => new() { ThrowOnAppendFailure = ThrowOnAppendFailure, GetAuthenticationHeaderValue = GetAuthenticationHeaderValue, BatchAppendSize = BatchAppendSize diff --git a/src/EventStore.Client/EventStoreClientSettings.ConnectionString.cs b/src/Kurrent.Client/Core/KurrentClientSettings.ConnectionString.cs similarity index 85% rename from src/EventStore.Client/EventStoreClientSettings.ConnectionString.cs rename to src/Kurrent.Client/Core/KurrentClientSettings.ConnectionString.cs index 48eb84956..c730b7b5a 100644 --- a/src/EventStore.Client/EventStoreClientSettings.ConnectionString.cs +++ b/src/Kurrent.Client/Core/KurrentClientSettings.ConnectionString.cs @@ -1,22 +1,17 @@ -using System; -using System.Collections.Generic; -using System.Linq; using System.Net; using System.Net.Http; -using System.Net.Security; -using System.Security.Authentication; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using Timeout_ = System.Threading.Timeout; namespace EventStore.Client { - public partial class EventStoreClientSettings { + public partial class KurrentClientSettings { /// /// Creates client settings from a connection string /// /// /// - public static EventStoreClientSettings Create(string connectionString) => + public static KurrentClientSettings Create(string connectionString) => ConnectionStringParser.Parse(connectionString); private static class ConnectionStringParser { @@ -41,13 +36,13 @@ private static class ConnectionStringParser { private const string ThrowOnAppendFailure = nameof(ThrowOnAppendFailure); private const string KeepAliveInterval = nameof(KeepAliveInterval); private const string KeepAliveTimeout = nameof(KeepAliveTimeout); - private const string UserCertFile = nameof(UserCertFile); + private const string UserCertFile = nameof(UserCertFile); private const string UserKeyFile = nameof(UserKeyFile); private const string UriSchemeDiscover = "esdb+discover"; private static readonly string[] Schemes = { "esdb", UriSchemeDiscover }; - private static readonly int DefaultPort = EventStoreClientConnectivitySettings.Default.ResolvedAddressOrDefault.Port; + private static readonly int DefaultPort = KurrentClientConnectivitySettings.Default.ResolvedAddressOrDefault.Port; private static readonly bool DefaultUseTls = true; private static readonly Dictionary SettingsType = @@ -64,11 +59,11 @@ private static class ConnectionStringParser { { ThrowOnAppendFailure, typeof(bool) }, { KeepAliveInterval, typeof(int) }, { KeepAliveTimeout, typeof(int) }, - { UserCertFile, typeof(string)}, - { UserKeyFile, typeof(string)}, + { UserCertFile, typeof(string) }, + { UserKeyFile, typeof(string) }, }; - public static EventStoreClientSettings Parse(string connectionString) { + public static KurrentClientSettings Parse(string connectionString) { var currentIndex = 0; var schemeIndex = connectionString.IndexOf(SchemeSeparator, currentIndex, StringComparison.Ordinal); if (schemeIndex == -1) @@ -77,10 +72,10 @@ public static EventStoreClientSettings Parse(string connectionString) { var scheme = ParseScheme(connectionString.Substring(0, schemeIndex)); currentIndex = schemeIndex + SchemeSeparator.Length; - var userInfoIndex = connectionString.IndexOf(UserInfoSeparator, currentIndex, StringComparison.Ordinal); - (string user, string pass)? userInfo = null; + var userInfoIndex = connectionString.IndexOf(UserInfoSeparator, currentIndex, StringComparison.Ordinal); + (string user, string pass)? userInfo = null; if (userInfoIndex != -1) { - userInfo = ParseUserInfo(connectionString.Substring(currentIndex, userInfoIndex - currentIndex)); + userInfo = ParseUserInfo(connectionString.Substring(currentIndex, userInfoIndex - currentIndex)); currentIndex = userInfoIndex + UserInfoSeparator.Length; } @@ -93,7 +88,7 @@ public static EventStoreClientSettings Parse(string connectionString) { if (questionMarkIndex == -1) questionMarkIndex = int.MaxValue; var hostSeparatorIndex = Math.Min(Math.Min(slashIndex, questionMarkIndex), endIndex); - var hosts = ParseHosts(connectionString.Substring(currentIndex, hostSeparatorIndex - currentIndex)); + var hosts = ParseHosts(connectionString.Substring(currentIndex, hostSeparatorIndex - currentIndex)); currentIndex = hostSeparatorIndex; string path = ""; @@ -117,13 +112,13 @@ public static EventStoreClientSettings Parse(string connectionString) { return CreateSettings(scheme, userInfo, hosts, options); } - private static EventStoreClientSettings CreateSettings( + private static KurrentClientSettings CreateSettings( string scheme, (string user, string pass)? userInfo, EndPoint[] hosts, Dictionary options ) { - var settings = new EventStoreClientSettings { - ConnectivitySettings = EventStoreClientConnectivitySettings.Default, - OperationOptions = EventStoreClientOperationOptions.Default + var settings = new KurrentClientSettings { + ConnectivitySettings = KurrentClientConnectivitySettings.Default, + OperationOptions = KurrentClientOperationOptions.Default }; if (userInfo.HasValue) @@ -163,11 +158,11 @@ private static EventStoreClientSettings CreateSettings( if (typedOptions.TryGetValue(NodePreference, out object? nodePreference)) { settings.ConnectivitySettings.NodePreference = ((string)nodePreference).ToLowerInvariant() switch { - "leader" => EventStore.Client.NodePreference.Leader, - "follower" => EventStore.Client.NodePreference.Follower, - "random" => EventStore.Client.NodePreference.Random, + "leader" => EventStore.Client.NodePreference.Leader, + "follower" => EventStore.Client.NodePreference.Follower, + "random" => EventStore.Client.NodePreference.Random, "readonlyreplica" => EventStore.Client.NodePreference.ReadOnlyReplica, - _ => throw new InvalidSettingException($"Invalid NodePreference: {nodePreference}") + _ => throw new InvalidSettingException($"Invalid NodePreference: {nodePreference}") }; } @@ -184,17 +179,17 @@ private static EventStoreClientSettings CreateSettings( if (typedOptions.TryGetValue(KeepAliveInterval, out var keepAliveIntervalMs)) { settings.ConnectivitySettings.KeepAliveInterval = keepAliveIntervalMs switch { - -1 => Timeout_.InfiniteTimeSpan, + -1 => Timeout_.InfiniteTimeSpan, int value and >= 0 => TimeSpan.FromMilliseconds(value), - _ => throw new InvalidSettingException($"Invalid KeepAliveInterval: {keepAliveIntervalMs}") + _ => throw new InvalidSettingException($"Invalid KeepAliveInterval: {keepAliveIntervalMs}") }; } if (typedOptions.TryGetValue(KeepAliveTimeout, out var keepAliveTimeoutMs)) { settings.ConnectivitySettings.KeepAliveTimeout = keepAliveTimeoutMs switch { - -1 => Timeout_.InfiniteTimeSpan, + -1 => Timeout_.InfiniteTimeSpan, int value and >= 0 => TimeSpan.FromMilliseconds(value), - _ => throw new InvalidSettingException($"Invalid KeepAliveTimeout: {keepAliveTimeoutMs}") + _ => throw new InvalidSettingException($"Invalid KeepAliveTimeout: {keepAliveTimeoutMs}") }; } @@ -221,7 +216,11 @@ private static EventStoreClientSettings CreateSettings( } try { +#if NET9_0_OR_GREATER + settings.ConnectivitySettings.TlsCaFile = X509CertificateLoader.LoadCertificateFromFile(tlsCaFilePath); +#else settings.ConnectivitySettings.TlsCaFile = new X509Certificate2(tlsCaFilePath); +#endif } catch (CryptographicException) { throw new InvalidClientCertificateException("Failed to load certificate. Invalid file format."); } @@ -239,9 +238,9 @@ HttpMessageHandler CreateDefaultHandler() { return settings.CreateHttpMessageHandler.Invoke(); var handler = new WinHttpHandler { - TcpKeepAliveEnabled = true, - TcpKeepAliveTime = settings.ConnectivitySettings.KeepAliveTimeout, - TcpKeepAliveInterval = settings.ConnectivitySettings.KeepAliveInterval, + TcpKeepAliveEnabled = true, + TcpKeepAliveTime = settings.ConnectivitySettings.KeepAliveTimeout, + TcpKeepAliveInterval = settings.ConnectivitySettings.KeepAliveInterval, EnableMultipleHttp2Connections = true }; @@ -285,7 +284,7 @@ HttpMessageHandler CreateDefaultHandler() { true when settings.ConnectivitySettings.TlsCaFile is not null => (sender, certificate, chain, errors) => { if (certificate is not X509Certificate2 peerCertificate || chain is null) return false; - chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust; + chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust; chain.ChainPolicy.CustomTrustStore.Add(settings.ConnectivitySettings.TlsCaFile); return chain.Build(peerCertificate); }, @@ -297,7 +296,7 @@ HttpMessageHandler CreateDefaultHandler() { #endif } - static void ConfigureClientCertificate(EventStoreClientSettings settings, IReadOnlyDictionary options) { + static void ConfigureClientCertificate(KurrentClientSettings settings, IReadOnlyDictionary options) { var certPemFilePath = GetOptionValueAsString(UserCertFile); var keyPemFilePath = GetOptionValueAsString(UserKeyFile); @@ -318,8 +317,7 @@ static void ConfigureClientCertificate(EventStoreClientSettings settings, IReadO ); try { - settings.ConnectivitySettings.ClientCertificate = - X509Certificates.CreateFromPemFile(certPemFilePath, keyPemFilePath); + settings.ConnectivitySettings.ClientCertificate = X509Certificates.CreateFromPemFile(certPemFilePath, keyPemFilePath); } catch (Exception ex) { throw new InvalidClientCertificateException("Failed to create client certificate.", ex); } diff --git a/src/EventStore.Client/EventStoreClientSettings.cs b/src/Kurrent.Client/Core/KurrentClientSettings.cs similarity index 74% rename from src/EventStore.Client/EventStoreClientSettings.cs rename to src/Kurrent.Client/Core/KurrentClientSettings.cs index f6a65219e..aed914074 100644 --- a/src/EventStore.Client/EventStoreClientSettings.cs +++ b/src/Kurrent.Client/Core/KurrentClientSettings.cs @@ -8,9 +8,9 @@ namespace EventStore.Client { /// - /// A class that represents the settings to use for operations made from an implementation of . + /// A class that represents the settings to use for operations made from an implementation of . /// - public partial class EventStoreClientSettings { + public partial class KurrentClientSettings { /// /// An optional list of s to use. /// @@ -37,16 +37,16 @@ public partial class EventStoreClientSettings { public ChannelCredentials? ChannelCredentials { get; set; } /// - /// The default to use. + /// The default to use. /// - public EventStoreClientOperationOptions OperationOptions { get; set; } = - EventStoreClientOperationOptions.Default; + public KurrentClientOperationOptions OperationOptions { get; set; } = + KurrentClientOperationOptions.Default; /// - /// The to use. + /// The to use. /// - public EventStoreClientConnectivitySettings ConnectivitySettings { get; set; } = - EventStoreClientConnectivitySettings.Default; + public KurrentClientConnectivitySettings ConnectivitySettings { get; set; } = + KurrentClientConnectivitySettings.Default; /// /// The optional to use if none have been supplied to the operation. diff --git a/src/EventStore.Client/NodePreference.cs b/src/Kurrent.Client/Core/NodePreference.cs similarity index 88% rename from src/EventStore.Client/NodePreference.cs rename to src/Kurrent.Client/Core/NodePreference.cs index a3f453eb3..530edb87d 100644 --- a/src/EventStore.Client/NodePreference.cs +++ b/src/Kurrent.Client/Core/NodePreference.cs @@ -1,6 +1,6 @@ namespace EventStore.Client { /// - /// Indicates the preferred EventStoreDB node type to connect to. + /// Indicates the preferred KurrentDB node type to connect to. /// public enum NodePreference { /// diff --git a/src/EventStore.Client/NodePreferenceComparers.cs b/src/Kurrent.Client/Core/NodePreferenceComparers.cs similarity index 100% rename from src/EventStore.Client/NodePreferenceComparers.cs rename to src/Kurrent.Client/Core/NodePreferenceComparers.cs diff --git a/src/EventStore.Client/NodeSelector.cs b/src/Kurrent.Client/Core/NodeSelector.cs similarity index 97% rename from src/EventStore.Client/NodeSelector.cs rename to src/Kurrent.Client/Core/NodeSelector.cs index 94c00cc56..661e1e190 100644 --- a/src/EventStore.Client/NodeSelector.cs +++ b/src/Kurrent.Client/Core/NodeSelector.cs @@ -26,7 +26,7 @@ internal class NodeSelector { private readonly Random _random; private readonly IComparer? _nodeStateComparer; - public NodeSelector(EventStoreClientSettings settings) { + public NodeSelector(KurrentClientSettings settings) { _random = new Random(0); _nodeStateComparer = settings.ConnectivitySettings.NodePreference switch { NodePreference.Leader => NodePreferenceComparers.Leader, diff --git a/src/EventStore.Client/Position.cs b/src/Kurrent.Client/Core/Position.cs similarity index 100% rename from src/EventStore.Client/Position.cs rename to src/Kurrent.Client/Core/Position.cs diff --git a/src/EventStore.Client/PrefixFilterExpression.cs b/src/Kurrent.Client/Core/PrefixFilterExpression.cs similarity index 100% rename from src/EventStore.Client/PrefixFilterExpression.cs rename to src/Kurrent.Client/Core/PrefixFilterExpression.cs diff --git a/src/EventStore.Client/ReconnectionRequired.cs b/src/Kurrent.Client/Core/ReconnectionRequired.cs similarity index 100% rename from src/EventStore.Client/ReconnectionRequired.cs rename to src/Kurrent.Client/Core/ReconnectionRequired.cs diff --git a/src/EventStore.Client/RegularFilterExpression.cs b/src/Kurrent.Client/Core/RegularFilterExpression.cs similarity index 100% rename from src/EventStore.Client/RegularFilterExpression.cs rename to src/Kurrent.Client/Core/RegularFilterExpression.cs diff --git a/src/EventStore.Client/ResolvedEvent.cs b/src/Kurrent.Client/Core/ResolvedEvent.cs similarity index 100% rename from src/EventStore.Client/ResolvedEvent.cs rename to src/Kurrent.Client/Core/ResolvedEvent.cs diff --git a/src/EventStore.Client/ServerCapabilities.cs b/src/Kurrent.Client/Core/ServerCapabilities.cs similarity index 100% rename from src/EventStore.Client/ServerCapabilities.cs rename to src/Kurrent.Client/Core/ServerCapabilities.cs diff --git a/src/EventStore.Client/SharingProvider.cs b/src/Kurrent.Client/Core/SharingProvider.cs similarity index 100% rename from src/EventStore.Client/SharingProvider.cs rename to src/Kurrent.Client/Core/SharingProvider.cs diff --git a/src/EventStore.Client/SingleNodeChannelSelector.cs b/src/Kurrent.Client/Core/SingleNodeChannelSelector.cs similarity index 96% rename from src/EventStore.Client/SingleNodeChannelSelector.cs rename to src/Kurrent.Client/Core/SingleNodeChannelSelector.cs index 79c3affb0..83449e689 100644 --- a/src/EventStore.Client/SingleNodeChannelSelector.cs +++ b/src/Kurrent.Client/Core/SingleNodeChannelSelector.cs @@ -12,7 +12,7 @@ internal class SingleNodeChannelSelector : IChannelSelector { private readonly DnsEndPoint _endPoint; public SingleNodeChannelSelector( - EventStoreClientSettings settings, + KurrentClientSettings settings, ChannelCache channelCache) { _log = settings.LoggerFactory?.CreateLogger() ?? diff --git a/src/EventStore.Client/SingleNodeHttpHandler.cs b/src/Kurrent.Client/Core/SingleNodeHttpHandler.cs similarity index 81% rename from src/EventStore.Client/SingleNodeHttpHandler.cs rename to src/Kurrent.Client/Core/SingleNodeHttpHandler.cs index b8560152e..0c346a00f 100644 --- a/src/EventStore.Client/SingleNodeHttpHandler.cs +++ b/src/Kurrent.Client/Core/SingleNodeHttpHandler.cs @@ -5,9 +5,9 @@ namespace EventStore.Client { internal class SingleNodeHttpHandler : DelegatingHandler { - private readonly EventStoreClientSettings _settings; + private readonly KurrentClientSettings _settings; - public SingleNodeHttpHandler(EventStoreClientSettings settings) { + public SingleNodeHttpHandler(KurrentClientSettings settings) { _settings = settings; } diff --git a/src/EventStore.Client/StreamFilter.cs b/src/Kurrent.Client/Core/StreamFilter.cs similarity index 100% rename from src/EventStore.Client/StreamFilter.cs rename to src/Kurrent.Client/Core/StreamFilter.cs diff --git a/src/EventStore.Client/StreamIdentifier.cs b/src/Kurrent.Client/Core/StreamIdentifier.cs similarity index 94% rename from src/EventStore.Client/StreamIdentifier.cs rename to src/Kurrent.Client/Core/StreamIdentifier.cs index 73e0ee25e..9ca6c9e7e 100644 --- a/src/EventStore.Client/StreamIdentifier.cs +++ b/src/Kurrent.Client/Core/StreamIdentifier.cs @@ -3,7 +3,7 @@ namespace EventStore.Client { #pragma warning disable 1591 - public partial class StreamIdentifier { + internal partial class StreamIdentifier { private string? _cached; public static implicit operator string?(StreamIdentifier? source) { diff --git a/src/EventStore.Client/StreamPosition.cs b/src/Kurrent.Client/Core/StreamPosition.cs similarity index 100% rename from src/EventStore.Client/StreamPosition.cs rename to src/Kurrent.Client/Core/StreamPosition.cs diff --git a/src/EventStore.Client/StreamRevision.cs b/src/Kurrent.Client/Core/StreamRevision.cs similarity index 100% rename from src/EventStore.Client/StreamRevision.cs rename to src/Kurrent.Client/Core/StreamRevision.cs diff --git a/src/EventStore.Client/StreamState.cs b/src/Kurrent.Client/Core/StreamState.cs similarity index 100% rename from src/EventStore.Client/StreamState.cs rename to src/Kurrent.Client/Core/StreamState.cs diff --git a/src/EventStore.Client/SubscriptionDroppedReason.cs b/src/Kurrent.Client/Core/SubscriptionDroppedReason.cs similarity index 100% rename from src/EventStore.Client/SubscriptionDroppedReason.cs rename to src/Kurrent.Client/Core/SubscriptionDroppedReason.cs diff --git a/src/EventStore.Client/SystemRoles.cs b/src/Kurrent.Client/Core/SystemRoles.cs similarity index 100% rename from src/EventStore.Client/SystemRoles.cs rename to src/Kurrent.Client/Core/SystemRoles.cs diff --git a/src/EventStore.Client/SystemStreams.cs b/src/Kurrent.Client/Core/SystemStreams.cs similarity index 90% rename from src/EventStore.Client/SystemStreams.cs rename to src/Kurrent.Client/Core/SystemStreams.cs index 67899794b..c8b72503a 100644 --- a/src/EventStore.Client/SystemStreams.cs +++ b/src/Kurrent.Client/Core/SystemStreams.cs @@ -4,12 +4,12 @@ namespace EventStore.Client { /// public static class SystemStreams { /// - /// A stream containing all events in the EventStoreDB transaction file. + /// A stream containing all events in the KurrentDB transaction file. /// public const string AllStream = "$all"; /// - /// A stream containing links pointing to each stream in the EventStoreDB. + /// A stream containing links pointing to each stream in the KurrentDB. /// public const string StreamsStream = "$streams"; diff --git a/src/EventStore.Client/TaskExtensions.cs b/src/Kurrent.Client/Core/TaskExtensions.cs similarity index 100% rename from src/EventStore.Client/TaskExtensions.cs rename to src/Kurrent.Client/Core/TaskExtensions.cs diff --git a/src/EventStore.Client/UserCredentials.cs b/src/Kurrent.Client/Core/UserCredentials.cs similarity index 95% rename from src/EventStore.Client/UserCredentials.cs rename to src/Kurrent.Client/Core/UserCredentials.cs index d944d90d7..6f9012951 100644 --- a/src/EventStore.Client/UserCredentials.cs +++ b/src/Kurrent.Client/Core/UserCredentials.cs @@ -5,7 +5,7 @@ namespace EventStore.Client { /// /// Represents either a username/password pair or a JWT token used for authentication and - /// authorization to perform operations on the EventStoreDB. + /// authorization to perform operations on the KurrentDB. /// public class UserCredentials { // ReSharper disable once InconsistentNaming @@ -51,4 +51,4 @@ public UserCredentials(string bearerToken) { /// public static implicit operator string(UserCredentials self) => self.ToString(); } -} \ No newline at end of file +} diff --git a/src/EventStore.Client/Uuid.cs b/src/Kurrent.Client/Core/Uuid.cs similarity index 98% rename from src/EventStore.Client/Uuid.cs rename to src/Kurrent.Client/Core/Uuid.cs index 6c96b1e2d..cbe7a7686 100644 --- a/src/EventStore.Client/Uuid.cs +++ b/src/Kurrent.Client/Core/Uuid.cs @@ -51,7 +51,7 @@ namespace EventStore.Client { /// /// /// - public static Uuid FromDto(UUID dto) => + internal static Uuid FromDto(UUID dto) => dto == null ? throw new ArgumentNullException(nameof(dto)) : dto.ValueCase switch { @@ -106,7 +106,7 @@ private Uuid(long msb, long lsb) { /// Converts the to the gRPC wire format. /// /// - public UUID ToDto() => + internal UUID ToDto() => new UUID { Structured = new UUID.Types.Structured { LeastSignificantBits = _lsb, diff --git a/src/EventStore.Client/Common/protos/code.proto b/src/Kurrent.Client/Core/protos/code.proto similarity index 100% rename from src/EventStore.Client/Common/protos/code.proto rename to src/Kurrent.Client/Core/protos/code.proto diff --git a/src/EventStore.Client/Common/protos/gossip.proto b/src/Kurrent.Client/Core/protos/gossip.proto similarity index 93% rename from src/EventStore.Client/Common/protos/gossip.proto rename to src/Kurrent.Client/Core/protos/gossip.proto index 192b3b0a4..f4ea9bcd4 100644 --- a/src/EventStore.Client/Common/protos/gossip.proto +++ b/src/Kurrent.Client/Core/protos/gossip.proto @@ -1,6 +1,6 @@ syntax = "proto3"; package event_store.client.gossip; -option java_package = "com.eventstore.client.gossip"; +option java_package = "io.kurrent.client.gossip"; import "shared.proto"; diff --git a/src/EventStore.Client/Common/protos/operations.proto b/src/Kurrent.Client/Core/protos/operations.proto similarity index 94% rename from src/EventStore.Client/Common/protos/operations.proto rename to src/Kurrent.Client/Core/protos/operations.proto index e8d5d2726..f4f9ae3c3 100644 --- a/src/EventStore.Client/Common/protos/operations.proto +++ b/src/Kurrent.Client/Core/protos/operations.proto @@ -1,6 +1,6 @@ syntax = "proto3"; package event_store.client.operations; -option java_package = "com.eventstore.client.operations"; +option java_package = "io.kurrent.client.operations"; import "shared.proto"; diff --git a/src/EventStore.Client/Common/protos/persistentsubscriptions.proto b/src/Kurrent.Client/Core/protos/persistentsubscriptions.proto similarity index 99% rename from src/EventStore.Client/Common/protos/persistentsubscriptions.proto rename to src/Kurrent.Client/Core/protos/persistentsubscriptions.proto index a4109cad2..ac63a3a6d 100644 --- a/src/EventStore.Client/Common/protos/persistentsubscriptions.proto +++ b/src/Kurrent.Client/Core/protos/persistentsubscriptions.proto @@ -1,6 +1,6 @@ syntax = "proto3"; package event_store.client.persistent_subscriptions; -option java_package = "com.eventstore.dbclient.proto.persistentsubscriptions"; +option java_package = "io.kurrent.dbclient.proto.persistentsubscriptions"; import "shared.proto"; diff --git a/src/EventStore.Client/Common/protos/projectionmanagement.proto b/src/Kurrent.Client/Core/protos/projectionmanagement.proto similarity index 98% rename from src/EventStore.Client/Common/protos/projectionmanagement.proto rename to src/Kurrent.Client/Core/protos/projectionmanagement.proto index f1733b55a..f16877012 100644 --- a/src/EventStore.Client/Common/protos/projectionmanagement.proto +++ b/src/Kurrent.Client/Core/protos/projectionmanagement.proto @@ -1,6 +1,6 @@ syntax = "proto3"; package event_store.client.projections; -option java_package = "com.eventstore.client.projections"; +option java_package = "io.kurrent.client.projections"; import "google/protobuf/struct.proto"; import "shared.proto"; diff --git a/src/EventStore.Client/Common/protos/serverfeatures.proto b/src/Kurrent.Client/Core/protos/serverfeatures.proto similarity index 85% rename from src/EventStore.Client/Common/protos/serverfeatures.proto rename to src/Kurrent.Client/Core/protos/serverfeatures.proto index cba04f2c6..61c4ab773 100644 --- a/src/EventStore.Client/Common/protos/serverfeatures.proto +++ b/src/Kurrent.Client/Core/protos/serverfeatures.proto @@ -1,6 +1,6 @@ syntax = "proto3"; package event_store.client.server_features; -option java_package = "com.eventstore.dbclient.proto.serverfeatures"; +option java_package = "io.kurrent.dbclient.proto.serverfeatures"; import "shared.proto"; service ServerFeatures { diff --git a/src/EventStore.Client/Common/protos/shared.proto b/src/Kurrent.Client/Core/protos/shared.proto similarity index 94% rename from src/EventStore.Client/Common/protos/shared.proto rename to src/Kurrent.Client/Core/protos/shared.proto index 2b113aed8..24780afc3 100644 --- a/src/EventStore.Client/Common/protos/shared.proto +++ b/src/Kurrent.Client/Core/protos/shared.proto @@ -1,6 +1,6 @@ syntax = "proto3"; package event_store.client; -option java_package = "com.eventstore.dbclient.proto.shared"; +option java_package = "io.kurrent.dbclient.proto.shared"; import "google/protobuf/empty.proto"; message UUID { diff --git a/src/EventStore.Client/Common/protos/status.proto b/src/Kurrent.Client/Core/protos/status.proto similarity index 100% rename from src/EventStore.Client/Common/protos/status.proto rename to src/Kurrent.Client/Core/protos/status.proto diff --git a/src/EventStore.Client/Common/protos/streams.proto b/src/Kurrent.Client/Core/protos/streams.proto similarity index 99% rename from src/EventStore.Client/Common/protos/streams.proto rename to src/Kurrent.Client/Core/protos/streams.proto index ac599fb82..0eb05295c 100644 --- a/src/EventStore.Client/Common/protos/streams.proto +++ b/src/Kurrent.Client/Core/protos/streams.proto @@ -1,6 +1,6 @@ syntax = "proto3"; package event_store.client.streams; -option java_package = "com.eventstore.dbclient.proto.streams"; +option java_package = "io.kurrent.dbclient.proto.streams"; import "shared.proto"; import "status.proto"; diff --git a/src/EventStore.Client/Common/protos/usermanagement.proto b/src/Kurrent.Client/Core/protos/usermanagement.proto similarity index 97% rename from src/EventStore.Client/Common/protos/usermanagement.proto rename to src/Kurrent.Client/Core/protos/usermanagement.proto index 1fab5a73e..4b55251fd 100644 --- a/src/EventStore.Client/Common/protos/usermanagement.proto +++ b/src/Kurrent.Client/Core/protos/usermanagement.proto @@ -1,6 +1,6 @@ syntax = "proto3"; package event_store.client.users; -option java_package = "com.eventstore.client.users"; +option java_package = "io.kurrent.client.users"; service Users { rpc Create (CreateReq) returns (CreateResp); diff --git a/src/Kurrent.Client/Kurrent.Client.csproj b/src/Kurrent.Client/Kurrent.Client.csproj new file mode 100644 index 000000000..e6652b773 --- /dev/null +++ b/src/Kurrent.Client/Kurrent.Client.csproj @@ -0,0 +1,112 @@ + + + + Kurrent.Client + The base GRPC client library for the Kurrent Platform. Get the open source or commercial versions of KurrentDB from https://kurrent.io/ + Kurrent.Client + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + MSBuild:Compile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Kurrent.Client/OpenTelemetry/TracerProviderBuilderExtensions.cs b/src/Kurrent.Client/OpenTelemetry/TracerProviderBuilderExtensions.cs new file mode 100644 index 000000000..19885375b --- /dev/null +++ b/src/Kurrent.Client/OpenTelemetry/TracerProviderBuilderExtensions.cs @@ -0,0 +1,19 @@ +using EventStore.Client.Diagnostics; +using JetBrains.Annotations; +using OpenTelemetry.Trace; + +namespace EventStore.Client.Extensions.OpenTelemetry; + +/// +/// Extension methods used to facilitate tracing instrumentation of the EventStore Client. +/// +[PublicAPI] +public static class TracerProviderBuilderExtensions { + /// + /// Adds the EventStore client ActivitySource name to the list of subscribed sources on the + /// + /// being configured. + /// The instance of to chain configuration. + public static TracerProviderBuilder AddKurrentClientInstrumentation(this TracerProviderBuilder builder) => + builder.AddSource(KurrentClientDiagnostics.InstrumentationName); +} diff --git a/src/EventStore.Client.Operations/DatabaseScavengeResult.cs b/src/Kurrent.Client/Operations/DatabaseScavengeResult.cs similarity index 100% rename from src/EventStore.Client.Operations/DatabaseScavengeResult.cs rename to src/Kurrent.Client/Operations/DatabaseScavengeResult.cs diff --git a/src/EventStore.Client.Operations/EventStoreOperationsClient.Admin.cs b/src/Kurrent.Client/Operations/KurrentOperationsClient.Admin.cs similarity index 85% rename from src/EventStore.Client.Operations/EventStoreOperationsClient.Admin.cs rename to src/Kurrent.Client/Operations/KurrentOperationsClient.Admin.cs index bfa750145..368fdca13 100644 --- a/src/EventStore.Client.Operations/EventStoreOperationsClient.Admin.cs +++ b/src/Kurrent.Client/Operations/KurrentOperationsClient.Admin.cs @@ -4,11 +4,11 @@ using EventStore.Client.Operations; namespace EventStore.Client { - public partial class EventStoreOperationsClient { + public partial class KurrentOperationsClient { private static readonly Empty EmptyResult = new Empty(); /// - /// Shuts down the EventStoreDB node. + /// Shuts down the KurrentDB node. /// /// /// @@ -21,7 +21,7 @@ public async Task ShutdownAsync( var channelInfo = await GetChannelInfo(cancellationToken).ConfigureAwait(false); using var call = new Operations.Operations.OperationsClient( channelInfo.CallInvoker).ShutdownAsync(EmptyResult, - EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); await call.ResponseAsync.ConfigureAwait(false); } @@ -39,7 +39,7 @@ public async Task MergeIndexesAsync( var channelInfo = await GetChannelInfo(cancellationToken).ConfigureAwait(false); using var call = new Operations.Operations.OperationsClient( channelInfo.CallInvoker).MergeIndexesAsync(EmptyResult, - EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); await call.ResponseAsync.ConfigureAwait(false); } @@ -57,7 +57,7 @@ public async Task ResignNodeAsync( var channelInfo = await GetChannelInfo(cancellationToken).ConfigureAwait(false); using var call = new Operations.Operations.OperationsClient( channelInfo.CallInvoker).ResignNodeAsync(EmptyResult, - EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); await call.ResponseAsync.ConfigureAwait(false); } @@ -77,7 +77,7 @@ public async Task SetNodePriorityAsync(int nodePriority, using var call = new Operations.Operations.OperationsClient( channelInfo.CallInvoker).SetNodePriorityAsync( new SetNodePriorityReq {Priority = nodePriority}, - EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); await call.ResponseAsync.ConfigureAwait(false); } @@ -96,7 +96,7 @@ public async Task RestartPersistentSubscriptions( using var call = new Operations.Operations.OperationsClient( channelInfo.CallInvoker).RestartPersistentSubscriptionsAsync( EmptyResult, - EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); await call.ResponseAsync.ConfigureAwait(false); } } diff --git a/src/EventStore.Client.Operations/EventStoreOperationsClient.Scavenge.cs b/src/Kurrent.Client/Operations/KurrentOperationsClient.Scavenge.cs similarity index 92% rename from src/EventStore.Client.Operations/EventStoreOperationsClient.Scavenge.cs rename to src/Kurrent.Client/Operations/KurrentOperationsClient.Scavenge.cs index 43dcfc50f..eb2c88c54 100644 --- a/src/EventStore.Client.Operations/EventStoreOperationsClient.Scavenge.cs +++ b/src/Kurrent.Client/Operations/KurrentOperationsClient.Scavenge.cs @@ -4,7 +4,7 @@ using EventStore.Client.Operations; namespace EventStore.Client { - public partial class EventStoreOperationsClient { + public partial class KurrentOperationsClient { /// /// Starts a scavenge operation. /// @@ -38,7 +38,7 @@ public async Task StartScavengeAsync( StartFromChunk = startFromChunk } }, - EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); var result = await call.ResponseAsync.ConfigureAwait(false); return result.ScavengeResult switch { @@ -68,7 +68,7 @@ public async Task StopScavengeAsync( Options = new StopScavengeReq.Types.Options { ScavengeId = scavengeId } - }, EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)) + }, KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)) .ResponseAsync.ConfigureAwait(false); return result.ScavengeResult switch { diff --git a/src/EventStore.Client.Operations/EventStoreOperationsClient.cs b/src/Kurrent.Client/Operations/KurrentOperationsClient.cs similarity index 51% rename from src/EventStore.Client.Operations/EventStoreOperationsClient.cs rename to src/Kurrent.Client/Operations/KurrentOperationsClient.cs index 672383348..d392aa578 100644 --- a/src/EventStore.Client.Operations/EventStoreOperationsClient.cs +++ b/src/Kurrent.Client/Operations/KurrentOperationsClient.cs @@ -6,9 +6,9 @@ namespace EventStore.Client; /// -/// The client used to perform maintenance and other administrative tasks on the EventStoreDB. +/// The client used to perform maintenance and other administrative tasks on the KurrentDB. /// -public sealed partial class EventStoreOperationsClient : EventStoreClientBase { +public sealed partial class KurrentOperationsClient : KurrentClientBase { static readonly Dictionary> ExceptionMap = new() { [Constants.Exceptions.ScavengeNotFound] = ex => new ScavengeNotFoundException( @@ -19,15 +19,15 @@ public sealed partial class EventStoreOperationsClient : EventStoreClientBase { readonly ILogger _log; /// - /// Constructs a new . This method is not intended to be called directly in your code. + /// Constructs a new . This method is not intended to be called directly in your code. /// /// - public EventStoreOperationsClient(IOptions options) : this(options.Value) { } + public KurrentOperationsClient(IOptions options) : this(options.Value) { } /// - /// Constructs a new . + /// Constructs a new . /// /// - public EventStoreOperationsClient(EventStoreClientSettings? settings = null) : base(settings, ExceptionMap) => - _log = Settings.LoggerFactory?.CreateLogger() ?? new NullLogger(); -} \ No newline at end of file + public KurrentOperationsClient(KurrentClientSettings? settings = null) : base(settings, ExceptionMap) => + _log = Settings.LoggerFactory?.CreateLogger() ?? new NullLogger(); +} diff --git a/src/EventStore.Client.Operations/EventStoreOperationsClientServiceCollectionExtensions.cs b/src/Kurrent.Client/Operations/KurrentOperationsClientServiceCollectionExtensions.cs similarity index 52% rename from src/EventStore.Client.Operations/EventStoreOperationsClientServiceCollectionExtensions.cs rename to src/Kurrent.Client/Operations/KurrentOperationsClientServiceCollectionExtensions.cs index 9f664277f..fc3ce9505 100644 --- a/src/EventStore.Client.Operations/EventStoreOperationsClientServiceCollectionExtensions.cs +++ b/src/Kurrent.Client/Operations/KurrentOperationsClientServiceCollectionExtensions.cs @@ -6,54 +6,53 @@ using Grpc.Core.Interceptors; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging; -using EventStoreOperationsClient = EventStore.Client.EventStoreOperationsClient; namespace Microsoft.Extensions.DependencyInjection { /// - /// A set of extension methods for which provide support for an . + /// A set of extension methods for which provide support for an . /// - public static class EventStoreOperationsClientServiceCollectionExtensions { + public static class KurrentOperationsClientServiceCollectionExtensions { /// - /// Adds an to the . + /// Adds an to the . /// /// /// /// /// /// - public static IServiceCollection AddEventStoreOperationsClient(this IServiceCollection services, Uri address, + public static IServiceCollection AddKurrentOperationsClient(this IServiceCollection services, Uri address, Func? createHttpMessageHandler = null) - => services.AddEventStoreOperationsClient(options => { + => services.AddKurrentOperationsClient(options => { options.ConnectivitySettings.Address = address; options.CreateHttpMessageHandler = createHttpMessageHandler; }); /// - /// Adds an to the . + /// Adds an to the . /// /// /// /// /// - public static IServiceCollection AddEventStoreOperationsClient(this IServiceCollection services, - Action? configureOptions = null) => - services.AddEventStoreOperationsClient(new EventStoreClientSettings(), configureOptions); + public static IServiceCollection AddKurrentOperationsClient(this IServiceCollection services, + Action? configureOptions = null) => + services.AddKurrentOperationsClient(new KurrentClientSettings(), configureOptions); /// - /// Adds an to the . + /// Adds an to the . /// /// /// /// /// /// - public static IServiceCollection AddEventStoreOperationsClient(this IServiceCollection services, - string connectionString, Action? configureOptions = null) => - services.AddEventStoreOperationsClient(EventStoreClientSettings.Create(connectionString), configureOptions); + public static IServiceCollection AddKurrentOperationsClient(this IServiceCollection services, + string connectionString, Action? configureOptions = null) => + services.AddKurrentOperationsClient(KurrentClientSettings.Create(connectionString), configureOptions); - private static IServiceCollection AddEventStoreOperationsClient(this IServiceCollection services, - EventStoreClientSettings options, Action? configureOptions) { + private static IServiceCollection AddKurrentOperationsClient(this IServiceCollection services, + KurrentClientSettings options, Action? configureOptions) { if (services == null) { throw new ArgumentNullException(nameof(services)); } @@ -64,7 +63,7 @@ private static IServiceCollection AddEventStoreOperationsClient(this IServiceCol options.LoggerFactory ??= provider.GetService(); options.Interceptors ??= provider.GetServices(); - return new EventStoreOperationsClient(options); + return new KurrentOperationsClient(options); }); return services; diff --git a/src/EventStore.Client.Operations/ScavengeResult.cs b/src/Kurrent.Client/Operations/ScavengeResult.cs similarity index 100% rename from src/EventStore.Client.Operations/ScavengeResult.cs rename to src/Kurrent.Client/Operations/ScavengeResult.cs diff --git a/src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.Create.cs b/src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.Create.cs similarity index 98% rename from src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.Create.cs rename to src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.Create.cs index 4cb7acac0..80987b3ce 100644 --- a/src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.Create.cs +++ b/src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.Create.cs @@ -5,7 +5,7 @@ using EventStore.Client.PersistentSubscriptions; namespace EventStore.Client { - partial class EventStorePersistentSubscriptionsClient { + partial class KurrentPersistentSubscriptionsClient { private static readonly IDictionary NamedConsumerStrategyToCreateProto = new Dictionary { [SystemConsumerStrategies.DispatchToSingle] = CreateReq.Types.ConsumerStrategy.DispatchToSingle, @@ -245,7 +245,7 @@ private async Task CreateInternalAsync(string streamName, string groupName, IEve ReadBatchSize = settings.ReadBatchSize } } - }, EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + }, KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); await call.ResponseAsync.ConfigureAwait(false); } } diff --git a/src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.Delete.cs b/src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.Delete.cs similarity index 93% rename from src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.Delete.cs rename to src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.Delete.cs index 40ef522ba..d84c0e61a 100644 --- a/src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.Delete.cs +++ b/src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.Delete.cs @@ -4,7 +4,7 @@ using EventStore.Client.PersistentSubscriptions; namespace EventStore.Client { - partial class EventStorePersistentSubscriptionsClient { + partial class KurrentPersistentSubscriptionsClient { /// /// Deletes a persistent subscription. /// @@ -39,7 +39,7 @@ public async Task DeleteToStreamAsync(string streamName, string groupName, TimeS new PersistentSubscriptions.PersistentSubscriptions.PersistentSubscriptionsClient( channelInfo.CallInvoker) .DeleteAsync(new DeleteReq {Options = deleteOptions}, - EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, + KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); await call.ResponseAsync.ConfigureAwait(false); } diff --git a/src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.Info.cs b/src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.Info.cs similarity index 94% rename from src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.Info.cs rename to src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.Info.cs index b1cc4bebf..78ececf72 100644 --- a/src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.Info.cs +++ b/src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.Info.cs @@ -6,7 +6,7 @@ #nullable enable namespace EventStore.Client { - partial class EventStorePersistentSubscriptionsClient { + partial class KurrentPersistentSubscriptionsClient { /// /// Gets the status of a persistent subscription to $all /// @@ -56,7 +56,7 @@ private async Task GetInfoGrpcAsync(GetInfoReq req, UserCredentials? userCredentials, CallInvoker callInvoker, CancellationToken cancellationToken) { var result = await new PersistentSubscriptions.PersistentSubscriptions.PersistentSubscriptionsClient(callInvoker) - .GetInfoAsync(req, EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)) + .GetInfoAsync(req, KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)) .ConfigureAwait(false); return PersistentSubscriptionInfo.From(result.SubscriptionInfo); diff --git a/src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.List.cs b/src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.List.cs similarity index 93% rename from src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.List.cs rename to src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.List.cs index ce588e3f7..a2c92b733 100644 --- a/src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.List.cs +++ b/src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.List.cs @@ -1,14 +1,9 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; using EventStore.Client.PersistentSubscriptions; using Grpc.Core; #nullable enable namespace EventStore.Client { - partial class EventStorePersistentSubscriptionsClient { + partial class KurrentPersistentSubscriptionsClient { /// /// Lists persistent subscriptions to $all. /// @@ -90,7 +85,7 @@ private async Task> ListGrpcAsync(ListRe UserCredentials? userCredentials, CallInvoker callInvoker, CancellationToken cancellationToken) { using var call = new PersistentSubscriptions.PersistentSubscriptions.PersistentSubscriptionsClient(callInvoker) - .ListAsync(req, EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + .ListAsync(req, KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); ListResp? response = await call.ResponseAsync.ConfigureAwait(false); diff --git a/src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.Read.cs b/src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.Read.cs similarity index 98% rename from src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.Read.cs rename to src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.Read.cs index 211ffdbeb..779413111 100644 --- a/src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.Read.cs +++ b/src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.Read.cs @@ -1,13 +1,13 @@ using System.Threading.Channels; -using EventStore.Client.Diagnostics; using EventStore.Client.PersistentSubscriptions; +using EventStore.Client.Diagnostics; using Grpc.Core; using static EventStore.Client.PersistentSubscriptions.PersistentSubscriptions; using static EventStore.Client.PersistentSubscriptions.ReadResp.ContentOneofCase; namespace EventStore.Client { - partial class EventStorePersistentSubscriptionsClient { + partial class KurrentPersistentSubscriptionsClient { /// /// Subscribes to a persistent subscription. /// @@ -223,7 +223,7 @@ async IAsyncEnumerable GetMessages() { internal PersistentSubscriptionResult( string streamName, string groupName, Func> selectChannelInfo, - ReadReq request, EventStoreClientSettings settings, UserCredentials? userCredentials, + ReadReq request, KurrentClientSettings settings, UserCredentials? userCredentials, CancellationToken cancellationToken ) { StreamName = streamName; @@ -231,7 +231,7 @@ CancellationToken cancellationToken _request = request; - _callOptions = EventStoreCallOptions.CreateStreaming( + _callOptions = KurrentCallOptions.CreateStreaming( settings, userCredentials: userCredentials, cancellationToken: cancellationToken @@ -270,7 +270,7 @@ async Task PumpMessages() { }; if (subscriptionMessage is PersistentSubscriptionMessage.Event evnt) - EventStoreClientDiagnostics.ActivitySource.TraceSubscriptionEvent( + KurrentClientDiagnostics.ActivitySource.TraceSubscriptionEvent( SubscriptionId, evnt.ResolvedEvent, channelInfo, diff --git a/src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.ReplayParked.cs b/src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.ReplayParked.cs similarity index 95% rename from src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.ReplayParked.cs rename to src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.ReplayParked.cs index 248ed9143..e13d4a4ad 100644 --- a/src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.ReplayParked.cs +++ b/src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.ReplayParked.cs @@ -7,7 +7,7 @@ #nullable enable namespace EventStore.Client { - partial class EventStorePersistentSubscriptionsClient { + partial class KurrentPersistentSubscriptionsClient { /// /// Retry the parked messages of the persistent subscription /// @@ -75,7 +75,7 @@ private async Task ReplayParkedGrpcAsync(ReplayParkedReq req, long? numberOfEven } await new PersistentSubscriptions.PersistentSubscriptions.PersistentSubscriptionsClient(callInvoker) - .ReplayParkedAsync(req, EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)) + .ReplayParkedAsync(req, KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)) .ConfigureAwait(false); } diff --git a/src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.RestartSubsystem.cs b/src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.RestartSubsystem.cs similarity index 90% rename from src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.RestartSubsystem.cs rename to src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.RestartSubsystem.cs index 4d01967d8..a82587442 100644 --- a/src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.RestartSubsystem.cs +++ b/src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.RestartSubsystem.cs @@ -4,7 +4,7 @@ #nullable enable namespace EventStore.Client { - partial class EventStorePersistentSubscriptionsClient { + partial class KurrentPersistentSubscriptionsClient { /// /// Restarts the persistent subscriptions subsystem. /// @@ -14,7 +14,7 @@ public async Task RestartSubsystemAsync(TimeSpan? deadline = null, UserCredentia var channelInfo = await GetChannelInfo(cancellationToken).ConfigureAwait(false); if (channelInfo.ServerCapabilities.SupportsPersistentSubscriptionsRestartSubsystem) { await new PersistentSubscriptions.PersistentSubscriptions.PersistentSubscriptionsClient(channelInfo.CallInvoker) - .RestartSubsystemAsync(new Empty(), EventStoreCallOptions + .RestartSubsystemAsync(new Empty(), KurrentCallOptions .CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)) .ConfigureAwait(false); return; diff --git a/src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.Update.cs b/src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.Update.cs similarity index 95% rename from src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.Update.cs rename to src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.Update.cs index 1eae92a25..19eb67d4b 100644 --- a/src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.Update.cs +++ b/src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.Update.cs @@ -1,11 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; using EventStore.Client.PersistentSubscriptions; namespace EventStore.Client { - public partial class EventStorePersistentSubscriptionsClient { + public partial class KurrentPersistentSubscriptionsClient { private static readonly IDictionary NamedConsumerStrategyToUpdateProto = new Dictionary { [SystemConsumerStrategies.DispatchToSingle] = UpdateReq.Types.ConsumerStrategy.DispatchToSingle, @@ -64,7 +60,7 @@ private static UpdateReq.Types.AllOptions AllOptionsForUpdateProto(Position posi [Obsolete("UpdateAsync is no longer supported. Use UpdateToStreamAsync instead.", false)] public Task UpdateAsync(string streamName, string groupName, PersistentSubscriptionSettings settings, TimeSpan? deadline = null, UserCredentials? userCredentials = null, - CancellationToken cancellationToken = default) => + CancellationToken cancellationToken = default) => UpdateToStreamAsync(streamName, groupName, settings, deadline, userCredentials, cancellationToken); /// @@ -148,7 +144,7 @@ public async Task UpdateToStreamAsync(string streamName, string groupName, Persi } } }, - EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); await call.ResponseAsync.ConfigureAwait(false); } diff --git a/src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.cs b/src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.cs similarity index 74% rename from src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.cs rename to src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.cs index 411de3e70..070f32698 100644 --- a/src/EventStore.Client.PersistentSubscriptions/EventStorePersistentSubscriptionsClient.cs +++ b/src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClient.cs @@ -6,9 +6,9 @@ namespace EventStore.Client { /// - /// The client used to manage persistent subscriptions in the EventStoreDB. + /// The client used to manage persistent subscriptions in the KurrentDB. /// - public sealed partial class EventStorePersistentSubscriptionsClient : EventStoreClientBase { + public sealed partial class KurrentPersistentSubscriptionsClient : KurrentClientBase { private static BoundedChannelOptions ReadBoundedChannelOptions = new (1) { SingleReader = true, SingleWriter = true, @@ -18,9 +18,9 @@ public sealed partial class EventStorePersistentSubscriptionsClient : EventStore private readonly ILogger _log; /// - /// Constructs a new . + /// Constructs a new . /// - public EventStorePersistentSubscriptionsClient(EventStoreClientSettings? settings) : base(settings, + public KurrentPersistentSubscriptionsClient(KurrentClientSettings? settings) : base(settings, new Dictionary> { [Constants.Exceptions.PersistentSubscriptionDoesNotExist] = ex => new PersistentSubscriptionNotFoundException( @@ -35,8 +35,8 @@ public EventStorePersistentSubscriptionsClient(EventStoreClientSettings? setting ex.Trailers.First(x => x.Key == Constants.Exceptions.StreamName).Value, ex.Trailers.First(x => x.Key == Constants.Exceptions.GroupName).Value, ex) }) { - _log = Settings.LoggerFactory?.CreateLogger() - ?? new NullLogger(); + _log = Settings.LoggerFactory?.CreateLogger() + ?? new NullLogger(); } private static string UrlEncode(string s) { diff --git a/src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClientCollectionExtensions.cs b/src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClientCollectionExtensions.cs new file mode 100644 index 000000000..9ed65e091 --- /dev/null +++ b/src/Kurrent.Client/PersistentSubscriptions/KurrentPersistentSubscriptionsClientCollectionExtensions.cs @@ -0,0 +1,61 @@ +// ReSharper disable CheckNamespace + +using System; +using System.Net.Http; +using EventStore.Client; +using Grpc.Core.Interceptors; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Logging; + +namespace Microsoft.Extensions.DependencyInjection { + /// + /// A set of extension methods for which provide support for an . + /// + public static class KurrentPersistentSubscriptionsClientCollectionExtensions { + /// + /// Adds an to the . + /// + /// + public static IServiceCollection AddKurrentPersistentSubscriptionsClient(this IServiceCollection services, + Uri address, Func? createHttpMessageHandler = null) + => services.AddKurrentPersistentSubscriptionsClient(options => { + options.ConnectivitySettings.Address = address; + options.CreateHttpMessageHandler = createHttpMessageHandler; + }); + + /// + /// Adds an to the . + /// + /// + public static IServiceCollection AddKurrentPersistentSubscriptionsClient(this IServiceCollection services, + Action? configureSettings = null) => + services.AddKurrentPersistentSubscriptionsClient(new KurrentClientSettings(), + configureSettings); + + /// + /// Adds an to the . + /// + /// + public static IServiceCollection AddKurrentPersistentSubscriptionsClient(this IServiceCollection services, + string connectionString, Action? configureSettings = null) => + services.AddKurrentPersistentSubscriptionsClient(KurrentClientSettings.Create(connectionString), + configureSettings); + + private static IServiceCollection AddKurrentPersistentSubscriptionsClient(this IServiceCollection services, + KurrentClientSettings settings, Action? configureSettings) { + if (services == null) { + throw new ArgumentNullException(nameof(services)); + } + + configureSettings?.Invoke(settings); + services.TryAddSingleton(provider => { + settings.LoggerFactory ??= provider.GetService(); + settings.Interceptors ??= provider.GetServices(); + + return new KurrentPersistentSubscriptionsClient(settings); + }); + return services; + } + } +} +// ReSharper restore CheckNamespace diff --git a/src/EventStore.Client.PersistentSubscriptions/MaximumSubscribersReachedException.cs b/src/Kurrent.Client/PersistentSubscriptions/MaximumSubscribersReachedException.cs similarity index 100% rename from src/EventStore.Client.PersistentSubscriptions/MaximumSubscribersReachedException.cs rename to src/Kurrent.Client/PersistentSubscriptions/MaximumSubscribersReachedException.cs diff --git a/src/EventStore.Client.PersistentSubscriptions/PersistentSubscription.cs b/src/Kurrent.Client/PersistentSubscriptions/PersistentSubscription.cs similarity index 96% rename from src/EventStore.Client.PersistentSubscriptions/PersistentSubscription.cs rename to src/Kurrent.Client/PersistentSubscriptions/PersistentSubscription.cs index f3d19b42e..637f54e30 100644 --- a/src/EventStore.Client.PersistentSubscriptions/PersistentSubscription.cs +++ b/src/Kurrent.Client/PersistentSubscriptions/PersistentSubscription.cs @@ -7,7 +7,7 @@ namespace EventStore.Client { /// Represents a persistent subscription connection. /// public class PersistentSubscription : IDisposable { - private readonly EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult _persistentSubscriptionResult; + private readonly KurrentPersistentSubscriptionsClient.PersistentSubscriptionResult _persistentSubscriptionResult; private readonly IAsyncEnumerator _enumerator; private readonly Func _eventAppeared; private readonly Action _subscriptionDropped; @@ -22,7 +22,7 @@ public class PersistentSubscription : IDisposable { public string SubscriptionId { get; } internal static async Task Confirm( - EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult persistentSubscriptionResult, + KurrentPersistentSubscriptionsClient.PersistentSubscriptionResult persistentSubscriptionResult, Func eventAppeared, Action subscriptionDropped, ILogger log, UserCredentials? userCredentials, CancellationToken cancellationToken = default) { @@ -45,7 +45,7 @@ internal static async Task Confirm( // PersistentSubscription takes responsibility for disposing the call and the disposable private PersistentSubscription( - EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult persistentSubscriptionResult, + KurrentPersistentSubscriptionsClient.PersistentSubscriptionResult persistentSubscriptionResult, IAsyncEnumerator enumerator, string subscriptionId, Func eventAppeared, Action subscriptionDropped, ILogger log, diff --git a/src/EventStore.Client.PersistentSubscriptions/PersistentSubscriptionDroppedByServerException.cs b/src/Kurrent.Client/PersistentSubscriptions/PersistentSubscriptionDroppedByServerException.cs similarity index 91% rename from src/EventStore.Client.PersistentSubscriptions/PersistentSubscriptionDroppedByServerException.cs rename to src/Kurrent.Client/PersistentSubscriptions/PersistentSubscriptionDroppedByServerException.cs index 29b42bb49..b25ea4f72 100644 --- a/src/EventStore.Client.PersistentSubscriptions/PersistentSubscriptionDroppedByServerException.cs +++ b/src/Kurrent.Client/PersistentSubscriptions/PersistentSubscriptionDroppedByServerException.cs @@ -2,7 +2,7 @@ namespace EventStore.Client { /// - /// The exception that is thrown when the EventStoreDB drops a persistent subscription. + /// The exception that is thrown when the KurrentDB drops a persistent subscription. /// public class PersistentSubscriptionDroppedByServerException : Exception { /// diff --git a/src/EventStore.Client.PersistentSubscriptions/PersistentSubscriptionExtraStatistic.cs b/src/Kurrent.Client/PersistentSubscriptions/PersistentSubscriptionExtraStatistic.cs similarity index 100% rename from src/EventStore.Client.PersistentSubscriptions/PersistentSubscriptionExtraStatistic.cs rename to src/Kurrent.Client/PersistentSubscriptions/PersistentSubscriptionExtraStatistic.cs diff --git a/src/EventStore.Client.PersistentSubscriptions/PersistentSubscriptionInfo.cs b/src/Kurrent.Client/PersistentSubscriptions/PersistentSubscriptionInfo.cs similarity index 100% rename from src/EventStore.Client.PersistentSubscriptions/PersistentSubscriptionInfo.cs rename to src/Kurrent.Client/PersistentSubscriptions/PersistentSubscriptionInfo.cs diff --git a/src/EventStore.Client.PersistentSubscriptions/PersistentSubscriptionMessage.cs b/src/Kurrent.Client/PersistentSubscriptions/PersistentSubscriptionMessage.cs similarity index 86% rename from src/EventStore.Client.PersistentSubscriptions/PersistentSubscriptionMessage.cs rename to src/Kurrent.Client/PersistentSubscriptions/PersistentSubscriptionMessage.cs index eabde9b62..7cd0d848d 100644 --- a/src/EventStore.Client.PersistentSubscriptions/PersistentSubscriptionMessage.cs +++ b/src/Kurrent.Client/PersistentSubscriptions/PersistentSubscriptionMessage.cs @@ -4,10 +4,10 @@ namespace EventStore.Client { /// public abstract record PersistentSubscriptionMessage { /// - /// A that represents a . + /// A that represents a . /// - /// The . - /// The number of times the has been retried. + /// The . + /// The number of times the has been retried. public record Event(ResolvedEvent ResolvedEvent, int? RetryCount) : PersistentSubscriptionMessage; /// diff --git a/src/EventStore.Client.PersistentSubscriptions/PersistentSubscriptionNakEventAction.cs b/src/Kurrent.Client/PersistentSubscriptions/PersistentSubscriptionNakEventAction.cs similarity index 100% rename from src/EventStore.Client.PersistentSubscriptions/PersistentSubscriptionNakEventAction.cs rename to src/Kurrent.Client/PersistentSubscriptions/PersistentSubscriptionNakEventAction.cs diff --git a/src/EventStore.Client.PersistentSubscriptions/PersistentSubscriptionNotFoundException.cs b/src/Kurrent.Client/PersistentSubscriptions/PersistentSubscriptionNotFoundException.cs similarity index 100% rename from src/EventStore.Client.PersistentSubscriptions/PersistentSubscriptionNotFoundException.cs rename to src/Kurrent.Client/PersistentSubscriptions/PersistentSubscriptionNotFoundException.cs diff --git a/src/EventStore.Client.PersistentSubscriptions/PersistentSubscriptionSettings.cs b/src/Kurrent.Client/PersistentSubscriptions/PersistentSubscriptionSettings.cs similarity index 100% rename from src/EventStore.Client.PersistentSubscriptions/PersistentSubscriptionSettings.cs rename to src/Kurrent.Client/PersistentSubscriptions/PersistentSubscriptionSettings.cs diff --git a/src/EventStore.Client.PersistentSubscriptions/SystemConsumerStrategies.cs b/src/Kurrent.Client/PersistentSubscriptions/SystemConsumerStrategies.cs similarity index 100% rename from src/EventStore.Client.PersistentSubscriptions/SystemConsumerStrategies.cs rename to src/Kurrent.Client/PersistentSubscriptions/SystemConsumerStrategies.cs diff --git a/src/EventStore.Client.ProjectionManagement/EventStoreProjectionManagementClient.Control.cs b/src/Kurrent.Client/ProjectionManagement/KurrentProjectionManagementClient.Control.cs similarity index 89% rename from src/EventStore.Client.ProjectionManagement/EventStoreProjectionManagementClient.Control.cs rename to src/Kurrent.Client/ProjectionManagement/KurrentProjectionManagementClient.Control.cs index e21da92fc..ff6ba9619 100644 --- a/src/EventStore.Client.ProjectionManagement/EventStoreProjectionManagementClient.Control.cs +++ b/src/Kurrent.Client/ProjectionManagement/KurrentProjectionManagementClient.Control.cs @@ -4,7 +4,7 @@ using EventStore.Client.Projections; namespace EventStore.Client { - public partial class EventStoreProjectionManagementClient { + public partial class KurrentProjectionManagementClient { /// /// Enables a projection. /// @@ -21,7 +21,7 @@ public async Task EnableAsync(string name, TimeSpan? deadline = null, UserCreden Options = new EnableReq.Types.Options { Name = name } - }, EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + }, KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); await call.ResponseAsync.ConfigureAwait(false); } @@ -42,7 +42,7 @@ public async Task ResetAsync(string name, TimeSpan? deadline = null, UserCredent Name = name, WriteCheckpoint = true } - }, EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + }, KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); await call.ResponseAsync.ConfigureAwait(false); } @@ -82,7 +82,7 @@ public async Task RestartSubsystemAsync(TimeSpan? deadline = null, UserCredentia var channelInfo = await GetChannelInfo(cancellationToken).ConfigureAwait(false); using var call = new Projections.Projections.ProjectionsClient( channelInfo.CallInvoker).RestartSubsystemAsync(new Empty(), - EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); await call.ResponseAsync.ConfigureAwait(false); } @@ -95,7 +95,7 @@ private async Task DisableInternalAsync(string name, bool writeCheckpoint, TimeS Name = name, WriteCheckpoint = writeCheckpoint } - }, EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + }, KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); await call.ResponseAsync.ConfigureAwait(false); } } diff --git a/src/EventStore.Client.ProjectionManagement/EventStoreProjectionManagementClient.Create.cs b/src/Kurrent.Client/ProjectionManagement/KurrentProjectionManagementClient.Create.cs similarity index 88% rename from src/EventStore.Client.ProjectionManagement/EventStoreProjectionManagementClient.Create.cs rename to src/Kurrent.Client/ProjectionManagement/KurrentProjectionManagementClient.Create.cs index 54498cabf..cae9b400e 100644 --- a/src/EventStore.Client.ProjectionManagement/EventStoreProjectionManagementClient.Create.cs +++ b/src/Kurrent.Client/ProjectionManagement/KurrentProjectionManagementClient.Create.cs @@ -4,7 +4,7 @@ using EventStore.Client.Projections; namespace EventStore.Client { - public partial class EventStoreProjectionManagementClient { + public partial class KurrentProjectionManagementClient { /// /// Creates a one-time projection. /// @@ -22,7 +22,7 @@ public async Task CreateOneTimeAsync(string query, TimeSpan? deadline = null, OneTime = new Empty(), Query = query } - }, EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + }, KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); await call.ResponseAsync.ConfigureAwait(false); } @@ -49,7 +49,7 @@ public async Task CreateContinuousAsync(string name, string query, bool trackEmi }, Query = query } - }, EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + }, KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); await call.ResponseAsync.ConfigureAwait(false); } @@ -73,7 +73,7 @@ public async Task CreateTransientAsync(string name, string query, TimeSpan? dead }, Query = query } - }, EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + }, KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); await call.ResponseAsync.ConfigureAwait(false); } } diff --git a/src/EventStore.Client.ProjectionManagement/EventStoreProjectionManagementClient.State.cs b/src/Kurrent.Client/ProjectionManagement/KurrentProjectionManagementClient.State.cs similarity index 96% rename from src/EventStore.Client.ProjectionManagement/EventStoreProjectionManagementClient.State.cs rename to src/Kurrent.Client/ProjectionManagement/KurrentProjectionManagementClient.State.cs index 64187fe1f..ca24d6ef9 100644 --- a/src/EventStore.Client.ProjectionManagement/EventStoreProjectionManagementClient.State.cs +++ b/src/Kurrent.Client/ProjectionManagement/KurrentProjectionManagementClient.State.cs @@ -8,7 +8,7 @@ using Type = System.Type; namespace EventStore.Client { - public partial class EventStoreProjectionManagementClient { + public partial class KurrentProjectionManagementClient { static readonly JsonSerializerOptions DefaultJsonSerializerOptions = new JsonSerializerOptions(); /// @@ -80,7 +80,7 @@ private async ValueTask GetResultInternalAsync(string name, string? parti Name = name, Partition = partition ?? string.Empty } - }, EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + }, KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); var response = await call.ResponseAsync.ConfigureAwait(false); return response.Result; @@ -155,7 +155,7 @@ private async ValueTask GetStateInternalAsync(string name, string? partit Name = name, Partition = partition ?? string.Empty } - }, EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + }, KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); var response = await call.ResponseAsync.ConfigureAwait(false); return response.State; diff --git a/src/EventStore.Client.ProjectionManagement/EventStoreProjectionManagementClient.Statistics.cs b/src/Kurrent.Client/ProjectionManagement/KurrentProjectionManagementClient.Statistics.cs similarity index 89% rename from src/EventStore.Client.ProjectionManagement/EventStoreProjectionManagementClient.Statistics.cs rename to src/Kurrent.Client/ProjectionManagement/KurrentProjectionManagementClient.Statistics.cs index 0b49b8b80..425831165 100644 --- a/src/EventStore.Client.ProjectionManagement/EventStoreProjectionManagementClient.Statistics.cs +++ b/src/Kurrent.Client/ProjectionManagement/KurrentProjectionManagementClient.Statistics.cs @@ -8,7 +8,7 @@ using Grpc.Core; namespace EventStore.Client { - public partial class EventStoreProjectionManagementClient { + public partial class KurrentProjectionManagementClient { /// /// List the of all one-time projections. /// @@ -21,7 +21,7 @@ public IAsyncEnumerable ListOneTimeAsync(TimeSpan? deadline = ListInternalAsync(new StatisticsReq.Types.Options { OneTime = new Empty() }, - EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken), + KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken), cancellationToken); /// @@ -37,7 +37,7 @@ public IAsyncEnumerable ListContinuousAsync(TimeSpan? deadlin ListInternalAsync(new StatisticsReq.Types.Options { Continuous = new Empty() }, - EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken), + KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken), cancellationToken); /// @@ -53,7 +53,7 @@ public IAsyncEnumerable ListContinuousAsync(TimeSpan? deadlin CancellationToken cancellationToken = default) => ListInternalAsync(new StatisticsReq.Types.Options { Name = name }, - EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken), + KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken), cancellationToken) .FirstOrDefaultAsync(cancellationToken).AsTask(); @@ -69,7 +69,7 @@ public IAsyncEnumerable ListAllAsync(TimeSpan? deadline = nul ListInternalAsync(new StatisticsReq.Types.Options { All = new Empty() }, - EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken), + KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken), cancellationToken); private async IAsyncEnumerable ListInternalAsync(StatisticsReq.Types.Options options, diff --git a/src/EventStore.Client.ProjectionManagement/EventStoreProjectionManagementClient.Update.cs b/src/Kurrent.Client/ProjectionManagement/KurrentProjectionManagementClient.Update.cs similarity index 87% rename from src/EventStore.Client.ProjectionManagement/EventStoreProjectionManagementClient.Update.cs rename to src/Kurrent.Client/ProjectionManagement/KurrentProjectionManagementClient.Update.cs index 8f577e92c..368ff3be4 100644 --- a/src/EventStore.Client.ProjectionManagement/EventStoreProjectionManagementClient.Update.cs +++ b/src/Kurrent.Client/ProjectionManagement/KurrentProjectionManagementClient.Update.cs @@ -4,7 +4,7 @@ using EventStore.Client.Projections; namespace EventStore.Client { - public partial class EventStoreProjectionManagementClient { + public partial class KurrentProjectionManagementClient { /// /// Updates a projection. /// @@ -32,7 +32,7 @@ public async Task UpdateAsync(string name, string query, bool? emitEnabled = nul using var call = new Projections.Projections.ProjectionsClient( channelInfo.CallInvoker).UpdateAsync(new UpdateReq { Options = options - }, EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + }, KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); await call.ResponseAsync.ConfigureAwait(false); } diff --git a/src/Kurrent.Client/ProjectionManagement/KurrentProjectionManagementClient.cs b/src/Kurrent.Client/ProjectionManagement/KurrentProjectionManagementClient.cs new file mode 100644 index 000000000..12e1abf18 --- /dev/null +++ b/src/Kurrent.Client/ProjectionManagement/KurrentProjectionManagementClient.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using Grpc.Core; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; + +namespace EventStore.Client { + /// + ///The client used to manage projections on the KurrentDB. + /// + public sealed partial class KurrentProjectionManagementClient : KurrentClientBase { + private readonly ILogger _log; + + /// + /// Constructs a new . This method is not intended to be called directly from your code. + /// + /// + public KurrentProjectionManagementClient(IOptions options) : this(options.Value) { + } + + /// + /// Constructs a new . + /// + /// + public KurrentProjectionManagementClient(KurrentClientSettings? settings) : base(settings, + new Dictionary>()) { + _log = settings?.LoggerFactory?.CreateLogger() ?? + new NullLogger(); + } + } +} diff --git a/src/EventStore.Client.ProjectionManagement/EventStoreProjectionManagementClientCollectionExtensions.cs b/src/Kurrent.Client/ProjectionManagement/KurrentProjectionManagementClientCollectionExtensions.cs similarity index 52% rename from src/EventStore.Client.ProjectionManagement/EventStoreProjectionManagementClientCollectionExtensions.cs rename to src/Kurrent.Client/ProjectionManagement/KurrentProjectionManagementClientCollectionExtensions.cs index ea1f634f6..5fe3932b7 100644 --- a/src/EventStore.Client.ProjectionManagement/EventStoreProjectionManagementClientCollectionExtensions.cs +++ b/src/Kurrent.Client/ProjectionManagement/KurrentProjectionManagementClientCollectionExtensions.cs @@ -9,51 +9,51 @@ namespace Microsoft.Extensions.DependencyInjection { /// - /// A set of extension methods for which provide support for an . + /// A set of extension methods for which provide support for an . /// - public static class EventStoreProjectionManagementClientCollectionExtensions { + public static class KurrentProjectionManagementClientCollectionExtensions { /// - /// Adds an to the . + /// Adds an to the . /// /// /// /// /// /// - public static IServiceCollection AddEventStoreProjectionManagementClient(this IServiceCollection services, + public static IServiceCollection AddKurrentProjectionManagementClient(this IServiceCollection services, Uri address, Func? createHttpMessageHandler = null) - => services.AddEventStoreProjectionManagementClient(options => { + => services.AddKurrentProjectionManagementClient(options => { options.ConnectivitySettings.Address = address; options.CreateHttpMessageHandler = createHttpMessageHandler; }); /// - /// Adds an to the . + /// Adds an to the . /// /// /// /// /// - public static IServiceCollection AddEventStoreProjectionManagementClient(this IServiceCollection services, - Action? configureSettings = null) => - services.AddEventStoreProjectionManagementClient(new EventStoreClientSettings(), configureSettings); + public static IServiceCollection AddKurrentProjectionManagementClient(this IServiceCollection services, + Action? configureSettings = null) => + services.AddKurrentProjectionManagementClient(new KurrentClientSettings(), configureSettings); /// - /// Adds an to the . + /// Adds an to the . /// /// /// /// /// /// - public static IServiceCollection AddEventStoreProjectionManagementClient(this IServiceCollection services, - string connectionString, Action? configureSettings = null) => - services.AddEventStoreProjectionManagementClient(EventStoreClientSettings.Create(connectionString), + public static IServiceCollection AddKurrentProjectionManagementClient(this IServiceCollection services, + string connectionString, Action? configureSettings = null) => + services.AddKurrentProjectionManagementClient(KurrentClientSettings.Create(connectionString), configureSettings); - private static IServiceCollection AddEventStoreProjectionManagementClient(this IServiceCollection services, - EventStoreClientSettings settings, Action? configureSettings) { + private static IServiceCollection AddKurrentProjectionManagementClient(this IServiceCollection services, + KurrentClientSettings settings, Action? configureSettings) { if (services == null) { throw new ArgumentNullException(nameof(services)); } @@ -64,7 +64,7 @@ private static IServiceCollection AddEventStoreProjectionManagementClient(this I settings.LoggerFactory ??= provider.GetService(); settings.Interceptors ??= provider.GetServices(); - return new EventStoreProjectionManagementClient(settings); + return new KurrentProjectionManagementClient(settings); }); return services; diff --git a/src/EventStore.Client.ProjectionManagement/ProjectionDetails.cs b/src/Kurrent.Client/ProjectionManagement/ProjectionDetails.cs similarity index 100% rename from src/EventStore.Client.ProjectionManagement/ProjectionDetails.cs rename to src/Kurrent.Client/ProjectionManagement/ProjectionDetails.cs diff --git a/src/EventStore.Client.Streams/ConditionalWriteResult.cs b/src/Kurrent.Client/Streams/ConditionalWriteResult.cs similarity index 100% rename from src/EventStore.Client.Streams/ConditionalWriteResult.cs rename to src/Kurrent.Client/Streams/ConditionalWriteResult.cs diff --git a/src/EventStore.Client.Streams/ConditionalWriteStatus.cs b/src/Kurrent.Client/Streams/ConditionalWriteStatus.cs similarity index 100% rename from src/EventStore.Client.Streams/ConditionalWriteStatus.cs rename to src/Kurrent.Client/Streams/ConditionalWriteStatus.cs diff --git a/src/EventStore.Client.Streams/DeadLine.cs b/src/Kurrent.Client/Streams/DeadLine.cs similarity index 100% rename from src/EventStore.Client.Streams/DeadLine.cs rename to src/Kurrent.Client/Streams/DeadLine.cs diff --git a/src/EventStore.Client.Streams/DeleteResult.cs b/src/Kurrent.Client/Streams/DeleteResult.cs similarity index 100% rename from src/EventStore.Client.Streams/DeleteResult.cs rename to src/Kurrent.Client/Streams/DeleteResult.cs diff --git a/src/EventStore.Client.Streams/Direction.cs b/src/Kurrent.Client/Streams/Direction.cs similarity index 100% rename from src/EventStore.Client.Streams/Direction.cs rename to src/Kurrent.Client/Streams/Direction.cs diff --git a/src/EventStore.Client.Streams/IWriteResult.cs b/src/Kurrent.Client/Streams/IWriteResult.cs similarity index 100% rename from src/EventStore.Client.Streams/IWriteResult.cs rename to src/Kurrent.Client/Streams/IWriteResult.cs diff --git a/src/EventStore.Client.Streams/InvalidTransactionException.cs b/src/Kurrent.Client/Streams/InvalidTransactionException.cs similarity index 97% rename from src/EventStore.Client.Streams/InvalidTransactionException.cs rename to src/Kurrent.Client/Streams/InvalidTransactionException.cs index 17933b654..f71505671 100644 --- a/src/EventStore.Client.Streams/InvalidTransactionException.cs +++ b/src/Kurrent.Client/Streams/InvalidTransactionException.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.Serialization; -namespace EventStore.Client; +namespace EventStore.Client; /// /// Exception thrown if there is an attempt to operate inside a @@ -28,4 +28,4 @@ public InvalidTransactionException(string message, Exception innerException) : b /// [Obsolete("Obsolete")] protected InvalidTransactionException(SerializationInfo info, StreamingContext context) : base(info, context) { } -} \ No newline at end of file +} diff --git a/src/EventStore.Client.Streams/EventStoreClient.Append.cs b/src/Kurrent.Client/Streams/KurrentClient.Append.cs similarity index 90% rename from src/EventStore.Client.Streams/EventStoreClient.Append.cs rename to src/Kurrent.Client/Streams/KurrentClient.Append.cs index 9b244b3a4..39d6f3066 100644 --- a/src/EventStore.Client.Streams/EventStoreClient.Append.cs +++ b/src/Kurrent.Client/Streams/KurrentClient.Append.cs @@ -6,21 +6,21 @@ using Grpc.Core; using Microsoft.Extensions.Logging; using EventStore.Client.Diagnostics; -using EventStore.Diagnostics; -using EventStore.Diagnostics.Telemetry; -using EventStore.Diagnostics.Tracing; +using Kurrent.Diagnostics; +using Kurrent.Diagnostics.Telemetry; +using Kurrent.Diagnostics.Tracing; using static EventStore.Client.Streams.AppendResp.Types.WrongExpectedVersion; using static EventStore.Client.Streams.Streams; namespace EventStore.Client { - public partial class EventStoreClient { + public partial class KurrentClient { /// /// Appends events asynchronously to a stream. /// /// The name of the stream to append events to. /// The expected of the stream to append to. /// An to append to the stream. - /// An to configure the operation's options. + /// An to configure the operation's options. /// /// The for the operation. /// The optional . @@ -29,7 +29,7 @@ public async Task AppendToStreamAsync( string streamName, StreamRevision expectedRevision, IEnumerable eventData, - Action? configureOperationOptions = null, + Action? configureOperationOptions = null, TimeSpan? deadline = null, UserCredentials? userCredentials = null, CancellationToken cancellationToken = default @@ -65,7 +65,7 @@ await GetChannelInfo(cancellationToken).ConfigureAwait(false), /// The name of the stream to append events to. /// The expected of the stream to append to. /// An to append to the stream. - /// An to configure the operation's options. + /// An to configure the operation's options. /// /// The for the operation. /// The optional . @@ -74,7 +74,7 @@ public async Task AppendToStreamAsync( string streamName, StreamState expectedState, IEnumerable eventData, - Action? configureOperationOptions = null, + Action? configureOperationOptions = null, TimeSpan? deadline = null, UserCredentials? userCredentials = null, CancellationToken cancellationToken = default @@ -108,16 +108,22 @@ ValueTask AppendToStreamInternal( ChannelInfo channelInfo, AppendReq header, IEnumerable eventData, - EventStoreClientOperationOptions operationOptions, + KurrentClientOperationOptions operationOptions, TimeSpan? deadline, UserCredentials? userCredentials, CancellationToken cancellationToken ) { - return EventStoreClientDiagnostics.ActivitySource.TraceClientOperation(Operation, TracingConstants.Operations.Append, AppendTags); + var tags = new ActivityTagsCollection() + .WithRequiredTag(TelemetryTags.Kurrent.Stream, header.Options.StreamIdentifier.StreamName.ToStringUtf8()) + .WithGrpcChannelServerTags(channelInfo) + .WithClientSettingsServerTags(Settings) + .WithOptionalTag(TelemetryTags.Database.User, userCredentials?.Username ?? Settings.DefaultCredentials?.Username); + + return KurrentClientDiagnostics.ActivitySource.TraceClientOperation(Operation, TracingConstants.Operations.Append, tags); async ValueTask Operation() { using var call = new StreamsClient(channelInfo.CallInvoker) - .Append(EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + .Append(KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); await call.RequestStream .WriteAsync(header) @@ -151,12 +157,6 @@ await call.RequestStream return HandleWrongExpectedRevision(response, header, operationOptions); } - - ActivityTagsCollection AppendTags() => new ActivityTagsCollection() - .WithRequiredTag(TelemetryTags.EventStore.Stream, header.Options.StreamIdentifier.StreamName.ToStringUtf8()) - .WithGrpcChannelServerTags(Settings, channelInfo) - .WithClientSettingsServerTags(Settings) - .WithOptionalTag(TelemetryTags.Database.User, userCredentials?.Username ?? Settings.DefaultCredentials?.Username); } IWriteResult HandleSuccessAppend(AppendResp response, AppendReq header) { @@ -179,7 +179,7 @@ IWriteResult HandleSuccessAppend(AppendResp response, AppendReq header) { } IWriteResult HandleWrongExpectedRevision( - AppendResp response, AppendReq header, EventStoreClientOperationOptions operationOptions + AppendResp response, AppendReq header, KurrentClientOperationOptions operationOptions ) { var actualStreamRevision = response.WrongExpectedVersion.CurrentRevisionOptionCase == CurrentRevisionOptionOneofCase.CurrentRevision ? new StreamRevision(response.WrongExpectedVersion.CurrentRevision) @@ -227,7 +227,7 @@ IWriteResult HandleWrongExpectedRevision( } class StreamAppender : IDisposable { - readonly EventStoreClientSettings _settings; + readonly KurrentClientSettings _settings; readonly CancellationToken _cancellationToken; readonly Action _onException; readonly Channel _channel; @@ -238,7 +238,7 @@ class StreamAppender : IDisposable { AsyncDuplexStreamingCall? _call; public StreamAppender( - EventStoreClientSettings settings, + KurrentClientSettings settings, ValueTask channelInfoTask, CancellationToken cancellationToken, Action onException @@ -282,10 +282,16 @@ ValueTask AppendInternal( IEnumerable events, CancellationToken cancellationToken ) { - return EventStoreClientDiagnostics.ActivitySource.TraceClientOperation( + var tags = new ActivityTagsCollection() + .WithRequiredTag(TelemetryTags.Kurrent.Stream, options.StreamIdentifier.StreamName.ToStringUtf8()) + .WithGrpcChannelServerTags(_channelInfo) + .WithClientSettingsServerTags(_settings) + .WithOptionalTag(TelemetryTags.Database.User, _settings.DefaultCredentials?.Username); + + return KurrentClientDiagnostics.ActivitySource.TraceClientOperation( Operation, TracingConstants.Operations.Append, - AppendTags + tags ); async ValueTask Operation() { @@ -304,12 +310,6 @@ async ValueTask Operation() { return await complete.Task.ConfigureAwait(false); } - - ActivityTagsCollection AppendTags() => new ActivityTagsCollection() - .WithRequiredTag(TelemetryTags.EventStore.Stream, options.StreamIdentifier.StreamName.ToStringUtf8()) - .WithGrpcChannelServerTags(_settings, _channelInfo) - .WithClientSettingsServerTags(_settings) - .WithOptionalTag(TelemetryTags.Database.User, _settings.DefaultCredentials?.Username); } async Task Duplex(ValueTask channelInfoTask) { @@ -322,7 +322,7 @@ async Task Duplex(ValueTask channelInfoTask) { } _call = new StreamsClient(_channelInfo.CallInvoker).BatchAppend( - EventStoreCallOptions.CreateStreaming( + KurrentCallOptions.CreateStreaming( _settings, userCredentials: _settings.DefaultCredentials, cancellationToken: _cancellationToken diff --git a/src/EventStore.Client.Streams/EventStoreClient.Delete.cs b/src/Kurrent.Client/Streams/KurrentClient.Delete.cs similarity index 95% rename from src/EventStore.Client.Streams/EventStoreClient.Delete.cs rename to src/Kurrent.Client/Streams/KurrentClient.Delete.cs index dfaac235f..50a174e25 100644 --- a/src/EventStore.Client.Streams/EventStoreClient.Delete.cs +++ b/src/Kurrent.Client/Streams/KurrentClient.Delete.cs @@ -5,7 +5,7 @@ using Microsoft.Extensions.Logging; namespace EventStore.Client { - public partial class EventStoreClient { + public partial class KurrentClient { /// /// Deletes a stream asynchronously. /// @@ -56,7 +56,7 @@ private async Task DeleteInternal(DeleteReq request, var channelInfo = await GetChannelInfo(cancellationToken).ConfigureAwait(false); using var call = new Streams.Streams.StreamsClient( channelInfo.CallInvoker).DeleteAsync(request, - EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); var result = await call.ResponseAsync.ConfigureAwait(false); return new DeleteResult(new Position(result.Position.CommitPosition, result.Position.PreparePosition)); diff --git a/src/EventStore.Client.Streams/EventStoreClient.Metadata.cs b/src/Kurrent.Client/Streams/KurrentClient.Metadata.cs similarity index 91% rename from src/EventStore.Client.Streams/EventStoreClient.Metadata.cs rename to src/Kurrent.Client/Streams/KurrentClient.Metadata.cs index 19de629e7..f8185607c 100644 --- a/src/EventStore.Client.Streams/EventStoreClient.Metadata.cs +++ b/src/Kurrent.Client/Streams/KurrentClient.Metadata.cs @@ -6,7 +6,7 @@ using Microsoft.Extensions.Logging; namespace EventStore.Client { - public partial class EventStoreClient { + public partial class KurrentClient { /// /// Asynchronously reads the metadata for a stream /// @@ -44,13 +44,13 @@ public async Task GetStreamMetadataAsync(string streamName /// The name of the stream to set metadata for. /// The of the stream to append to. /// A representing the new metadata. - /// An to configure the operation's options. + /// An to configure the operation's options. /// /// The optional to perform operation with. /// The optional . /// public Task SetStreamMetadataAsync(string streamName, StreamState expectedState, - StreamMetadata metadata, Action? configureOperationOptions = null, + StreamMetadata metadata, Action? configureOperationOptions = null, TimeSpan? deadline = null, UserCredentials? userCredentials = null, CancellationToken cancellationToken = default) { var options = Settings.OperationOptions.Clone(); @@ -69,13 +69,13 @@ public Task SetStreamMetadataAsync(string streamName, StreamState /// The name of the stream to set metadata for. /// The of the stream to append to. /// A representing the new metadata. - /// An to configure the operation's options. + /// An to configure the operation's options. /// /// The optional to perform operation with. /// The optional . /// public Task SetStreamMetadataAsync(string streamName, StreamRevision expectedRevision, - StreamMetadata metadata, Action? configureOperationOptions = null, + StreamMetadata metadata, Action? configureOperationOptions = null, TimeSpan? deadline = null, UserCredentials? userCredentials = null, CancellationToken cancellationToken = default) { var options = Settings.OperationOptions.Clone(); @@ -91,7 +91,7 @@ public Task SetStreamMetadataAsync(string streamName, StreamRevisi private async Task SetStreamMetadataInternal(StreamMetadata metadata, AppendReq appendReq, - EventStoreClientOperationOptions operationOptions, + KurrentClientOperationOptions operationOptions, TimeSpan? deadline, UserCredentials? userCredentials, CancellationToken cancellationToken) { diff --git a/src/EventStore.Client.Streams/EventStoreClient.Read.cs b/src/Kurrent.Client/Streams/KurrentClient.Read.cs similarity index 97% rename from src/EventStore.Client.Streams/EventStoreClient.Read.cs rename to src/Kurrent.Client/Streams/KurrentClient.Read.cs index 7960622ea..0523d9516 100644 --- a/src/EventStore.Client.Streams/EventStoreClient.Read.cs +++ b/src/Kurrent.Client/Streams/KurrentClient.Read.cs @@ -5,7 +5,7 @@ using static EventStore.Client.Streams.ReadResp.ContentOneofCase; namespace EventStore.Client { - public partial class EventStoreClient { + public partial class KurrentClient { /// /// Asynchronously reads all events. /// @@ -140,10 +140,10 @@ async IAsyncEnumerable GetMessages() { internal ReadAllStreamResult( Func> selectCallInvoker, ReadReq request, - EventStoreClientSettings settings, TimeSpan? deadline, UserCredentials? userCredentials, + KurrentClientSettings settings, TimeSpan? deadline, UserCredentials? userCredentials, CancellationToken cancellationToken ) { - var callOptions = EventStoreCallOptions.CreateStreaming( + var callOptions = KurrentCallOptions.CreateStreaming( settings, deadline, userCredentials, @@ -339,10 +339,10 @@ async IAsyncEnumerable GetMessages() { internal ReadStreamResult( Func> selectCallInvoker, ReadReq request, - EventStoreClientSettings settings, TimeSpan? deadline, UserCredentials? userCredentials, + KurrentClientSettings settings, TimeSpan? deadline, UserCredentials? userCredentials, CancellationToken cancellationToken ) { - var callOptions = EventStoreCallOptions.CreateStreaming( + var callOptions = KurrentCallOptions.CreateStreaming( settings, deadline, userCredentials, @@ -465,4 +465,4 @@ static ResolvedEvent ConvertToResolvedEvent(ReadResp.Types.ReadEvent readEvent) e.CustomMetadata.ToByteArray() ); } -} \ No newline at end of file +} diff --git a/src/EventStore.Client.Streams/EventStoreClient.Subscriptions.cs b/src/Kurrent.Client/Streams/KurrentClient.Subscriptions.cs similarity index 97% rename from src/EventStore.Client.Streams/EventStoreClient.Subscriptions.cs rename to src/Kurrent.Client/Streams/KurrentClient.Subscriptions.cs index 6f3b2f2c6..92adb172b 100644 --- a/src/EventStore.Client.Streams/EventStoreClient.Subscriptions.cs +++ b/src/Kurrent.Client/Streams/KurrentClient.Subscriptions.cs @@ -6,7 +6,7 @@ using static EventStore.Client.Streams.ReadResp.ContentOneofCase; namespace EventStore.Client { - public partial class EventStoreClient { + public partial class KurrentClient { /// /// Subscribes to all events. /// @@ -133,7 +133,7 @@ public class StreamSubscriptionResult : IAsyncEnumerable, IAsyncD private readonly Channel _channel; private readonly CancellationTokenSource _cts; private readonly CallOptions _callOptions; - private readonly EventStoreClientSettings _settings; + private readonly KurrentClientSettings _settings; private AsyncServerStreamingCall? _call; private int _messagesEnumerated; @@ -175,13 +175,13 @@ async IAsyncEnumerable GetMessages() { internal StreamSubscriptionResult( Func> selectChannelInfo, - ReadReq request, EventStoreClientSettings settings, UserCredentials? userCredentials, + ReadReq request, KurrentClientSettings settings, UserCredentials? userCredentials, CancellationToken cancellationToken ) { _request = request; _settings = settings; - _callOptions = EventStoreCallOptions.CreateStreaming( + _callOptions = KurrentCallOptions.CreateStreaming( settings, userCredentials: userCredentials, cancellationToken: cancellationToken @@ -229,7 +229,7 @@ async Task PumpMessages() { }; if (subscriptionMessage is StreamMessage.Event evt) - EventStoreClientDiagnostics.ActivitySource.TraceSubscriptionEvent( + KurrentClientDiagnostics.ActivitySource.TraceSubscriptionEvent( SubscriptionId, evt.ResolvedEvent, channelInfo, diff --git a/src/EventStore.Client.Streams/EventStoreClient.Tombstone.cs b/src/Kurrent.Client/Streams/KurrentClient.Tombstone.cs similarity index 95% rename from src/EventStore.Client.Streams/EventStoreClient.Tombstone.cs rename to src/Kurrent.Client/Streams/KurrentClient.Tombstone.cs index 9fcddfeb4..26d62dad9 100644 --- a/src/EventStore.Client.Streams/EventStoreClient.Tombstone.cs +++ b/src/Kurrent.Client/Streams/KurrentClient.Tombstone.cs @@ -5,7 +5,7 @@ using Microsoft.Extensions.Logging; namespace EventStore.Client { - public partial class EventStoreClient { + public partial class KurrentClient { /// /// Tombstones a stream asynchronously. Note: Tombstoned streams can never be recreated. /// @@ -54,7 +54,7 @@ private async Task TombstoneInternal(TombstoneReq request, TimeSpa var channelInfo = await GetChannelInfo(cancellationToken).ConfigureAwait(false); using var call = new Streams.Streams.StreamsClient( channelInfo.CallInvoker).TombstoneAsync(request, - EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); var result = await call.ResponseAsync.ConfigureAwait(false); return new DeleteResult(new Position(result.Position.CommitPosition, result.Position.PreparePosition)); diff --git a/src/EventStore.Client.Streams/EventStoreClient.cs b/src/Kurrent.Client/Streams/KurrentClient.cs similarity index 90% rename from src/EventStore.Client.Streams/EventStoreClient.cs rename to src/Kurrent.Client/Streams/KurrentClient.cs index 9474ff653..3dccf53ee 100644 --- a/src/EventStore.Client.Streams/EventStoreClient.cs +++ b/src/Kurrent.Client/Streams/KurrentClient.cs @@ -10,7 +10,7 @@ namespace EventStore.Client { /// /// The client used for operations on streams. /// - public sealed partial class EventStoreClient : EventStoreClientBase { + public sealed partial class KurrentClient : KurrentClientBase { static readonly JsonSerializerOptions StreamMetadataJsonSerializerOptions = new() { Converters = { StreamMetadataJsonConverter.Instance @@ -23,7 +23,7 @@ public sealed partial class EventStoreClient : EventStoreClientBase { AllowSynchronousContinuations = true }; - readonly ILogger _log; + readonly ILogger _log; Lazy _batchAppenderLazy; StreamAppender BatchAppender => _batchAppenderLazy.Value; readonly CancellationTokenSource _disposedTokenSource; @@ -56,17 +56,17 @@ public sealed partial class EventStoreClient : EventStoreClientBase { }; /// - /// Constructs a new . This is not intended to be called directly from your code. + /// Constructs a new . This is not intended to be called directly from your code. /// /// - public EventStoreClient(IOptions options) : this(options.Value) { } + public KurrentClient(IOptions options) : this(options.Value) { } /// - /// Constructs a new . + /// Constructs a new . /// /// - public EventStoreClient(EventStoreClientSettings? settings = null) : base(settings, ExceptionMap) { - _log = Settings.LoggerFactory?.CreateLogger() ?? new NullLogger(); + public KurrentClient(KurrentClientSettings? settings = null) : base(settings, ExceptionMap) { + _log = Settings.LoggerFactory?.CreateLogger() ?? new NullLogger(); _disposedTokenSource = new CancellationTokenSource(); _batchAppenderLazy = new Lazy(CreateStreamAppender); } @@ -163,4 +163,4 @@ public override async ValueTask DisposeAsync() { await base.DisposeAsync().ConfigureAwait(false); } } -} \ No newline at end of file +} diff --git a/src/EventStore.Client.Streams/EventStoreClientExtensions.cs b/src/Kurrent.Client/Streams/KurrentClientExtensions.cs similarity index 94% rename from src/EventStore.Client.Streams/EventStoreClientExtensions.cs rename to src/Kurrent.Client/Streams/KurrentClientExtensions.cs index 85a78dbe5..690fa89bd 100644 --- a/src/EventStore.Client.Streams/EventStoreClientExtensions.cs +++ b/src/Kurrent.Client/Streams/KurrentClientExtensions.cs @@ -6,9 +6,9 @@ namespace EventStore.Client { /// - /// A set of extension methods for an . + /// A set of extension methods for an . /// - public static class EventStoreClientExtensions { + public static class KurrentClientExtensions { private static readonly JsonSerializerOptions SystemSettingsJsonSerializerOptions = new JsonSerializerOptions { Converters = { SystemSettingsJsonConverter.Instance @@ -26,7 +26,7 @@ public static class EventStoreClientExtensions { /// /// public static Task SetSystemSettingsAsync( - this EventStoreClient client, + this KurrentClient client, SystemSettings settings, TimeSpan? deadline = null, UserCredentials? userCredentials = null, CancellationToken cancellationToken = default) { @@ -51,7 +51,7 @@ public static Task SetSystemSettingsAsync( /// /// public static async Task ConditionalAppendToStreamAsync( - this EventStoreClient client, + this KurrentClient client, string streamName, StreamRevision expectedRevision, IEnumerable eventData, @@ -84,7 +84,7 @@ public static async Task ConditionalAppendToStreamAsync( /// /// public static async Task ConditionalAppendToStreamAsync( - this EventStoreClient client, + this KurrentClient client, string streamName, StreamState expectedState, IEnumerable eventData, diff --git a/src/EventStore.Client.Streams/EventStoreClientServiceCollectionExtensions.cs b/src/Kurrent.Client/Streams/KurrentClientServiceCollectionExtensions.cs similarity index 54% rename from src/EventStore.Client.Streams/EventStoreClientServiceCollectionExtensions.cs rename to src/Kurrent.Client/Streams/KurrentClientServiceCollectionExtensions.cs index 5278f4a6d..b2832fa56 100644 --- a/src/EventStore.Client.Streams/EventStoreClientServiceCollectionExtensions.cs +++ b/src/Kurrent.Client/Streams/KurrentClientServiceCollectionExtensions.cs @@ -9,116 +9,116 @@ namespace Microsoft.Extensions.DependencyInjection { /// - /// A set of extension methods for which provide support for an . + /// A set of extension methods for which provide support for an . /// - public static class EventStoreClientServiceCollectionExtensions { + public static class KurrentClientServiceCollectionExtensions { /// - /// Adds an to the . + /// Adds an to the . /// /// /// /// /// /// - public static IServiceCollection AddEventStoreClient(this IServiceCollection services, Uri address, + public static IServiceCollection AddKurrentClient(this IServiceCollection services, Uri address, Func? createHttpMessageHandler = null) - => services.AddEventStoreClient(options => { + => services.AddKurrentClient(options => { options.ConnectivitySettings.Address = address; options.CreateHttpMessageHandler = createHttpMessageHandler; }); /// - /// Adds an to the . + /// Adds an to the . /// /// /// /// /// /// - public static IServiceCollection AddEventStoreClient(this IServiceCollection services, + public static IServiceCollection AddKurrentClient(this IServiceCollection services, Func addressFactory, Func? createHttpMessageHandler = null) - => services.AddEventStoreClient(provider => options => { + => services.AddKurrentClient(provider => options => { options.ConnectivitySettings.Address = addressFactory(provider); options.CreateHttpMessageHandler = createHttpMessageHandler; }); /// - /// Adds an to the . + /// Adds an to the . /// /// /// /// /// - public static IServiceCollection AddEventStoreClient(this IServiceCollection services, - Action? configureSettings = null) => - services.AddEventStoreClient(new EventStoreClientSettings(), configureSettings); + public static IServiceCollection AddKurrentClient(this IServiceCollection services, + Action? configureSettings = null) => + services.AddKurrentClient(new KurrentClientSettings(), configureSettings); /// - /// Adds an to the . + /// Adds an to the . /// /// /// /// /// - public static IServiceCollection AddEventStoreClient(this IServiceCollection services, - Func> configureSettings) => - services.AddEventStoreClient(new EventStoreClientSettings(), + public static IServiceCollection AddKurrentClient(this IServiceCollection services, + Func> configureSettings) => + services.AddKurrentClient(new KurrentClientSettings(), configureSettings); /// - /// Adds an to the . + /// Adds an to the . /// /// /// /// /// /// - public static IServiceCollection AddEventStoreClient(this IServiceCollection services, - string connectionString, Action? configureSettings = null) { + public static IServiceCollection AddKurrentClient(this IServiceCollection services, + string connectionString, Action? configureSettings = null) { if (services == null) { throw new ArgumentNullException(nameof(services)); } - return services.AddEventStoreClient(EventStoreClientSettings.Create(connectionString), configureSettings); + return services.AddKurrentClient(KurrentClientSettings.Create(connectionString), configureSettings); } /// - /// Adds an to the . + /// Adds an to the . /// /// /// /// /// /// - public static IServiceCollection AddEventStoreClient(this IServiceCollection services, + public static IServiceCollection AddKurrentClient(this IServiceCollection services, Func connectionStringFactory, - Action? configureSettings = null) { + Action? configureSettings = null) { if (services == null) { throw new ArgumentNullException(nameof(services)); } - return services.AddEventStoreClient(provider => EventStoreClientSettings.Create(connectionStringFactory(provider)), configureSettings); + return services.AddKurrentClient(provider => KurrentClientSettings.Create(connectionStringFactory(provider)), configureSettings); } - private static IServiceCollection AddEventStoreClient(this IServiceCollection services, - EventStoreClientSettings settings, - Action? configureSettings) { + private static IServiceCollection AddKurrentClient(this IServiceCollection services, + KurrentClientSettings settings, + Action? configureSettings) { configureSettings?.Invoke(settings); services.TryAddSingleton(provider => { settings.LoggerFactory ??= provider.GetService(); settings.Interceptors ??= provider.GetServices(); - return new EventStoreClient(settings); + return new KurrentClient(settings); }); return services; } - private static IServiceCollection AddEventStoreClient(this IServiceCollection services, - Func settingsFactory, - Action? configureSettings = null) { + private static IServiceCollection AddKurrentClient(this IServiceCollection services, + Func settingsFactory, + Action? configureSettings = null) { services.TryAddSingleton(provider => { var settings = settingsFactory(provider); @@ -127,15 +127,15 @@ private static IServiceCollection AddEventStoreClient(this IServiceCollection se settings.LoggerFactory ??= provider.GetService(); settings.Interceptors ??= provider.GetServices(); - return new EventStoreClient(settings); + return new KurrentClient(settings); }); return services; } - private static IServiceCollection AddEventStoreClient(this IServiceCollection services, - EventStoreClientSettings settings, - Func> configureSettingsFactory) { + private static IServiceCollection AddKurrentClient(this IServiceCollection services, + KurrentClientSettings settings, + Func> configureSettingsFactory) { services.TryAddSingleton(provider => { configureSettingsFactory(provider).Invoke(settings); @@ -143,7 +143,7 @@ private static IServiceCollection AddEventStoreClient(this IServiceCollection se settings.LoggerFactory ??= provider.GetService(); settings.Interceptors ??= provider.GetServices(); - return new EventStoreClient(settings); + return new KurrentClient(settings); }); return services; diff --git a/src/EventStore.Client.Streams/MaximumAppendSizeExceededException.cs b/src/Kurrent.Client/Streams/MaximumAppendSizeExceededException.cs similarity index 100% rename from src/EventStore.Client.Streams/MaximumAppendSizeExceededException.cs rename to src/Kurrent.Client/Streams/MaximumAppendSizeExceededException.cs diff --git a/src/EventStore.Client.Streams/ReadState.cs b/src/Kurrent.Client/Streams/ReadState.cs similarity index 100% rename from src/EventStore.Client.Streams/ReadState.cs rename to src/Kurrent.Client/Streams/ReadState.cs diff --git a/src/EventStore.Client.Streams/StreamAcl.cs b/src/Kurrent.Client/Streams/StreamAcl.cs similarity index 100% rename from src/EventStore.Client.Streams/StreamAcl.cs rename to src/Kurrent.Client/Streams/StreamAcl.cs diff --git a/src/EventStore.Client.Streams/StreamAclJsonConverter.cs b/src/Kurrent.Client/Streams/StreamAclJsonConverter.cs similarity index 100% rename from src/EventStore.Client.Streams/StreamAclJsonConverter.cs rename to src/Kurrent.Client/Streams/StreamAclJsonConverter.cs diff --git a/src/EventStore.Client.Streams/StreamMessage.cs b/src/Kurrent.Client/Streams/StreamMessage.cs similarity index 57% rename from src/EventStore.Client.Streams/StreamMessage.cs rename to src/Kurrent.Client/Streams/StreamMessage.cs index 4f1a87559..54aaffad9 100644 --- a/src/EventStore.Client.Streams/StreamMessage.cs +++ b/src/Kurrent.Client/Streams/StreamMessage.cs @@ -4,9 +4,9 @@ namespace EventStore.Client { /// public abstract record StreamMessage { /// - /// A that represents a . + /// A that represents a . /// - /// The . + /// The . public record Event(ResolvedEvent ResolvedEvent) : StreamMessage; /// @@ -24,57 +24,57 @@ public record Ok : StreamMessage { }; /// - /// A indicating the first position of a stream. + /// A indicating the first position of a stream. /// - /// The . + /// The . public record FirstStreamPosition(StreamPosition StreamPosition) : StreamMessage; /// - /// A indicating the last position of a stream. + /// A indicating the last position of a stream. /// - /// The . + /// The . public record LastStreamPosition(StreamPosition StreamPosition) : StreamMessage; /// - /// A indicating the last position of the $all stream. + /// A indicating the last position of the $all stream. /// - /// The . + /// The . public record LastAllStreamPosition(Position Position) : StreamMessage; /// - /// A indicating that the subscription is ready to send additional messages. + /// A indicating that the subscription is ready to send additional messages. /// /// The unique identifier of the subscription. public record SubscriptionConfirmation(string SubscriptionId) : StreamMessage; /// - /// A indicating that a checkpoint has been reached. + /// A indicating that a checkpoint has been reached. /// /// The . public record AllStreamCheckpointReached(Position Position) : StreamMessage; /// - /// A indicating that a checkpoint has been reached. + /// A indicating that a checkpoint has been reached. /// /// The . public record StreamCheckpointReached(StreamPosition StreamPosition) : StreamMessage; /// - /// A indicating that the subscription is live. + /// A indicating that the subscription is live. /// public record CaughtUp : StreamMessage { internal static readonly CaughtUp Instance = new(); } /// - /// A indicating that the subscription has switched to catch up mode. + /// A indicating that the subscription has switched to catch up mode. /// public record FellBehind : StreamMessage { internal static readonly FellBehind Instance = new(); } /// - /// A that could not be identified, usually indicating a lower client compatibility level than the server supports. + /// A that could not be identified, usually indicating a lower client compatibility level than the server supports. /// public record Unknown : StreamMessage { internal static readonly Unknown Instance = new(); diff --git a/src/EventStore.Client.Streams/StreamMetadata.cs b/src/Kurrent.Client/Streams/StreamMetadata.cs similarity index 100% rename from src/EventStore.Client.Streams/StreamMetadata.cs rename to src/Kurrent.Client/Streams/StreamMetadata.cs diff --git a/src/EventStore.Client.Streams/StreamMetadataJsonConverter.cs b/src/Kurrent.Client/Streams/StreamMetadataJsonConverter.cs similarity index 100% rename from src/EventStore.Client.Streams/StreamMetadataJsonConverter.cs rename to src/Kurrent.Client/Streams/StreamMetadataJsonConverter.cs diff --git a/src/EventStore.Client.Streams/StreamMetadataResult.cs b/src/Kurrent.Client/Streams/StreamMetadataResult.cs similarity index 100% rename from src/EventStore.Client.Streams/StreamMetadataResult.cs rename to src/Kurrent.Client/Streams/StreamMetadataResult.cs diff --git a/src/EventStore.Client.Streams/StreamSubscription.cs b/src/Kurrent.Client/Streams/StreamSubscription.cs similarity index 96% rename from src/EventStore.Client.Streams/StreamSubscription.cs rename to src/Kurrent.Client/Streams/StreamSubscription.cs index f70080c17..e7271b364 100644 --- a/src/EventStore.Client.Streams/StreamSubscription.cs +++ b/src/Kurrent.Client/Streams/StreamSubscription.cs @@ -6,7 +6,7 @@ namespace EventStore.Client { /// A class representing a . /// public class StreamSubscription : IDisposable { - private readonly EventStoreClient.StreamSubscriptionResult _subscription; + private readonly KurrentClient.StreamSubscriptionResult _subscription; private readonly IAsyncEnumerator _messages; private readonly Func _eventAppeared; private readonly Func _checkpointReached; @@ -21,7 +21,7 @@ public class StreamSubscription : IDisposable { public string SubscriptionId { get; } internal static async Task Confirm( - EventStoreClient.StreamSubscriptionResult subscription, + KurrentClient.StreamSubscriptionResult subscription, Func eventAppeared, Action? subscriptionDropped, ILogger log, @@ -49,7 +49,7 @@ enumerator.Current is not StreamMessage.SubscriptionConfirmation(var subscriptio } private StreamSubscription( - EventStoreClient.StreamSubscriptionResult subscription, + KurrentClient.StreamSubscriptionResult subscription, IAsyncEnumerator messages, string subscriptionId, Func eventAppeared, Action? subscriptionDropped, diff --git a/src/EventStore.Client.Streams/Streams/AppendReq.cs b/src/Kurrent.Client/Streams/Streams/AppendReq.cs similarity index 100% rename from src/EventStore.Client.Streams/Streams/AppendReq.cs rename to src/Kurrent.Client/Streams/Streams/AppendReq.cs diff --git a/src/EventStore.Client.Streams/Streams/BatchAppendReq.cs b/src/Kurrent.Client/Streams/Streams/BatchAppendReq.cs similarity index 100% rename from src/EventStore.Client.Streams/Streams/BatchAppendReq.cs rename to src/Kurrent.Client/Streams/Streams/BatchAppendReq.cs diff --git a/src/EventStore.Client.Streams/Streams/BatchAppendResp.cs b/src/Kurrent.Client/Streams/Streams/BatchAppendResp.cs similarity index 98% rename from src/EventStore.Client.Streams/Streams/BatchAppendResp.cs rename to src/Kurrent.Client/Streams/Streams/BatchAppendResp.cs index 926dcee25..4be031057 100644 --- a/src/EventStore.Client.Streams/Streams/BatchAppendResp.cs +++ b/src/Kurrent.Client/Streams/Streams/BatchAppendResp.cs @@ -1,5 +1,5 @@ -using System; using Grpc.Core; +using EventStore.Client; using static EventStore.Client.WrongExpectedVersion.CurrentStreamRevisionOptionOneofCase; using static EventStore.Client.WrongExpectedVersion.ExpectedStreamPositionOptionOneofCase; diff --git a/src/EventStore.Client.Streams/Streams/DeleteReq.cs b/src/Kurrent.Client/Streams/Streams/DeleteReq.cs similarity index 100% rename from src/EventStore.Client.Streams/Streams/DeleteReq.cs rename to src/Kurrent.Client/Streams/Streams/DeleteReq.cs diff --git a/src/EventStore.Client.Streams/Streams/ReadReq.cs b/src/Kurrent.Client/Streams/Streams/ReadReq.cs similarity index 100% rename from src/EventStore.Client.Streams/Streams/ReadReq.cs rename to src/Kurrent.Client/Streams/Streams/ReadReq.cs diff --git a/src/EventStore.Client.Streams/Streams/TombstoneReq.cs b/src/Kurrent.Client/Streams/Streams/TombstoneReq.cs similarity index 100% rename from src/EventStore.Client.Streams/Streams/TombstoneReq.cs rename to src/Kurrent.Client/Streams/Streams/TombstoneReq.cs diff --git a/src/EventStore.Client.Streams/SubscriptionFilterOptions.cs b/src/Kurrent.Client/Streams/SubscriptionFilterOptions.cs similarity index 100% rename from src/EventStore.Client.Streams/SubscriptionFilterOptions.cs rename to src/Kurrent.Client/Streams/SubscriptionFilterOptions.cs diff --git a/src/EventStore.Client.Streams/SuccessResult.cs b/src/Kurrent.Client/Streams/SuccessResult.cs similarity index 100% rename from src/EventStore.Client.Streams/SuccessResult.cs rename to src/Kurrent.Client/Streams/SuccessResult.cs diff --git a/src/EventStore.Client.Streams/SystemEventTypes.cs b/src/Kurrent.Client/Streams/SystemEventTypes.cs similarity index 100% rename from src/EventStore.Client.Streams/SystemEventTypes.cs rename to src/Kurrent.Client/Streams/SystemEventTypes.cs diff --git a/src/EventStore.Client.Streams/SystemMetadata.cs b/src/Kurrent.Client/Streams/SystemMetadata.cs similarity index 100% rename from src/EventStore.Client.Streams/SystemMetadata.cs rename to src/Kurrent.Client/Streams/SystemMetadata.cs diff --git a/src/EventStore.Client.Streams/SystemSettings.cs b/src/Kurrent.Client/Streams/SystemSettings.cs similarity index 100% rename from src/EventStore.Client.Streams/SystemSettings.cs rename to src/Kurrent.Client/Streams/SystemSettings.cs diff --git a/src/EventStore.Client.Streams/SystemSettingsJsonConverter.cs b/src/Kurrent.Client/Streams/SystemSettingsJsonConverter.cs similarity index 100% rename from src/EventStore.Client.Streams/SystemSettingsJsonConverter.cs rename to src/Kurrent.Client/Streams/SystemSettingsJsonConverter.cs diff --git a/src/EventStore.Client.Streams/WriteResultExtensions.cs b/src/Kurrent.Client/Streams/WriteResultExtensions.cs similarity index 91% rename from src/EventStore.Client.Streams/WriteResultExtensions.cs rename to src/Kurrent.Client/Streams/WriteResultExtensions.cs index ed83c532e..7b5005e02 100644 --- a/src/EventStore.Client.Streams/WriteResultExtensions.cs +++ b/src/Kurrent.Client/Streams/WriteResultExtensions.cs @@ -1,7 +1,7 @@ namespace EventStore.Client { internal static class WriteResultExtensions { public static IWriteResult OptionallyThrowWrongExpectedVersionException(this IWriteResult writeResult, - EventStoreClientOperationOptions options) => + KurrentClientOperationOptions options) => (options.ThrowOnAppendFailure, writeResult) switch { (true, WrongExpectedVersionResult wrongExpectedVersionResult) => throw new WrongExpectedVersionException(wrongExpectedVersionResult.StreamName, diff --git a/src/EventStore.Client.Streams/WrongExpectedVersionResult.cs b/src/Kurrent.Client/Streams/WrongExpectedVersionResult.cs similarity index 100% rename from src/EventStore.Client.Streams/WrongExpectedVersionResult.cs rename to src/Kurrent.Client/Streams/WrongExpectedVersionResult.cs diff --git a/src/EventStore.Client.UserManagement/EventStoreUserManagementClient.cs b/src/Kurrent.Client/UserManagement/KurrentUserManagementClient.cs similarity index 90% rename from src/EventStore.Client.UserManagement/EventStoreUserManagementClient.cs rename to src/Kurrent.Client/UserManagement/KurrentUserManagementClient.cs index 6b86e81b4..ce18d40a0 100644 --- a/src/EventStore.Client.UserManagement/EventStoreUserManagementClient.cs +++ b/src/Kurrent.Client/UserManagement/KurrentUserManagementClient.cs @@ -8,17 +8,17 @@ namespace EventStore.Client { /// /// The client used for operations on internal users. /// - public sealed class EventStoreUserManagementClient : EventStoreClientBase { + public sealed class KurrentUserManagementClient : KurrentClientBase { private readonly ILogger _log; /// - /// Constructs a new . + /// Constructs a new . /// /// - public EventStoreUserManagementClient(EventStoreClientSettings? settings = null) : + public KurrentUserManagementClient(KurrentClientSettings? settings = null) : base(settings, ExceptionMap) { - _log = Settings.LoggerFactory?.CreateLogger() ?? - new NullLogger(); + _log = Settings.LoggerFactory?.CreateLogger() ?? + new NullLogger(); } /// @@ -54,7 +54,7 @@ public async Task CreateUserAsync(string loginName, string fullName, string[] gr Password = password, Groups = {groups} } - }, EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + }, KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); await call.ResponseAsync.ConfigureAwait(false); } @@ -84,7 +84,7 @@ public async Task GetUserAsync(string loginName, TimeSpan? deadline Options = new DetailsReq.Types.Options { LoginName = loginName } - }, EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + }, KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); await call.ResponseStream.MoveNext().ConfigureAwait(false); var userDetails = call.ResponseStream.Current.UserDetails; @@ -121,7 +121,7 @@ public async Task DeleteUserAsync(string loginName, TimeSpan? deadline = null, Options = new DeleteReq.Types.Options { LoginName = loginName } - }, EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + }, KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); await call.ResponseAsync.ConfigureAwait(false); } @@ -151,7 +151,7 @@ public async Task EnableUserAsync(string loginName, TimeSpan? deadline = null, Options = new EnableReq.Types.Options { LoginName = loginName } - }, EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + }, KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); await call.ResponseAsync.ConfigureAwait(false); } @@ -174,7 +174,7 @@ public async Task DisableUserAsync(string loginName, TimeSpan? deadline = null, Options = new DisableReq.Types.Options { LoginName = loginName } - }, EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + }, KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); await call.ResponseAsync.ConfigureAwait(false); } @@ -191,7 +191,7 @@ public async IAsyncEnumerable ListAllAsync(TimeSpan? deadline = nul var channelInfo = await GetChannelInfo(cancellationToken).ConfigureAwait(false); using var call = new Users.Users.UsersClient( channelInfo.CallInvoker).Details(new DetailsReq(), - EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); await foreach (var userDetail in call.ResponseStream .ReadAllAsync(cancellationToken) @@ -234,7 +234,7 @@ public async Task ChangePasswordAsync(string loginName, string currentPassword, LoginName = loginName } }, - EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); await call.ResponseAsync.ConfigureAwait(false); } @@ -266,7 +266,7 @@ public async Task ResetPasswordAsync(string loginName, string newPassword, LoginName = loginName } }, - EventStoreCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); + KurrentCallOptions.CreateNonStreaming(Settings, deadline, userCredentials, cancellationToken)); await call.ResponseAsync.ConfigureAwait(false); } diff --git a/src/EventStore.Client.UserManagement/EventStoreUserManagementClientCollectionExtensions.cs b/src/Kurrent.Client/UserManagement/KurrentUserManagementClientCollectionExtensions.cs similarity index 53% rename from src/EventStore.Client.UserManagement/EventStoreUserManagementClientCollectionExtensions.cs rename to src/Kurrent.Client/UserManagement/KurrentUserManagementClientCollectionExtensions.cs index 2b25f816c..220f99740 100644 --- a/src/EventStore.Client.UserManagement/EventStoreUserManagementClientCollectionExtensions.cs +++ b/src/Kurrent.Client/UserManagement/KurrentUserManagementClientCollectionExtensions.cs @@ -8,51 +8,51 @@ namespace Microsoft.Extensions.DependencyInjection { /// - /// A set of extension methods for which provide support for an . + /// A set of extension methods for which provide support for an . /// - public static class EventStoreUserManagementClientCollectionExtensions { + public static class KurrentUserManagementClientCollectionExtensions { /// - /// Adds an to the . + /// Adds an to the . /// /// /// /// /// /// - public static IServiceCollection AddEventStoreUserManagementClient(this IServiceCollection services, + public static IServiceCollection AddKurrentUserManagementClient(this IServiceCollection services, Uri address, Func? createHttpMessageHandler = null) - => services.AddEventStoreUserManagementClient(options => { + => services.AddKurrentUserManagementClient(options => { options.ConnectivitySettings.Address = address; options.CreateHttpMessageHandler = createHttpMessageHandler; }); /// - /// Adds an to the . + /// Adds an to the . /// /// /// /// /// /// - public static IServiceCollection AddEventStoreUserManagementClient(this IServiceCollection services, - string connectionString, Action? configureSettings = null) - => services.AddEventStoreUserManagementClient(EventStoreClientSettings.Create(connectionString), + public static IServiceCollection AddKurrentUserManagementClient(this IServiceCollection services, + string connectionString, Action? configureSettings = null) + => services.AddKurrentUserManagementClient(KurrentClientSettings.Create(connectionString), configureSettings); /// - /// Adds an to the . + /// Adds an to the . /// /// /// /// /// - public static IServiceCollection AddEventStoreUserManagementClient(this IServiceCollection services, - Action? configureSettings = null) => - services.AddEventStoreUserManagementClient(new EventStoreClientSettings(), configureSettings); + public static IServiceCollection AddKurrentUserManagementClient(this IServiceCollection services, + Action? configureSettings = null) => + services.AddKurrentUserManagementClient(new KurrentClientSettings(), configureSettings); - private static IServiceCollection AddEventStoreUserManagementClient(this IServiceCollection services, - EventStoreClientSettings settings, Action? configureSettings = null) { + private static IServiceCollection AddKurrentUserManagementClient(this IServiceCollection services, + KurrentClientSettings settings, Action? configureSettings = null) { configureSettings?.Invoke(settings); if (services == null) { throw new ArgumentNullException(nameof(services)); @@ -62,7 +62,7 @@ private static IServiceCollection AddEventStoreUserManagementClient(this IServic settings.LoggerFactory ??= provider.GetService(); settings.Interceptors ??= provider.GetServices(); - return new EventStoreUserManagementClient(settings); + return new KurrentUserManagementClient(settings); }); return services; diff --git a/src/EventStore.Client.UserManagement/EventStoreUserManagerClientExtensions.cs b/src/Kurrent.Client/UserManagement/KurrentUserManagerClientExtensions.cs similarity index 75% rename from src/EventStore.Client.UserManagement/EventStoreUserManagerClientExtensions.cs rename to src/Kurrent.Client/UserManagement/KurrentUserManagerClientExtensions.cs index a43ae43d7..be365fdd2 100644 --- a/src/EventStore.Client.UserManagement/EventStoreUserManagerClientExtensions.cs +++ b/src/Kurrent.Client/UserManagement/KurrentUserManagerClientExtensions.cs @@ -1,9 +1,9 @@ -namespace EventStore.Client; +namespace EventStore.Client; /// -/// A set of extension methods for an . +/// A set of extension methods for an . /// -public static class EventStoreUserManagerClientExtensions { +public static class KurrentUserManagerClientExtensions { /// /// Gets the of the internal user specified by the supplied . /// @@ -13,11 +13,11 @@ public static class EventStoreUserManagerClientExtensions { /// /// public static Task GetCurrentUserAsync( - this EventStoreUserManagementClient users, + this KurrentUserManagementClient users, UserCredentials userCredentials, TimeSpan? deadline = null, CancellationToken cancellationToken = default ) => users.GetUserAsync( userCredentials.Username!, deadline, userCredentials, cancellationToken ); -} \ No newline at end of file +} diff --git a/src/EventStore.Client.UserManagement/UserDetails.cs b/src/Kurrent.Client/UserManagement/UserDetails.cs similarity index 99% rename from src/EventStore.Client.UserManagement/UserDetails.cs rename to src/Kurrent.Client/UserManagement/UserDetails.cs index 92c345eea..b7414dd36 100644 --- a/src/EventStore.Client.UserManagement/UserDetails.cs +++ b/src/Kurrent.Client/UserManagement/UserDetails.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client; +namespace EventStore.Client; /// /// Provides the details for a user. @@ -94,4 +94,4 @@ public override string ToString() => LoginName, Groups = string.Join(",", Groups) }?.ToString()!; -} \ No newline at end of file +} diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 151f65d09..6630ffb1b 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -3,38 +3,42 @@ true - xUnit1031 + xUnit1031;NU1903 + false + false - - - + + + - - + + all runtime; build; native; contentfiles; analyzers + + - + - + - + diff --git a/test/EventStore.Client.Operations.Tests/AssemblyInfo.cs b/test/EventStore.Client.Operations.Tests/AssemblyInfo.cs deleted file mode 100644 index b0b47aa73..000000000 --- a/test/EventStore.Client.Operations.Tests/AssemblyInfo.cs +++ /dev/null @@ -1 +0,0 @@ -[assembly: CollectionBehavior(DisableTestParallelization = true)] \ No newline at end of file diff --git a/test/EventStore.Client.Operations.Tests/EventStore.Client.Operations.Tests.csproj b/test/EventStore.Client.Operations.Tests/EventStore.Client.Operations.Tests.csproj deleted file mode 100644 index d43bdceb5..000000000 --- a/test/EventStore.Client.Operations.Tests/EventStore.Client.Operations.Tests.csproj +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/test/EventStore.Client.Operations.Tests/MergeIndexesTests.cs b/test/EventStore.Client.Operations.Tests/MergeIndexesTests.cs deleted file mode 100644 index c4cf7bfb0..000000000 --- a/test/EventStore.Client.Operations.Tests/MergeIndexesTests.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace EventStore.Client.Operations.Tests; - -public class MergeIndexesTests : IClassFixture { - public MergeIndexesTests(ITestOutputHelper output, InsecureClientTestFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - InsecureClientTestFixture Fixture { get; } - - [Fact] - public async Task merge_indexes_does_not_throw() => - await Fixture.Operations - .MergeIndexesAsync(userCredentials: TestCredentials.Root) - .ShouldNotThrowAsync(); - - [Fact] - public async Task merge_indexes_without_credentials_throws() => - await Fixture.Operations - .MergeIndexesAsync() - .ShouldThrowAsync(); -} \ No newline at end of file diff --git a/test/EventStore.Client.Operations.Tests/ResignNodeTests.cs b/test/EventStore.Client.Operations.Tests/ResignNodeTests.cs deleted file mode 100644 index 6012ae943..000000000 --- a/test/EventStore.Client.Operations.Tests/ResignNodeTests.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace EventStore.Client.Operations.Tests; - -public class ResignNodeTests : IClassFixture { - public ResignNodeTests(ITestOutputHelper output, InsecureClientTestFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - InsecureClientTestFixture Fixture { get; } - - [Fact] - public async Task resign_node_does_not_throw() => - await Fixture.Operations - .ResignNodeAsync(userCredentials: TestCredentials.Root) - .ShouldNotThrowAsync(); - - [Fact] - public async Task resign_node_without_credentials_throws() => - await Fixture.Operations - .ResignNodeAsync() - .ShouldThrowAsync(); -} \ No newline at end of file diff --git a/test/EventStore.Client.Operations.Tests/RestartPersistentSubscriptionsTests.cs b/test/EventStore.Client.Operations.Tests/RestartPersistentSubscriptionsTests.cs deleted file mode 100644 index 1d04d1ca4..000000000 --- a/test/EventStore.Client.Operations.Tests/RestartPersistentSubscriptionsTests.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace EventStore.Client.Operations.Tests; - -public class RestartPersistentSubscriptionsTests : IClassFixture { - public RestartPersistentSubscriptionsTests(ITestOutputHelper output, InsecureClientTestFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - InsecureClientTestFixture Fixture { get; } - - [Fact] - public async Task restart_persistent_subscriptions_does_not_throw() => - await Fixture.Operations - .RestartPersistentSubscriptions(userCredentials: TestCredentials.Root) - .ShouldNotThrowAsync(); - - [Fact] - public async Task restart_persistent_subscriptions_without_credentials_throws() => - await Fixture.Operations - .RestartPersistentSubscriptions() - .ShouldThrowAsync(); -} \ No newline at end of file diff --git a/test/EventStore.Client.Operations.Tests/ShutdownNodeAuthenticationTests.cs b/test/EventStore.Client.Operations.Tests/ShutdownNodeAuthenticationTests.cs deleted file mode 100644 index 4219f616d..000000000 --- a/test/EventStore.Client.Operations.Tests/ShutdownNodeAuthenticationTests.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace EventStore.Client.Operations.Tests; - -public class ShutdownNodeAuthenticationTests : IClassFixture { - public ShutdownNodeAuthenticationTests(ITestOutputHelper output, InsecureClientTestFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - InsecureClientTestFixture Fixture { get; } - - [Fact] - public async Task shutdown_without_credentials_throws() => - await Fixture.Operations.ShutdownAsync().ShouldThrowAsync(); -} \ No newline at end of file diff --git a/test/EventStore.Client.Operations.Tests/ShutdownNodeTests.cs b/test/EventStore.Client.Operations.Tests/ShutdownNodeTests.cs deleted file mode 100644 index 4c73f52fa..000000000 --- a/test/EventStore.Client.Operations.Tests/ShutdownNodeTests.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace EventStore.Client.Operations.Tests; - -public class ShutdownNodeTests : IClassFixture { - public ShutdownNodeTests(ITestOutputHelper output, InsecureClientTestFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - InsecureClientTestFixture Fixture { get; } - - [Fact] - public async Task shutdown_does_not_throw() => - await Fixture.Operations.ShutdownAsync(userCredentials: TestCredentials.Root).ShouldNotThrowAsync(); -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/AssemblyInfo.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/AssemblyInfo.cs deleted file mode 100644 index b0b47aa73..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/AssemblyInfo.cs +++ /dev/null @@ -1 +0,0 @@ -[assembly: CollectionBehavior(DisableTestParallelization = true)] \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/Bugs/Issue_1125.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/Bugs/Issue_1125.cs deleted file mode 100644 index c94429ca3..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/Bugs/Issue_1125.cs +++ /dev/null @@ -1,84 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.Bugs; - -public class Issue_1125 : IClassFixture { - readonly Fixture _fixture; - - public Issue_1125(Fixture fixture) => _fixture = fixture; - - public static IEnumerable TestCases() => Enumerable.Range(0, 50).Select(i => new object[] { i }); - - [Theory] - [MemberData(nameof(TestCases))] - public async Task persistent_subscription_delivers_all_events(int iteration) { - const int eventCount = 250; - const int totalEvents = eventCount * 2; - - var hitCount = 0; - - var userCredentials = new UserCredentials("admin", "changeit"); - - var streamName = $"stream_{iteration}"; - var subscriptionName = $"subscription_{iteration}"; - - for (var i = 0; i < eventCount; i++) - await _fixture.StreamsClient.AppendToStreamAsync( - streamName, - StreamState.Any, - _fixture.CreateTestEvents() - ); - - await _fixture.Client.CreateToStreamAsync( - streamName, - subscriptionName, - new( - true, - StreamPosition.Start, - readBatchSize: 10, - historyBufferSize: 20 - ), - userCredentials: userCredentials - ); - - await using var subscription = - _fixture.Client.SubscribeToStream(streamName, subscriptionName, userCredentials: userCredentials); - - await Task.WhenAll(Subscribe(), Append()).WithTimeout(); - - Assert.Equal(totalEvents, hitCount); - - return; - - async Task Subscribe() { - await foreach (var message in subscription.Messages) { - if (message is not PersistentSubscriptionMessage.Event(var resolvedEvent, var retryCount)) { - continue; - } - - if (retryCount is 0 or null) { - var result = Interlocked.Increment(ref hitCount); - - await subscription.Ack(resolvedEvent); - - if (totalEvents == result) - return; - } else { - // This is a retry - await subscription.Ack(resolvedEvent); - } - } - } - - async Task Append() { - for (var i = 0; i < eventCount; i++) - await _fixture.StreamsClient.AppendToStreamAsync( - streamName, - StreamState.Any, - _fixture.CreateTestEvents()); - } - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/Diagnostics/PersistentSubscriptionsTracingInstrumentationTests.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/Diagnostics/PersistentSubscriptionsTracingInstrumentationTests.cs deleted file mode 100644 index 904f74f70..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/Diagnostics/PersistentSubscriptionsTracingInstrumentationTests.cs +++ /dev/null @@ -1,155 +0,0 @@ -using EventStore.Diagnostics.Tracing; - -namespace EventStore.Client.PersistentSubscriptions.Tests.Diagnostics; - -[Trait("Category", "Diagnostics:Tracing")] -public class PersistentSubscriptionsTracingInstrumentationTests(ITestOutputHelper output, DiagnosticsFixture fixture) - : EventStoreTests(output, fixture) { - [Fact] - public async Task PersistentSubscriptionIsInstrumentedWithTracingAndRestoresRemoteAppendContextAsExpected() { - var stream = Fixture.GetStreamName(); - var events = Fixture.CreateTestEvents(2, metadata: Fixture.CreateTestJsonMetadata()).ToArray(); - - var groupName = $"{stream}-group"; - await Fixture.Subscriptions.CreateToStreamAsync( - stream, - groupName, - new() - ); - - await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - events - ); - - string? subscriptionId = null; - await Subscribe().WithTimeout(); - - var appendActivity = Fixture - .GetActivitiesForOperation(TracingConstants.Operations.Append, stream) - .SingleOrDefault() - .ShouldNotBeNull(); - - var subscribeActivities = Fixture - .GetActivitiesForOperation(TracingConstants.Operations.Subscribe, stream) - .ToArray(); - - subscriptionId.ShouldNotBeNull(); - subscribeActivities.Length.ShouldBe(events.Length); - - for (var i = 0; i < subscribeActivities.Length; i++) { - subscribeActivities[i].TraceId.ShouldBe(appendActivity.Context.TraceId); - subscribeActivities[i].ParentSpanId.ShouldBe(appendActivity.Context.SpanId); - subscribeActivities[i].HasRemoteParent.ShouldBeTrue(); - - Fixture.AssertSubscriptionActivityHasExpectedTags( - subscribeActivities[i], - stream, - events[i].EventId.ToString(), - subscriptionId - ); - } - - return; - - async Task Subscribe() { - await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, groupName); - await using var enumerator = subscription.Messages.GetAsyncEnumerator(); - - int eventsAppeared = 0; - while (await enumerator.MoveNextAsync()) { - if (enumerator.Current is PersistentSubscriptionMessage.SubscriptionConfirmation(var sid)) - subscriptionId = sid; - - if (enumerator.Current is not PersistentSubscriptionMessage.Event(_, _)) - continue; - - eventsAppeared++; - if (eventsAppeared >= events.Length) - return; - } - } - } - - [Fact] - public async Task PersistentSubscriptionDoesNotThrowWhenInstrumentedWithTracingAndReceivesNonJsonEvents() { - var stream = Fixture.GetStreamName(); - var events = Fixture.CreateTestEvents( - 2, - metadata: Fixture.CreateTestJsonMetadata(), - contentType: Constants.Metadata.ContentTypes.ApplicationOctetStream - ).ToArray(); - - var groupName = $"{stream}-group"; - await Fixture.Subscriptions.CreateToStreamAsync( - stream, - groupName, - new() - ); - - await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - events - ); - - await Subscribe().WithTimeout(); - - return; - - async Task Subscribe() { - await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, groupName); - await using var enumerator = subscription.Messages.GetAsyncEnumerator(); - - var eventsAppeared = 0; - while (await enumerator.MoveNextAsync()) { - if (enumerator.Current is PersistentSubscriptionMessage.Event(_, _)) - eventsAppeared++; - - if (eventsAppeared >= events.Length) - return; - } - } - } - - [Fact] - public async Task PersistentSubscriptionDoesNotThrowWhenInstrumentedWithTracingAndReceivesEventsWithInvalidJsonMetadata() { - var stream = Fixture.GetStreamName(); - var events = Fixture.CreateTestEvents( - 2, - metadata: "clearlynotavalidjsonobject"u8.ToArray() - ).ToArray(); - - var groupName = $"{stream}-group"; - await Fixture.Subscriptions.CreateToStreamAsync( - stream, - groupName, - new() - ); - - await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - events - ); - - await Subscribe().WithTimeout(); - - return; - - async Task Subscribe() { - await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, groupName); - await using var enumerator = subscription.Messages.GetAsyncEnumerator(); - - var eventsAppeared = 0; - while (await enumerator.MoveNextAsync()) { - if (enumerator.Current is PersistentSubscriptionMessage.Event(_, _)) - eventsAppeared++; - - if (eventsAppeared >= events.Length) - return; - } - } - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/EventStore.Client.PersistentSubscriptions.Tests.csproj b/test/EventStore.Client.PersistentSubscriptions.Tests/EventStore.Client.PersistentSubscriptions.Tests.csproj deleted file mode 100644 index 04cf6634b..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/EventStore.Client.PersistentSubscriptions.Tests.csproj +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/EventStore.Client.PersistentSubscriptions.Tests.csproj.DotSettings b/test/EventStore.Client.PersistentSubscriptions.Tests/EventStore.Client.PersistentSubscriptions.Tests.csproj.DotSettings deleted file mode 100644 index a456beab9..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/EventStore.Client.PersistentSubscriptions.Tests.csproj.DotSettings +++ /dev/null @@ -1,4 +0,0 @@ - - False - False - False \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/EventStoreClientFixture.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/EventStoreClientFixture.cs deleted file mode 100644 index babe29328..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/EventStoreClientFixture.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests; - -public abstract class EventStoreClientFixture : EventStoreClientFixtureBase { - readonly bool _skipPsWarmUp; - - protected EventStoreClientFixture(EventStoreClientSettings? settings = null, bool skipPSWarmUp = false, bool noDefaultCredentials = false) - : base(settings, noDefaultCredentials: noDefaultCredentials) { - _skipPsWarmUp = skipPSWarmUp; - - Client = new(Settings); - StreamsClient = new(Settings); - UserManagementClient = new(Settings); - } - - public EventStorePersistentSubscriptionsClient Client { get; } - public EventStoreClient StreamsClient { get; } - public EventStoreUserManagementClient UserManagementClient { get; } - - protected override async Task OnServerUpAsync() { - await StreamsClient.WarmUp(); - await UserManagementClient.WarmUp(); - - if (!_skipPsWarmUp) - await Client.WarmUp(); - - await UserManagementClient.CreateUserWithRetry( - TestCredentials.TestUser1.Username!, - TestCredentials.TestUser1.Username!, - Array.Empty(), - TestCredentials.TestUser1.Password!, - TestCredentials.Root - ); - } - - public override async Task DisposeAsync() { - await UserManagementClient.DisposeAsync(); - await StreamsClient.DisposeAsync(); - await Client.DisposeAsync(); - await base.DisposeAsync(); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/PersistentSubscriptionSettingsTests.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/PersistentSubscriptionSettingsTests.cs deleted file mode 100644 index de32c4160..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/PersistentSubscriptionSettingsTests.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests; - -public class PersistentSubscriptionSettingsTests { - [Fact] - public void LargeCheckpointAfterThrows() => - Assert.Throws(() => new PersistentSubscriptionSettings(checkPointAfter: TimeSpan.FromDays(25 * 365))); - - [Fact] - public void LargeMessageTimeoutThrows() => - Assert.Throws(() => new PersistentSubscriptionSettings(messageTimeout: TimeSpan.FromDays(25 * 365))); -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_max_one_client_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_max_one_client_obsolete.cs deleted file mode 100644 index 3c39e3598..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_max_one_client_obsolete.cs +++ /dev/null @@ -1,43 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_max_one_client_obsolete : IClassFixture { - const string Group = "maxoneclient"; - - readonly Fixture _fixture; - - public connect_to_existing_with_max_one_client_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_second_subscription_fails_to_connect() { - using var first = await _fixture.Client.SubscribeToAllAsync( - Group, - delegate { return Task.CompletedTask; }, - userCredentials: TestCredentials.Root - ).WithTimeout(); - - var ex = await Assert.ThrowsAsync( - async () => { - using var _ = await _fixture.Client.SubscribeToAllAsync( - Group, - delegate { return Task.CompletedTask; }, - userCredentials: TestCredentials.Root - ); - } - ).WithTimeout(); - - Assert.Equal(SystemStreams.AllStream, ex.StreamName); - Assert.Equal(Group, ex.GroupName); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => - Client.CreateToAllAsync( - Group, - new(maxSubscriberCount: 1), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_permissions_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_permissions_obsolete.cs deleted file mode 100644 index 890dacf49..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_permissions_obsolete.cs +++ /dev/null @@ -1,37 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_permissions_obsolete - : IClassFixture { - const string Group = "connectwithpermissions"; - - readonly Fixture _fixture; - - public connect_to_existing_with_permissions_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_succeeds() { - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - using var subscription = await _fixture.Client.SubscribeToAllAsync( - Group, - delegate { return Task.CompletedTask; }, - (s, reason, ex) => dropped.TrySetResult((reason, ex)), - TestCredentials.Root - ).WithTimeout(); - - Assert.NotNull(subscription); - - await Assert.ThrowsAsync(() => dropped.Task.WithTimeout()); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => - Client.CreateToAllAsync( - Group, - new(), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_beginning_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_beginning_obsolete.cs deleted file mode 100644 index 10b06a965..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_beginning_obsolete.cs +++ /dev/null @@ -1,66 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_beginning_obsolete : IClassFixture { - const string Group = "startfrombeginning"; - - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_beginning_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_gets_event_zero_as_its_first_event() { - var resolvedEvent = await _fixture.FirstEvent.WithTimeout(TimeSpan.FromSeconds(10)); - Assert.Equal(_fixture.Events![0].Event.EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - - PersistentSubscription? _subscription; - - public Fixture() => _firstEventSource = new(); - - public ResolvedEvent[]? Events { get; set; } - - public Task FirstEvent => _firstEventSource.Task; - - protected override async Task Given() { - //append 10 events to random streams to make sure we have at least 10 events in the transaction file - foreach (var @event in CreateTestEvents(10)) - await StreamsClient.AppendToStreamAsync(Guid.NewGuid().ToString(), StreamState.NoStream, new[] { @event }); - - Events = await StreamsClient.ReadAllAsync( - Direction.Forwards, - Position.Start, - 10, - userCredentials: TestCredentials.Root - ).ToArrayAsync(); - - await Client.CreateToAllAsync( - Group, - new(startFrom: Position.Start), - userCredentials: TestCredentials.Root - ); - } - - protected override async Task When() => - _subscription = await Client.SubscribeToAllAsync( - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.Root - ); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_not_set_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_not_set_obsolete.cs deleted file mode 100644 index 5446e1eef..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_not_set_obsolete.cs +++ /dev/null @@ -1,64 +0,0 @@ - -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_not_set_obsolete : IClassFixture { - const string Group = "startfromend1"; - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_not_set_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_gets_no_non_system_events() => - await Assert.ThrowsAsync(() => _fixture.FirstNonSystemEvent.WithTimeout()); - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstNonSystemEventSource; - PersistentSubscription? _subscription; - - public Fixture() => _firstNonSystemEventSource = new(); - - public Task FirstNonSystemEvent => _firstNonSystemEventSource.Task; - - protected override async Task Given() { - foreach (var @event in CreateTestEvents(10)) - await StreamsClient.AppendToStreamAsync( - "non-system-stream-" + Guid.NewGuid(), - StreamState.Any, - new[] { - @event - } - ); - - await Client.CreateToAllAsync( - Group, - new(), - userCredentials: TestCredentials.Root - ); - } - - protected override async Task When() => - _subscription = await Client.SubscribeToAllAsync( - Group, - async (subscription, e, r, ct) => { - if (SystemStreams.IsSystemStream(e.OriginalStreamId)) { - await subscription.Ack(e); - return; - } - - _firstNonSystemEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstNonSystemEventSource.TrySetException(ex!); - }, - TestCredentials.Root - ); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_not_set_then_event_written_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_not_set_then_event_written_obsolete.cs deleted file mode 100644 index 1ee2b6fae..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_not_set_then_event_written_obsolete.cs +++ /dev/null @@ -1,72 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_not_set_then_event_written_obsolete - : IClassFixture { - const string Group = "startfromnotset2"; - - readonly Fixture _fixture; - - public - connect_to_existing_with_start_from_not_set_then_event_written_obsolete(Fixture fixture) => - _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_non_system_event2() { - var resolvedEvent = await _fixture.FirstNonSystemEvent.WithTimeout(); - Assert.Equal(_fixture.ExpectedEvent!.EventId, resolvedEvent.Event.EventId); - Assert.Equal(_fixture.ExpectedStreamId, resolvedEvent.Event.EventStreamId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstNonSystemEventSource; - - public readonly EventData? ExpectedEvent; - public readonly string ExpectedStreamId; - - PersistentSubscription? _subscription; - - public Fixture() { - _firstNonSystemEventSource = new(); - ExpectedEvent = CreateTestEvents(1).First(); - ExpectedStreamId = Guid.NewGuid().ToString(); - } - - public Task FirstNonSystemEvent => _firstNonSystemEventSource.Task; - - protected override async Task Given() { - foreach (var @event in CreateTestEvents(10)) - await StreamsClient.AppendToStreamAsync( - "non-system-stream-" + Guid.NewGuid(), - StreamState.Any, - new[] { @event } - ); - - await Client.CreateToAllAsync(Group, new(), userCredentials: TestCredentials.Root); - _subscription = await Client.SubscribeToAllAsync( - Group, - async (subscription, e, r, ct) => { - if (SystemStreams.IsSystemStream(e.OriginalStreamId)) { - await subscription.Ack(e); - return; - } - - _firstNonSystemEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstNonSystemEventSource.TrySetException(ex!); - }, - TestCredentials.Root - ); - } - - protected override async Task When() => await StreamsClient.AppendToStreamAsync(ExpectedStreamId, StreamState.NoStream, new[] { ExpectedEvent! }); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_end_position_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_end_position_obsolete.cs deleted file mode 100644 index 7057b1489..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_end_position_obsolete.cs +++ /dev/null @@ -1,63 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_set_to_end_position_obsolete: IClassFixture { - const string Group = "startfromend1"; - - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_set_to_end_position_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_gets_no_non_system_events() => - await Assert.ThrowsAsync(() => _fixture.FirstNonSystemEvent.WithTimeout()); - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstNonSystemEventSource; - - PersistentSubscription? _subscription; - - public Fixture() => _firstNonSystemEventSource = new(); - - public Task FirstNonSystemEvent => _firstNonSystemEventSource.Task; - - protected override async Task Given() { - foreach (var @event in CreateTestEvents(10)) - await StreamsClient.AppendToStreamAsync( - "non-system-stream-" + Guid.NewGuid(), - StreamState.Any, - new[] { @event } - ); - - await Client.CreateToAllAsync( - Group, - new(startFrom: Position.End), - userCredentials: TestCredentials.Root - ); - } - - protected override async Task When() => - _subscription = await Client.SubscribeToAllAsync( - Group, - async (subscription, e, r, ct) => { - if (SystemStreams.IsSystemStream(e.OriginalStreamId)) { - await subscription.Ack(e); - return; - } - - _firstNonSystemEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstNonSystemEventSource.TrySetException(ex!); - }, - TestCredentials.Root - ); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_end_position_then_event_written_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_end_position_then_event_written_obsolete.cs deleted file mode 100644 index 7083cb78f..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_end_position_then_event_written_obsolete.cs +++ /dev/null @@ -1,69 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class - connect_to_existing_with_start_from_set_to_end_position_then_event_written_obsolete - : IClassFixture { - const string Group = "startfromnotset2"; - - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_set_to_end_position_then_event_written_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_non_system_event() { - var resolvedEvent = await _fixture.FirstNonSystemEvent.WithTimeout(); - Assert.Equal(_fixture.ExpectedEvent.EventId, resolvedEvent.Event.EventId); - Assert.Equal(_fixture.ExpectedStreamId, resolvedEvent.Event.EventStreamId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstNonSystemEventSource; - public readonly EventData ExpectedEvent; - public readonly string ExpectedStreamId; - PersistentSubscription? _subscription; - - public Fixture() { - _firstNonSystemEventSource = new(); - ExpectedEvent = CreateTestEvents(1).First(); - ExpectedStreamId = Guid.NewGuid().ToString(); - } - - public Task FirstNonSystemEvent => _firstNonSystemEventSource.Task; - - protected override async Task Given() { - foreach (var @event in CreateTestEvents(10)) - await StreamsClient.AppendToStreamAsync( - "non-system-stream-" + Guid.NewGuid(), - StreamState.Any, - new[] { @event } - ); - - await Client.CreateToAllAsync(Group, new(startFrom: Position.End), userCredentials: TestCredentials.Root); - _subscription = await Client.SubscribeToAllAsync( - Group, - async (subscription, e, r, ct) => { - if (SystemStreams.IsSystemStream(e.OriginalStreamId)) { - await subscription.Ack(e); - return; - } - - _firstNonSystemEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstNonSystemEventSource.TrySetException(ex!); - }, - TestCredentials.Root - ); - } - - protected override async Task When() => await StreamsClient.AppendToStreamAsync(ExpectedStreamId, StreamState.NoStream, new[] { ExpectedEvent }); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_invalid_middle_position_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_invalid_middle_position_obsolete.cs deleted file mode 100644 index f1d317b76..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_invalid_middle_position_obsolete.cs +++ /dev/null @@ -1,49 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_set_to_invalid_middle_position_obsolete - : IClassFixture { - const string Group = "startfrominvalid1"; - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_set_to_invalid_middle_position_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_is_dropped() { - var (reason, exception) = await _fixture.Dropped.WithTimeout(); - Assert.Equal(SubscriptionDroppedReason.ServerError, reason); - Assert.IsType(exception); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource<(SubscriptionDroppedReason, Exception?)> _dropped; - - PersistentSubscription? _subscription; - - public Fixture() => _dropped = new(); - - public Task<(SubscriptionDroppedReason, Exception?)> Dropped => _dropped.Task; - - protected override async Task Given() { - var invalidPosition = new Position(1L, 1L); - await Client.CreateToAllAsync( - Group, - new(startFrom: invalidPosition), - userCredentials: TestCredentials.Root - ); - } - - protected override async Task When() => - _subscription = await Client.SubscribeToAllAsync( - Group, - async (subscription, e, r, ct) => await subscription.Ack(e), - (subscription, reason, ex) => { _dropped.TrySetResult((reason, ex)); }, - TestCredentials.Root - ); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_valid_middle_position_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_valid_middle_position_obsolete.cs deleted file mode 100644 index 69230d695..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_with_start_from_set_to_valid_middle_position_obsolete.cs +++ /dev/null @@ -1,65 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_set_to_valid_middle_position_obsolete - : IClassFixture { - const string Group = "startfromvalid"; - - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_set_to_valid_middle_position_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_gets_the_event_at_the_specified_start_position_as_its_first_event() { - var resolvedEvent = await _fixture.FirstEvent.WithTimeout(); - Assert.Equal(_fixture.ExpectedEvent.OriginalPosition, resolvedEvent.Event.Position); - Assert.Equal(_fixture.ExpectedEvent.Event.EventId, resolvedEvent.Event.EventId); - Assert.Equal(_fixture.ExpectedEvent.Event.EventStreamId, resolvedEvent.Event.EventStreamId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - PersistentSubscription? _subscription; - - public Fixture() => _firstEventSource = new(); - - public Task FirstEvent => _firstEventSource.Task; - public ResolvedEvent ExpectedEvent { get; private set; } - - protected override async Task Given() { - var events = await StreamsClient.ReadAllAsync( - Direction.Forwards, - Position.Start, - 10, - userCredentials: TestCredentials.Root - ).ToArrayAsync(); - - ExpectedEvent = events[events.Length / 2]; //just a random event in the middle of the results - - await Client.CreateToAllAsync( - Group, - new(startFrom: ExpectedEvent.OriginalPosition), - userCredentials: TestCredentials.Root - ); - } - - protected override async Task When() => - _subscription = await Client.SubscribeToAllAsync( - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.Root - ); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_without_permissions_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_without_permissions_obsolete.cs deleted file mode 100644 index b09dbc46a..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_without_permissions_obsolete.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_without_permissions_obsolete - : IClassFixture { - readonly Fixture _fixture; - public connect_to_existing_without_permissions_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public Task throws_access_denied() => - Assert.ThrowsAsync( - async () => { - using var _ = await _fixture.Client.SubscribeToAllAsync( - "agroupname55", - delegate { return Task.CompletedTask; } - ); - } - ).WithTimeout(); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => - Client.CreateToAllAsync( - "agroupname55", - new(), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_without_read_all_permissions_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_without_read_all_permissions_obsolete.cs deleted file mode 100644 index da6f19f72..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_existing_without_read_all_permissions_obsolete.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_without_read_all_permissions_obsolete - : IClassFixture { - readonly Fixture _fixture; - public connect_to_existing_without_read_all_permissions_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public Task throws_access_denied() => - Assert.ThrowsAsync( - async () => { - using var _ = await _fixture.Client.SubscribeToAllAsync( - "agroupname55", - delegate { return Task.CompletedTask; }, - userCredentials: TestCredentials.TestUser1 - ); - } - ).WithTimeout(); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => - Client.CreateToAllAsync( - "agroupname55", - new(), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_non_existing_with_permissions_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_non_existing_with_permissions_obsolete.cs deleted file mode 100644 index 5f8c885c1..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_to_non_existing_with_permissions_obsolete.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_non_existing_with_permissions_obsolete - : IClassFixture { - const string Group = "foo"; - - readonly Fixture _fixture; - - public connect_to_non_existing_with_permissions_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task throws_persistent_subscription_not_found() { - var ex = await Assert.ThrowsAsync( - async () => { - using var _ = await _fixture.Client.SubscribeToAllAsync( - Group, - delegate { return Task.CompletedTask; }, - userCredentials: TestCredentials.Root - ); - } - ).WithTimeout(); - - Assert.Equal(SystemStreams.AllStream, ex.StreamName); - Assert.Equal(Group, ex.GroupName); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_with_retries_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_with_retries_obsolete.cs deleted file mode 100644 index 085eecc3e..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/connect_with_retries_obsolete.cs +++ /dev/null @@ -1,59 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_with_retries_obsolete - : IClassFixture { - const string Group = "retries"; - readonly Fixture _fixture; - - public connect_with_retries_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task events_are_retried_until_success() => Assert.Equal(5, await _fixture.RetryCount.WithTimeout()); - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _retryCountSource; - PersistentSubscription? _subscription; - - public Fixture() => _retryCountSource = new(); - - public Task RetryCount => _retryCountSource.Task; - - protected override async Task Given() { - await Client.CreateToAllAsync( - Group, - new(startFrom: Position.Start), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToAllAsync( - Group, - async (subscription, e, r, ct) => { - if (r > 4) { - _retryCountSource.TrySetResult(r.Value); - await subscription.Ack(e.Event.EventId); - } - else { - await subscription.Nack( - PersistentSubscriptionNakEventAction.Retry, - "Not yet tried enough times", - e - ); - } - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _retryCountSource.TrySetException(ex!); - }, - TestCredentials.Root - ); - } - - protected override Task When() => Task.CompletedTask; - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/deleting_existing_with_subscriber_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/deleting_existing_with_subscriber_obsolete.cs deleted file mode 100644 index fdca510d5..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/deleting_existing_with_subscriber_obsolete.cs +++ /dev/null @@ -1,66 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class deleting_existing_with_subscriber_obsolete - : IClassFixture { - readonly Fixture _fixture; - - public deleting_existing_with_subscriber_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_is_dropped() { - var (reason, exception) = await _fixture.Dropped.WithTimeout(); - Assert.Equal(SubscriptionDroppedReason.ServerError, reason); - var ex = Assert.IsType(exception); - - Assert.Equal(SystemStreams.AllStream, ex.StreamName); - Assert.Equal("groupname123", ex.GroupName); - } - - [Fact(Skip = "Isn't this how it should work?")] - public async Task the_subscription_is_dropped_with_not_found() { - var (reason, exception) = await _fixture.Dropped.WithTimeout(); - Assert.Equal(SubscriptionDroppedReason.ServerError, reason); - var ex = Assert.IsType(exception); - Assert.Equal(SystemStreams.AllStream, ex.StreamName); - Assert.Equal("groupname123", ex.GroupName); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource<(SubscriptionDroppedReason, Exception?)> _dropped; - PersistentSubscription? _subscription; - - public Fixture() => _dropped = new(); - - public Task<(SubscriptionDroppedReason, Exception?)> Dropped => _dropped.Task; - - protected override async Task Given() { - await Client.CreateToAllAsync( - "groupname123", - new(), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToAllAsync( - "groupname123", - async (s, e, i, ct) => await s.Ack(e), - (s, r, e) => _dropped.TrySetResult((r, e)), - TestCredentials.Root - ); - - // todo: investigate why this test is flaky without this delay - await Task.Delay(500); - } - - protected override Task When() => - Client.DeleteToAllAsync( - "groupname123", - userCredentials: TestCredentials.Root - ); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_catching_up_to_link_to_events_manual_ack_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_catching_up_to_link_to_events_manual_ack_obsolete.cs deleted file mode 100644 index cfccd2de2..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_catching_up_to_link_to_events_manual_ack_obsolete.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System.Text; - -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class happy_case_catching_up_to_link_to_events_manual_ack_obsolete - : IClassFixture { - const string Group = nameof(Group); - const int BufferCount = 10; - const int EventWriteCount = BufferCount * 2; - - readonly Fixture _fixture; - - public happy_case_catching_up_to_link_to_events_manual_ack_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task Test() => await _fixture.EventsReceived.WithTimeout(); - - public class Fixture : EventStoreClientFixture { - readonly EventData[] _events; - readonly TaskCompletionSource _eventsReceived; - int _eventReceivedCount; - - PersistentSubscription? _subscription; - - public Fixture() { - _events = CreateTestEvents(EventWriteCount) - .Select( - (e, i) => new EventData( - e.EventId, - SystemEventTypes.LinkTo, - Encoding.UTF8.GetBytes($"{i}@test"), - contentType: Constants.Metadata.ContentTypes.ApplicationOctetStream - ) - ) - .ToArray(); - - _eventsReceived = new(); - } - - public Task EventsReceived => _eventsReceived.Task; - - protected override async Task Given() { - foreach (var e in _events) - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); - - await Client.CreateToAllAsync( - Group, - new(startFrom: Position.Start, resolveLinkTos: true), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToAllAsync( - Group, - async (subscription, e, retryCount, ct) => { - await subscription.Ack(e); - - if (e.OriginalStreamId.StartsWith("test-") - && Interlocked.Increment(ref _eventReceivedCount) == _events.Length) - _eventsReceived.TrySetResult(true); - }, - (s, r, e) => { - if (e != null) - _eventsReceived.TrySetException(e); - }, - bufferSize: BufferCount, - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() => Task.CompletedTask; - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_catching_up_to_normal_events_manual_ack_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_catching_up_to_normal_events_manual_ack_obsolete.cs deleted file mode 100644 index cd1f69ee4..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_catching_up_to_normal_events_manual_ack_obsolete.cs +++ /dev/null @@ -1,65 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class happy_case_catching_up_to_normal_events_manual_ack_obsolete : IClassFixture { - const string Group = nameof(Group); - const int BufferCount = 10; - const int EventWriteCount = BufferCount * 2; - - readonly Fixture _fixture; - - public happy_case_catching_up_to_normal_events_manual_ack_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task Test() => await _fixture.EventsReceived.WithTimeout(); - - public class Fixture : EventStoreClientFixture { - readonly EventData[] _events; - readonly TaskCompletionSource _eventsReceived; - int _eventReceivedCount; - - PersistentSubscription? _subscription; - - public Fixture() { - _events = CreateTestEvents(EventWriteCount).ToArray(); - _eventsReceived = new(); - } - - public Task EventsReceived => _eventsReceived.Task; - - protected override async Task Given() { - foreach (var e in _events) - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); - - await Client.CreateToAllAsync( - Group, - new(startFrom: Position.Start, resolveLinkTos: true), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToAllAsync( - Group, - async (subscription, e, retryCount, ct) => { - await subscription.Ack(e); - - if (e.OriginalStreamId.StartsWith("test-") - && Interlocked.Increment(ref _eventReceivedCount) == _events.Length) - _eventsReceived.TrySetResult(true); - }, - (s, r, e) => { - if (e != null) - _eventsReceived.TrySetException(e); - }, - bufferSize: BufferCount, - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() => Task.CompletedTask; - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_filtered_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_filtered_obsolete.cs deleted file mode 100644 index f9169733b..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_filtered_obsolete.cs +++ /dev/null @@ -1,72 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class happy_case_filtered_obsolete : IClassFixture { - readonly Fixture _fixture; - - public happy_case_filtered_obsolete(Fixture fixture) => _fixture = fixture; - - public static IEnumerable FilterCases() => Filters.All.Select(filter => new object[] { filter }); - - [SupportsPSToAll.Theory] - [MemberData(nameof(FilterCases))] - public async Task reads_all_existing_filtered_events(string filterName) { - var streamPrefix = $"{filterName}-{_fixture.GetStreamName()}"; - var (getFilter, prepareEvent) = Filters.GetFilter(filterName); - var filter = getFilter(streamPrefix); - - var appeared = new TaskCompletionSource(); - var appearedEvents = new List(); - var events = _fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)).ToArray(); - - foreach (var e in events) - await _fixture.StreamsClient.AppendToStreamAsync( - $"{streamPrefix}_{Guid.NewGuid():n}", - StreamState.NoStream, - new[] { e } - ); - - await _fixture.Client.CreateToAllAsync( - filterName, - filter, - new(startFrom: Position.Start), - userCredentials: TestCredentials.Root - ); - - using var subscription = await _fixture.Client.SubscribeToAllAsync( - filterName, - async (s, e, r, ct) => { - appearedEvents.Add(e.Event); - if (appearedEvents.Count >= events.Length) - appeared.TrySetResult(true); - - await s.Ack(e); - }, - userCredentials: TestCredentials.Root - ) - .WithTimeout(); - - await Task.WhenAll(appeared.Task).WithTimeout(); - - Assert.Equal(events.Select(x => x.EventId), appearedEvents.Select(x => x.EventId)); - } - - public class Fixture : EventStoreClientFixture { - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync( - Guid.NewGuid().ToString(), - StreamState.NoStream, - CreateTestEvents(256) - ); - - await StreamsClient.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.Any, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_filtered_with_start_from_set_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_filtered_with_start_from_set_obsolete.cs deleted file mode 100644 index 111ca4e19..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_filtered_with_start_from_set_obsolete.cs +++ /dev/null @@ -1,86 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class happy_case_filtered_with_start_from_set_obsolete : IClassFixture { - readonly Fixture _fixture; - - public happy_case_filtered_with_start_from_set_obsolete(Fixture fixture) => _fixture = fixture; - - public static IEnumerable FilterCases() => Filters.All.Select(filter => new object[] { filter }); - - [SupportsPSToAll.Theory] - [MemberData(nameof(FilterCases))] - public async Task reads_all_existing_filtered_events_from_specified_start(string filterName) { - var streamPrefix = $"{filterName}-{_fixture.GetStreamName()}"; - var (getFilter, prepareEvent) = Filters.GetFilter(filterName); - var filter = getFilter(streamPrefix); - - var appeared = new TaskCompletionSource(); - var appearedEvents = new List(); - var events = _fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)).ToArray(); - var eventsToSkip = events.Take(10).ToArray(); - var eventsToCapture = events.Skip(10).ToArray(); - - IWriteResult? eventToCaptureResult = null; - - foreach (var e in eventsToSkip) - await _fixture.StreamsClient.AppendToStreamAsync( - $"{streamPrefix}_{Guid.NewGuid():n}", - StreamState.NoStream, - new[] { e } - ); - - foreach (var e in eventsToCapture) { - var result = await _fixture.StreamsClient.AppendToStreamAsync( - $"{streamPrefix}_{Guid.NewGuid():n}", - StreamState.NoStream, - new[] { e } - ); - - eventToCaptureResult ??= result; - } - - await _fixture.Client.CreateToAllAsync( - filterName, - filter, - new(startFrom: eventToCaptureResult!.LogPosition), - userCredentials: TestCredentials.Root - ); - - using var subscription = await _fixture.Client.SubscribeToAllAsync( - filterName, - async (s, e, r, ct) => { - appearedEvents.Add(e.Event); - if (appearedEvents.Count >= eventsToCapture.Length) - appeared.TrySetResult(true); - - await s.Ack(e); - }, - userCredentials: TestCredentials.Root - ) - .WithTimeout(); - - await Task.WhenAll(appeared.Task).WithTimeout(); - - Assert.Equal(eventsToCapture.Select(x => x.EventId), appearedEvents.Select(x => x.EventId)); - } - - public class Fixture : EventStoreClientFixture { - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync( - Guid.NewGuid().ToString(), - StreamState.NoStream, - CreateTestEvents(256) - ); - - await StreamsClient.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.Any, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_writing_and_subscribing_to_normal_events_manual_ack_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_writing_and_subscribing_to_normal_events_manual_ack_obsolete.cs deleted file mode 100644 index 2563c488d..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/happy_case_writing_and_subscribing_to_normal_events_manual_ack_obsolete.cs +++ /dev/null @@ -1,65 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class happy_case_writing_and_subscribing_to_normal_events_manual_ack_obsolete - : IClassFixture { - const string Group = nameof(Group); - const int BufferCount = 10; - const int EventWriteCount = BufferCount * 2; - - readonly Fixture _fixture; - - public happy_case_writing_and_subscribing_to_normal_events_manual_ack_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task Test() => await _fixture.EventsReceived.WithTimeout(); - - public class Fixture : EventStoreClientFixture { - readonly EventData[] _events; - readonly TaskCompletionSource _eventsReceived; - int _eventReceivedCount; - - PersistentSubscription? _subscription; - - public Fixture() { - _events = CreateTestEvents(EventWriteCount).ToArray(); - _eventsReceived = new(); - } - - public Task EventsReceived => _eventsReceived.Task; - - protected override async Task Given() { - await Client.CreateToAllAsync( - Group, - new(startFrom: Position.End, resolveLinkTos: true), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToAllAsync( - Group, - async (subscription, e, retryCount, ct) => { - await subscription.Ack(e); - if (e.OriginalStreamId.StartsWith("test-") - && Interlocked.Increment(ref _eventReceivedCount) == _events.Length) - _eventsReceived.TrySetResult(true); - }, - (s, r, e) => { - if (e != null) - _eventsReceived.TrySetException(e); - }, - bufferSize: BufferCount, - userCredentials: TestCredentials.Root - ); - } - - protected override async Task When() { - foreach (var e in _events) - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); - } - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/update_existing_with_check_point_filtered_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/update_existing_with_check_point_filtered_obsolete.cs deleted file mode 100644 index 0e9e2be21..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/update_existing_with_check_point_filtered_obsolete.cs +++ /dev/null @@ -1,120 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class update_existing_with_check_point_filtered_obsolete - : IClassFixture { - const string Group = "existing-with-check-point-filtered"; - - readonly Fixture _fixture; - - public update_existing_with_check_point_filtered_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task resumes_from_check_point() { - var resumedEvent = await _fixture.Resumed.WithTimeout(TimeSpan.FromSeconds(10)); - Assert.True(resumedEvent.Event.Position > _fixture.CheckPoint); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _appeared; - readonly List _appearedEvents; - readonly TaskCompletionSource<(SubscriptionDroppedReason, Exception?)> _droppedSource; - readonly EventData[] _events; - readonly TaskCompletionSource _resumedSource; - - PersistentSubscription? _firstSubscription; - PersistentSubscription? _secondSubscription; - - public Fixture() { - _droppedSource = new(); - _resumedSource = new(); - _appeared = new(); - _appearedEvents = new(); - _events = CreateTestEvents(5).ToArray(); - } - - public Task Resumed => _resumedSource.Task; - - public Position CheckPoint { get; private set; } - - protected override async Task Given() { - foreach (var e in _events) - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.NoStream, new[] { e }); - - await Client.CreateToAllAsync( - Group, - StreamFilter.Prefix("test"), - new( - checkPointLowerBound: 5, - checkPointAfter: TimeSpan.FromSeconds(1), - startFrom: Position.Start - ), - userCredentials: TestCredentials.Root - ); - - _firstSubscription = await Client.SubscribeToAllAsync( - Group, - async (s, e, r, ct) => { - _appearedEvents.Add(e); - - if (_appearedEvents.Count == _events.Length) - _appeared.TrySetResult(true); - - await s.Ack(e); - }, - (subscription, reason, ex) => _droppedSource.TrySetResult((reason, ex)), - TestCredentials.Root - ); - - await Task.WhenAll(_appeared.Task, Checkpointed()).WithTimeout(); - - return; - - async Task Checkpointed() { - await using var subscription = StreamsClient.SubscribeToStream( - $"$persistentsubscription-$all::{Group}-checkpoint", - FromStream.Start, - userCredentials: TestCredentials.Root); - await foreach (var message in subscription.Messages) { - if (message is not StreamMessage.Event(var resolvedEvent)) { - continue; - } - CheckPoint = resolvedEvent.Event.Data.ParsePosition(); - return; - } - } - } - - protected override async Task When() { - // Force restart of the subscription - await Client.UpdateToAllAsync(Group, new(), userCredentials: TestCredentials.Root); - - await _droppedSource.Task.WithTimeout(); - - _secondSubscription = await Client.SubscribeToAllAsync( - Group, - async (s, e, r, ct) => { - _resumedSource.TrySetResult(e); - await s.Ack(e); - s.Dispose(); - }, - (_, reason, ex) => { - if (ex is not null) - _resumedSource.TrySetException(ex); - else - _resumedSource.TrySetResult(default); - }, - TestCredentials.Root - ); - - foreach (var e in _events) - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.NoStream, new[] { e }); - } - - public override Task DisposeAsync() { - _firstSubscription?.Dispose(); - _secondSubscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/update_existing_with_subscribers_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/update_existing_with_subscribers_obsolete.cs deleted file mode 100644 index 17a77063c..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/update_existing_with_subscribers_obsolete.cs +++ /dev/null @@ -1,60 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class update_existing_with_subscribers_obsolete - : IClassFixture { - const string Group = "existing"; - - readonly Fixture _fixture; - - public update_existing_with_subscribers_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task existing_subscriptions_are_dropped() { - var (reason, exception) = await _fixture.Dropped.WithTimeout(TimeSpan.FromSeconds(10)); - Assert.Equal(SubscriptionDroppedReason.ServerError, reason); - var ex = Assert.IsType(exception); - - Assert.Equal(SystemStreams.AllStream, ex.StreamName); - Assert.Equal(Group, ex.GroupName); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource<(SubscriptionDroppedReason, Exception?)> _droppedSource; - PersistentSubscription? _subscription; - - public Fixture() => _droppedSource = new(); - - public Task<(SubscriptionDroppedReason, Exception?)> Dropped => _droppedSource.Task; - - protected override async Task Given() { - await Client.CreateToAllAsync( - Group, - new(), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToAllAsync( - Group, - delegate { return Task.CompletedTask; }, - (subscription, reason, ex) => _droppedSource.TrySetResult((reason, ex)), - TestCredentials.Root - ); - - // todo: investigate why this test is flaky without this delay - await Task.Delay(500); - } - - protected override Task When() => - Client.UpdateToAllAsync( - Group, - new(), - userCredentials: TestCredentials.Root - ); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/when_writing_and_filtering_out_events_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/when_writing_and_filtering_out_events_obsolete.cs deleted file mode 100644 index 302ac221a..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/when_writing_and_filtering_out_events_obsolete.cs +++ /dev/null @@ -1,108 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class when_writing_and_filtering_out_events_obsolete - : IClassFixture { - const string Group = "filtering-out-events"; - - readonly Fixture _fixture; - - public when_writing_and_filtering_out_events_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task it_should_write_a_check_point() { - await Task.Yield(); - Assert.True(_fixture.SecondCheckPoint > _fixture.FirstCheckPoint); - Assert.Equal( - _fixture.Events.Select(e => e.EventId), - _fixture.AppearedEvents.Select(e => e.Event.EventId) - ); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _appeared; - readonly List _appearedEvents, _checkPoints; - readonly EventData[] _events; - - PersistentSubscription? _subscription; - - public Fixture() { - _appeared = new(); - _appearedEvents = new(); - _checkPoints = new(); - _events = CreateTestEvents(10).ToArray(); - } - - public Position SecondCheckPoint { get; private set; } - public Position FirstCheckPoint { get; private set; } - public EventData[] Events => _events.ToArray(); - public ResolvedEvent[] AppearedEvents => _appearedEvents.ToArray(); - - protected override async Task Given() { - foreach (var e in _events) - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); - - await Client.CreateToAllAsync( - Group, - StreamFilter.Prefix("test"), - new( - checkPointLowerBound: 1, - checkPointUpperBound: 5, - checkPointAfter: TimeSpan.FromSeconds(1), - startFrom: Position.Start - ), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToAllAsync( - Group, - async (s, e, r, ct) => { - _appearedEvents.Add(e); - - if (_appearedEvents.Count == _events.Length) - _appeared.TrySetResult(true); - - await s.Ack(e); - }, - userCredentials: TestCredentials.Root - ); - - await Task.WhenAll(_appeared.Task, Checkpointed()).WithTimeout(); - - async Task Checkpointed() { - bool firstCheckpointSet = false; - await using var subscription = StreamsClient.SubscribeToStream( - $"$persistentsubscription-$all::{Group}-checkpoint", - FromStream.Start, - userCredentials: TestCredentials.Root); - await foreach (var message in subscription.Messages) { - if (message is not StreamMessage.Event(var resolvedEvent)) { - continue; - } - - if (!firstCheckpointSet) { - FirstCheckPoint = resolvedEvent.Event.Data.ParsePosition(); - firstCheckpointSet = true; - } else { - SecondCheckPoint = resolvedEvent.Event.Data.ParsePosition(); - return; - } - } - } - } - - protected override async Task When() { - foreach (var e in _events) - await StreamsClient.AppendToStreamAsync( - "filtered-out-stream-" + Guid.NewGuid(), - StreamState.Any, - new[] { e } - ); - } - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/when_writing_and_subscribing_to_normal_events_manual_nack_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/when_writing_and_subscribing_to_normal_events_manual_nack_obsolete.cs deleted file mode 100644 index f18d6ad96..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/when_writing_and_subscribing_to_normal_events_manual_nack_obsolete.cs +++ /dev/null @@ -1,68 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class when_writing_and_subscribing_to_normal_events_manual_nack_obsolete - : IClassFixture { - const string Group = nameof(Group); - const int BufferCount = 10; - const int EventWriteCount = BufferCount * 2; - - readonly Fixture _fixture; - - public when_writing_and_subscribing_to_normal_events_manual_nack_obsolete(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task Test() => await _fixture.EventsReceived.WithTimeout(); - - public class Fixture : EventStoreClientFixture { - readonly EventData[] _events; - readonly TaskCompletionSource _eventsReceived; - int _eventReceivedCount; - - PersistentSubscription? _subscription; - - public Fixture() { - _events = CreateTestEvents(EventWriteCount) - .ToArray(); - - _eventsReceived = new(); - } - - public Task EventsReceived => _eventsReceived.Task; - - protected override async Task Given() { - await Client.CreateToAllAsync( - Group, - new(startFrom: Position.Start, resolveLinkTos: true), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToAllAsync( - Group, - async (subscription, e, retryCount, ct) => { - await subscription.Nack(PersistentSubscriptionNakEventAction.Park, "fail", e); - - if (e.OriginalStreamId.StartsWith("test-") - && Interlocked.Increment(ref _eventReceivedCount) == _events.Length) - _eventsReceived.TrySetResult(true); - }, - (s, r, e) => { - if (e != null) - _eventsReceived.TrySetException(e); - }, - bufferSize: BufferCount, - userCredentials: TestCredentials.Root - ); - } - - protected override async Task When() { - foreach (var e in _events) - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); - } - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/can_create_duplicate_name_on_different_streams.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/can_create_duplicate_name_on_different_streams.cs deleted file mode 100644 index d23e7c911..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/can_create_duplicate_name_on_different_streams.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class can_create_duplicate_name_on_different_streams : IClassFixture { - readonly Fixture _fixture; - - public can_create_duplicate_name_on_different_streams(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public Task the_completion_succeeds() => - _fixture.Client.CreateToStreamAsync("someother", "group3211", new(), userCredentials: TestCredentials.Root); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - - protected override Task When() => - Client.CreateToAllAsync( - "group3211", - new(), - userCredentials: TestCredentials.Root - ); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_max_one_client.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_max_one_client.cs deleted file mode 100644 index db2818abf..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_max_one_client.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class connect_to_existing_with_max_one_client : IClassFixture { - private const string Group = "maxoneclient"; - - private readonly Fixture _fixture; - - public connect_to_existing_with_max_one_client(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_second_subscription_fails_to_connect2() { - var ex = await Assert.ThrowsAsync( - () => Task.WhenAll(Subscribe().WithTimeout(), Subscribe().WithTimeout())); - - Assert.Equal(SystemStreams.AllStream, ex.StreamName); - Assert.Equal(Group, ex.GroupName); - return; - - async Task Subscribe() { - await using var subscription = _fixture.Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - await subscription.Messages.AnyAsync(); - } - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => - Client.CreateToAllAsync(Group, new(maxSubscriberCount: 1), userCredentials: TestCredentials.Root); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_permissions.cs deleted file mode 100644 index e10ed9909..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_permissions.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class connect_to_existing_with_permissions : IClassFixture { - private const string Group = "connectwithpermissions"; - private readonly Fixture _fixture; - - public connect_to_existing_with_permissions(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_succeeds() { - await using var subscription = - _fixture.Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - - Assert.True(await subscription.Messages - .FirstAsync().AsTask().WithTimeout() is PersistentSubscriptionMessage.SubscriptionConfirmation); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Client.CreateToAllAsync(Group, new(), userCredentials: TestCredentials.Root); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_beginning.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_beginning.cs deleted file mode 100644 index 47e36c620..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_beginning.cs +++ /dev/null @@ -1,52 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class connect_to_existing_with_start_from_beginning - : IClassFixture { - private const string Group = "startfrombeginning"; - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_beginning(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_gets_event_zero_as_its_first_event() { - var resolvedEvent = await _fixture.Subscription!.Messages.OfType() - .Select(e => e.ResolvedEvent) - .FirstOrDefaultAsync().AsTask().WithTimeout(); - - Assert.Equal(_fixture.Events[0].Event.EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public ResolvedEvent[] Events { get; private set; } = Array.Empty(); - - protected override async Task Given() { - //append 10 events to random streams to make sure we have at least 10 events in the transaction file - foreach (var @event in CreateTestEvents(10)) { - await StreamsClient.AppendToStreamAsync(Guid.NewGuid().ToString(), StreamState.NoStream, - new[] { @event }); - } - - Events = await StreamsClient - .ReadAllAsync(Direction.Forwards, Position.Start, 10, userCredentials: TestCredentials.Root) - .ToArrayAsync(); - - await Client.CreateToAllAsync(Group, new(startFrom: Position.Start), userCredentials: TestCredentials.Root); - } - - protected override Task When() { - Subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - - return Task.CompletedTask; - } - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_not_set.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_not_set.cs deleted file mode 100644 index 17a28d1d6..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_not_set.cs +++ /dev/null @@ -1,44 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class connect_to_existing_with_start_from_not_set - : IClassFixture { - private const string Group = "startfromend1"; - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_not_set(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_gets_no_non_system_events() { - await Assert.ThrowsAsync(() => _fixture.Subscription!.Messages - .OfType() - .Where(e => !SystemStreams.IsSystemStream(e.ResolvedEvent.OriginalStreamId)) - .AnyAsync() - .AsTask() - .WithTimeout(TimeSpan.FromMilliseconds(250))); - } - - public class Fixture : EventStoreClientFixture { - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - protected override async Task Given() { - foreach (var @event in CreateTestEvents(10)) - await StreamsClient.AppendToStreamAsync("non-system-stream-" + Guid.NewGuid(), StreamState.Any, - new[] { @event }); - - await Client.CreateToAllAsync(Group, new(), userCredentials: TestCredentials.Root); - } - - protected override Task When() { - Subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - return Task.CompletedTask; - } - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_not_set_then_event_written.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_not_set_then_event_written.cs deleted file mode 100644 index bbd8ef16e..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_not_set_then_event_written.cs +++ /dev/null @@ -1,54 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class connect_to_existing_with_start_from_not_set_then_event_written - : IClassFixture { - private const string Group = "startfromnotset2"; - - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_not_set_then_event_written(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_non_system_event() { - var resolvedEvent = await _fixture.Subscription!.Messages.OfType() - .Select(e => e.ResolvedEvent) - .Where(resolvedEvent => !SystemStreams.IsSystemStream(resolvedEvent.OriginalStreamId)) - .FirstOrDefaultAsync().AsTask().WithTimeout(); - - Assert.Equal(_fixture.ExpectedEvent.EventId, resolvedEvent.Event.EventId); - Assert.Equal(_fixture.ExpectedStreamId, resolvedEvent.Event.EventStreamId); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData ExpectedEvent; - public readonly string ExpectedStreamId; - - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - ExpectedEvent = CreateTestEvents(1).First(); - ExpectedStreamId = Guid.NewGuid().ToString(); - } - - protected override async Task Given() { - foreach (var @event in CreateTestEvents(10)) { - await StreamsClient.AppendToStreamAsync("non-system-stream-" + Guid.NewGuid(), StreamState.Any, - new[] { @event }); - } - - await Client.CreateToAllAsync(Group, new(), userCredentials: TestCredentials.Root); - Subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - } - - protected override async Task When() => - await StreamsClient.AppendToStreamAsync(ExpectedStreamId, StreamState.NoStream, new[] { ExpectedEvent }); - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_end_position.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_end_position.cs deleted file mode 100644 index e7f3c9913..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_end_position.cs +++ /dev/null @@ -1,46 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class connect_to_existing_with_start_from_set_to_end_position - : IClassFixture { - private const string Group = "startfromend1"; - - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_set_to_end_position(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_gets_no_non_system_events() { - await Assert.ThrowsAsync(() => _fixture.Subscription!.Messages - .OfType() - .Where(e => !SystemStreams.IsSystemStream(e.ResolvedEvent.OriginalStreamId)) - .AnyAsync() - .AsTask() - .WithTimeout(TimeSpan.FromMilliseconds(250))); - } - - public class Fixture : EventStoreClientFixture { - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - protected override async Task Given() { - foreach (var @event in CreateTestEvents(10)) { - await StreamsClient.AppendToStreamAsync("non-system-stream-" + Guid.NewGuid(), StreamState.Any, - new[] { @event }); - } - - await Client.CreateToAllAsync(Group, new(startFrom: Position.End), userCredentials: TestCredentials.Root); - } - - protected override Task When() { - Subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - return Task.CompletedTask; - } - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_end_position_then_event_written.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_end_position_then_event_written.cs deleted file mode 100644 index 835c8538c..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_end_position_then_event_written.cs +++ /dev/null @@ -1,56 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class - connect_to_existing_with_start_from_set_to_end_position_then_event_written - : IClassFixture { - private const string Group = "startfromnotset2"; - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_set_to_end_position_then_event_written(Fixture fixture) => - _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_non_system_event() { - var resolvedEvent = await _fixture.Subscription!.Messages - .OfType() - .Select(e => e.ResolvedEvent) - .Where(resolvedEvent => !SystemStreams.IsSystemStream(resolvedEvent.OriginalStreamId)) - .FirstAsync() - .AsTask() - .WithTimeout(); - Assert.Equal(_fixture.ExpectedEvent.EventId, resolvedEvent.Event.EventId); - Assert.Equal(_fixture.ExpectedStreamId, resolvedEvent.Event.EventStreamId); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData ExpectedEvent; - public readonly string ExpectedStreamId; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - ExpectedEvent = CreateTestEvents(1).First(); - ExpectedStreamId = Guid.NewGuid().ToString(); - } - - protected override async Task Given() { - foreach (var @event in CreateTestEvents(10)) { - await StreamsClient.AppendToStreamAsync("non-system-stream-" + Guid.NewGuid(), StreamState.Any, - new[] { @event }); - } - - await Client.CreateToAllAsync(Group, new(startFrom: Position.End), userCredentials: TestCredentials.Root); - Subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - } - - protected override async Task When() => - await StreamsClient.AppendToStreamAsync(ExpectedStreamId, StreamState.NoStream, new[] { ExpectedEvent }); - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_invalid_middle_position.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_invalid_middle_position.cs deleted file mode 100644 index b45330a9e..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_invalid_middle_position.cs +++ /dev/null @@ -1,48 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class connect_to_existing_with_start_from_set_to_invalid_middle_position - : IClassFixture { - private const string Group = "startfrominvalid1"; - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_set_to_invalid_middle_position(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_is_dropped() { - var ex = await Assert.ThrowsAsync(async () => - await _fixture.Enumerator!.MoveNextAsync()); - - Assert.Equal(SystemStreams.AllStream, ex.StreamName); - Assert.Equal(Group, ex.GroupName); - } - - public class Fixture : EventStoreClientFixture { - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - public IAsyncEnumerator? Enumerator { get; private set; } - - protected override async Task Given() { - var invalidPosition = new Position(1L, 1L); - await Client.CreateToAllAsync(Group, new(startFrom: invalidPosition), - userCredentials: TestCredentials.Root); - } - - protected override async Task When() { - Subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - Enumerator = Subscription.Messages.GetAsyncEnumerator(); - - await Enumerator.MoveNextAsync(); - } - - public override async Task DisposeAsync() { - if (Enumerator is not null) { - await Enumerator.DisposeAsync(); - } - - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_valid_middle_position.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_valid_middle_position.cs deleted file mode 100644 index daaf838a9..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_with_start_from_set_to_valid_middle_position.cs +++ /dev/null @@ -1,51 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class connect_to_existing_with_start_from_set_to_valid_middle_position - : IClassFixture { - private const string Group = "startfromvalid"; - - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_set_to_valid_middle_position(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_gets_the_event_at_the_specified_start_position_as_its_first_event() { - var resolvedEvent = await _fixture.Subscription!.Messages.OfType() - .Select(e => e.ResolvedEvent) - .FirstAsync() - .AsTask() - .WithTimeout(); - Assert.Equal(_fixture.ExpectedEvent.OriginalPosition, resolvedEvent.Event.Position); - Assert.Equal(_fixture.ExpectedEvent.Event.EventId, resolvedEvent.Event.EventId); - Assert.Equal(_fixture.ExpectedEvent.Event.EventStreamId, resolvedEvent.Event.EventStreamId); - } - - public class Fixture : EventStoreClientFixture { - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - public ResolvedEvent ExpectedEvent { get; private set; } - - protected override async Task Given() { - var events = await StreamsClient - .ReadAllAsync(Direction.Forwards, Position.Start, 10, userCredentials: TestCredentials.Root) - .ToArrayAsync(); - - ExpectedEvent = events[events.Length / 2]; //just a random event in the middle of the results - - await Client.CreateToAllAsync(Group, new(startFrom: ExpectedEvent.OriginalPosition), - userCredentials: TestCredentials.Root); - } - - protected override Task When() { - Subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - return Task.CompletedTask; - } - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_without_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_without_permissions.cs deleted file mode 100644 index 865281ec0..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_without_permissions.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class connect_to_existing_without_permissions : IClassFixture { - private readonly Fixture _fixture; - public connect_to_existing_without_permissions(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public Task throws_access_denied() => - Assert.ThrowsAsync( - async () => { - await using var subscription = _fixture.Client.SubscribeToAll("agroupname55"); - await subscription.AnyAsync().AsTask().WithTimeout(); - }); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => - Client.CreateToAllAsync("agroupname55", new(), userCredentials: TestCredentials.Root); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_without_read_all_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_without_read_all_permissions.cs deleted file mode 100644 index 56eccd0fe..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_existing_without_read_all_permissions.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class connect_to_existing_without_read_all_permissions - : IClassFixture { - private readonly Fixture _fixture; - public connect_to_existing_without_read_all_permissions(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public Task throws_access_denied() => - Assert.ThrowsAsync( - async () => { - await using var subscription = - _fixture.Client.SubscribeToAll("agroupname55", userCredentials: TestCredentials.TestUser1); - await subscription.Messages.AnyAsync().AsTask().WithTimeout(); - }); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => - Client.CreateToAllAsync("agroupname55", new(), userCredentials: TestCredentials.Root); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_non_existing_with_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_non_existing_with_permissions.cs deleted file mode 100644 index 40a541040..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_to_non_existing_with_permissions.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class connect_to_non_existing_with_permissions - : IClassFixture { - private const string Group = "foo"; - - private readonly Fixture _fixture; - - public connect_to_non_existing_with_permissions(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task throws_persistent_subscription_not_found() { - await using var subscription = _fixture.Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - - Assert.True(await subscription.Messages.OfType().AnyAsync() - .AsTask() - .WithTimeout()); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_with_retries.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_with_retries.cs deleted file mode 100644 index ea4236278..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/connect_with_retries.cs +++ /dev/null @@ -1,49 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class connect_with_retries : IClassFixture { - private const string Group = "retries"; - private readonly Fixture _fixture; - - public connect_with_retries(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task events_are_retried_until_success() { - var retryCount = await _fixture.Subscription!.Messages.OfType() - .SelectAwait(async e => { - if (e.RetryCount > 4) { - await _fixture.Subscription.Ack(e.ResolvedEvent); - } else { - await _fixture.Subscription.Nack(PersistentSubscriptionNakEventAction.Retry, - "Not yet tried enough times", e.ResolvedEvent); - } - - return e.RetryCount; - }) - .Where(retryCount => retryCount > 4) - .FirstOrDefaultAsync() - .AsTask() - .WithTimeout(); - - Assert.Equal(5, retryCount); - } - - public class Fixture : EventStoreClientFixture { - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - protected override async Task Given() { - await Client.CreateToAllAsync(Group, new(startFrom: Position.Start), userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - } - - protected override Task When() => Task.CompletedTask; - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_after_deleting_the_same.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_after_deleting_the_same.cs deleted file mode 100644 index a3c673f48..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_after_deleting_the_same.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class create_after_deleting_the_same : IClassFixture { - readonly Fixture _fixture; - - public create_after_deleting_the_same(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_completion_succeeds() => - await _fixture.Client.CreateToAllAsync( - "existing", - new(), - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - - protected override async Task When() { - await Client.CreateToAllAsync( - "existing", - new(), - userCredentials: TestCredentials.Root - ); - - await Client.DeleteToAllAsync( - "existing", - userCredentials: TestCredentials.Root - ); - } - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_duplicate.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_duplicate.cs deleted file mode 100644 index abe410c26..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_duplicate.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Grpc.Core; - -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class create_duplicate : IClassFixture { - readonly Fixture _fixture; - - public create_duplicate(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_completion_fails() { - var ex = await Assert.ThrowsAsync( - () => _fixture.Client.CreateToAllAsync( - "group32", - new(), - userCredentials: TestCredentials.Root - ) - ); - - Assert.Equal(StatusCode.AlreadyExists, ex.StatusCode); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - - protected override Task When() => - Client.CreateToAllAsync( - "group32", - new(), - userCredentials: TestCredentials.Root - ); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_filtered.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_filtered.cs deleted file mode 100644 index 8eff2a425..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_filtered.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class create_filtered : IClassFixture { - readonly Fixture _fixture; - - public create_filtered(Fixture fixture) => _fixture = fixture; - - public static IEnumerable FilterCases() => Filters.All.Select(filter => new object[] { filter }); - - [SupportsPSToAll.Theory] - [MemberData(nameof(FilterCases))] - public async Task the_completion_succeeds(string filterName) { - var streamPrefix = _fixture.GetStreamName(); - var (getFilter, _) = Filters.GetFilter(filterName); - var filter = getFilter(streamPrefix); - - await _fixture.Client.CreateToAllAsync( - filterName, - filter, - new(), - userCredentials: TestCredentials.Root - ); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_on_all_stream.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_on_all_stream.cs deleted file mode 100644 index 92aa86e1d..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_on_all_stream.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class create_on_all_stream : IClassFixture { - readonly Fixture _fixture; - - public create_on_all_stream(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public Task the_completion_succeeds() => _fixture.Client.CreateToAllAsync("existing", new(), userCredentials: TestCredentials.Root); - - [SupportsPSToAll.Fact] - public Task throws_argument_exception_if_wrong_start_from_type_passed() => - Assert.ThrowsAsync( - () => _fixture.Client.CreateToAllAsync("existing", new(startFrom: StreamPosition.End), userCredentials: TestCredentials.Root) - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_persistent_subscription_with_dont_timeout.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_persistent_subscription_with_dont_timeout.cs deleted file mode 100644 index f44c830f0..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_persistent_subscription_with_dont_timeout.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class create_with_dont_timeout - : IClassFixture { - readonly Fixture _fixture; - - public create_with_dont_timeout(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public Task the_subscription_is_created_without_error() => - _fixture.Client.CreateToAllAsync( - "dont-timeout", - new(messageTimeout: TimeSpan.Zero), - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_with_commit_position_equal_to_last_indexed_position.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_with_commit_position_equal_to_last_indexed_position.cs deleted file mode 100644 index e6db02901..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_with_commit_position_equal_to_last_indexed_position.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class create_with_commit_position_equal_to_last_indexed_position : IClassFixture { - readonly Fixture _fixture; - - public create_with_commit_position_equal_to_last_indexed_position(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_completion_succeeds() => - await _fixture.Client.CreateToAllAsync( - "group57", - new(startFrom: new Position(_fixture.LastCommitPosition, _fixture.LastCommitPosition)), - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - public ulong LastCommitPosition; - - protected override async Task Given() { - var lastEvent = await StreamsClient.ReadAllAsync( - Direction.Backwards, - Position.End, - 1, - userCredentials: TestCredentials.Root - ).FirstAsync(); - - LastCommitPosition = lastEvent.OriginalPosition?.CommitPosition ?? throw new(); - } - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_with_commit_position_larger_than_last_indexed_position.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_with_commit_position_larger_than_last_indexed_position.cs deleted file mode 100644 index 7769f8b70..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_with_commit_position_larger_than_last_indexed_position.cs +++ /dev/null @@ -1,41 +0,0 @@ -using Grpc.Core; - -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class create_with_commit_position_larger_than_last_indexed_position - : IClassFixture { - readonly Fixture _fixture; - - public create_with_commit_position_larger_than_last_indexed_position(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task fails() { - var ex = await Assert.ThrowsAsync( - () => - _fixture.Client.CreateToAllAsync( - "group57", - new(startFrom: new Position(_fixture.LastCommitPosition + 1, _fixture.LastCommitPosition)), - userCredentials: TestCredentials.Root - ) - ); - - Assert.Equal(StatusCode.Internal, ex.StatusCode); - } - - public class Fixture : EventStoreClientFixture { - public ulong LastCommitPosition; - - protected override async Task Given() { - var lastEvent = await StreamsClient.ReadAllAsync( - Direction.Backwards, - Position.End, - 1, - userCredentials: TestCredentials.Root - ).FirstAsync(); - - LastCommitPosition = lastEvent.OriginalPosition?.CommitPosition ?? throw new(); - } - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_with_prepare_position_larger_than_commit_position.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_with_prepare_position_larger_than_commit_position.cs deleted file mode 100644 index 434e90d7a..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_with_prepare_position_larger_than_commit_position.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class create_with_prepare_position_larger_than_commit_position - : IClassFixture { - readonly Fixture _fixture; - - public create_with_prepare_position_larger_than_commit_position(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public Task fails_with_argument_out_of_range_exception() => - Assert.ThrowsAsync( - () => - _fixture.Client.CreateToAllAsync( - "group57", - new(startFrom: new Position(0, 1)), - userCredentials: TestCredentials.Root - ) - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_without_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_without_permissions.cs deleted file mode 100644 index 71d87a128..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/create_without_permissions.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class create_without_permissions - : IClassFixture { - readonly Fixture _fixture; - - public create_without_permissions(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public Task the_completion_fails_with_access_denied() => - Assert.ThrowsAsync( - () => - _fixture.Client.CreateToAllAsync( - "group57", - new() - ) - ); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_existing_with_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_existing_with_permissions.cs deleted file mode 100644 index a81180092..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_existing_with_permissions.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class deleting_existing_with_permissions - : IClassFixture { - readonly Fixture _fixture; - - public deleting_existing_with_permissions(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public Task the_delete_of_group_succeeds() => - _fixture.Client.DeleteToAllAsync( - "groupname123", - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - - protected override Task When() => - Client.CreateToAllAsync( - "groupname123", - new(), - userCredentials: TestCredentials.Root - ); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_existing_with_subscriber.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_existing_with_subscriber.cs deleted file mode 100644 index 4db83e251..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_existing_with_subscriber.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class deleting_existing_with_subscriber : IClassFixture { - public const string Group = "groupname123"; - private readonly Fixture _fixture; - - public deleting_existing_with_subscriber(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_subscription_is_dropped_with_not_found() { - await using var subscription = _fixture.Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - - Assert.True(await subscription.Messages.OfType().AnyAsync() - .AsTask() - .WithTimeout()); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Client.CreateToAllAsync(Group, new(), userCredentials: TestCredentials.Root); - - protected override Task When() => Client.DeleteToAllAsync(Group, userCredentials: TestCredentials.Root); - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_filtered.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_filtered.cs deleted file mode 100644 index 7a461ebf9..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_filtered.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class deleting_filtered - : IClassFixture { - const string Group = "to-be-deleted"; - readonly Fixture _fixture; - - public deleting_filtered(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_completion_succeeds() => await _fixture.Client.DeleteToAllAsync(Group, userCredentials: TestCredentials.Root); - - public class Fixture : EventStoreClientFixture { - protected override async Task Given() => - await Client.CreateToAllAsync( - Group, - EventTypeFilter.Prefix("prefix-filter-"), - new(), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_nonexistent.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_nonexistent.cs deleted file mode 100644 index 804850e89..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_nonexistent.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class deleting_nonexistent - : IClassFixture { - readonly Fixture _fixture; - - public deleting_nonexistent(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_delete_fails_with_argument_exception() => - await Assert.ThrowsAsync( - () => _fixture.Client.DeleteToAllAsync(Guid.NewGuid().ToString(), userCredentials: TestCredentials.Root) - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_without_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_without_permissions.cs deleted file mode 100644 index 13e1339a9..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/deleting_without_permissions.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class deleting_without_permissions - : IClassFixture { - readonly Fixture _fixture; - - public deleting_without_permissions(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_delete_fails_with_access_denied() => - await Assert.ThrowsAsync(() => _fixture.Client.DeleteToAllAsync(Guid.NewGuid().ToString())); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/get_info.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/get_info.cs deleted file mode 100644 index ab748a5d5..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/get_info.cs +++ /dev/null @@ -1,181 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class get_info : IClassFixture { - private const string GroupName = nameof(get_info); - - private static readonly PersistentSubscriptionSettings Settings = new( - resolveLinkTos: true, - startFrom: Position.Start, - extraStatistics: true, - messageTimeout: TimeSpan.FromSeconds(9), - maxRetryCount: 11, - liveBufferSize: 303, - readBatchSize: 30, - historyBufferSize: 909, - checkPointAfter: TimeSpan.FromSeconds(1), - checkPointLowerBound: 1, - checkPointUpperBound: 1, - maxSubscriberCount: 500, - consumerStrategyName: SystemConsumerStrategies.Pinned); - - private readonly Fixture _fixture; - - public get_info(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task throws_when_not_supported() { - if (SupportsPSToAll.No) { - await Assert.ThrowsAsync(async () => - await _fixture.Client.GetInfoToAllAsync(GroupName, userCredentials: TestCredentials.Root)); - } - } - - [SupportsPSToAll.Fact] - public async Task returns_expected_result() { - var result = await _fixture.Client.GetInfoToAllAsync(GroupName, userCredentials: TestCredentials.Root); - - Assert.Equal("$all", result.EventSource); - Assert.Equal(GroupName, result.GroupName); - Assert.Equal("Live", result.Status); - - Assert.NotNull(Settings.StartFrom); - Assert.True(result.Stats.TotalItems > 0); - Assert.True(result.Stats.OutstandingMessagesCount > 0); - Assert.True(result.Stats.AveragePerSecond >= 0); - Assert.True(result.Stats.ParkedMessageCount > 0); - Assert.True(result.Stats.AveragePerSecond >= 0); - Assert.True(result.Stats.CountSinceLastMeasurement >= 0); - Assert.True(result.Stats.TotalInFlightMessages >= 0); - Assert.NotNull(result.Stats.LastKnownEventPosition); - Assert.NotNull(result.Stats.LastCheckpointedEventPosition); - Assert.True(result.Stats.LiveBufferCount >= 0); - - Assert.NotNull(result.Connections); - Assert.NotEmpty(result.Connections); - - var connection = result.Connections.First(); - Assert.NotNull(connection.From); - Assert.Equal(TestCredentials.Root.Username, connection.Username); - Assert.NotEmpty(connection.ConnectionName); - Assert.True(connection.AverageItemsPerSecond >= 0); - Assert.True(connection.TotalItems > 0); - Assert.True(connection.CountSinceLastMeasurement >= 0); - Assert.True(connection.AvailableSlots >= 0); - Assert.True(connection.InFlightMessages >= 0); - Assert.NotNull(connection.ExtraStatistics); - Assert.NotEmpty(connection.ExtraStatistics); - - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Highest); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Mean); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Median); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Fastest); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Quintile1); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Quintile2); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Quintile3); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Quintile4); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Quintile5); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyPercent); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyFivePercent); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyNinePercent); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyNinePointFivePercent); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyNinePointNinePercent); - - Assert.NotNull(result.Settings); - Assert.Equal(Settings.StartFrom, result.Settings!.StartFrom); - Assert.Equal(Settings.ResolveLinkTos, result.Settings!.ResolveLinkTos); - Assert.Equal(Settings.ExtraStatistics, result.Settings!.ExtraStatistics); - Assert.Equal(Settings.MessageTimeout, result.Settings!.MessageTimeout); - Assert.Equal(Settings.MaxRetryCount, result.Settings!.MaxRetryCount); - Assert.Equal(Settings.LiveBufferSize, result.Settings!.LiveBufferSize); - Assert.Equal(Settings.ReadBatchSize, result.Settings!.ReadBatchSize); - Assert.Equal(Settings.HistoryBufferSize, result.Settings!.HistoryBufferSize); - Assert.Equal(Settings.CheckPointAfter, result.Settings!.CheckPointAfter); - Assert.Equal(Settings.CheckPointLowerBound, result.Settings!.CheckPointLowerBound); - Assert.Equal(Settings.CheckPointUpperBound, result.Settings!.CheckPointUpperBound); - Assert.Equal(Settings.MaxSubscriberCount, result.Settings!.MaxSubscriberCount); - Assert.Equal(Settings.ConsumerStrategyName, result.Settings!.ConsumerStrategyName); - } - - [SupportsPSToAll.Fact] - public async Task throws_with_non_existing_subscription() => - await Assert.ThrowsAsync( - async () => await _fixture.Client.GetInfoToAllAsync("NonExisting", userCredentials: TestCredentials.Root)); - - [SupportsPSToAll.Fact] - public async Task throws_with_no_credentials() => - await Assert.ThrowsAsync(async () => - await _fixture.Client.GetInfoToAllAsync("NonExisting")); - - [SupportsPSToAll.Fact] - public async Task throws_with_non_existing_user() => - await Assert.ThrowsAsync(async () => - await _fixture.Client.GetInfoToAllAsync("NonExisting", userCredentials: TestCredentials.TestBadUser)); - - [SupportsPSToAll.Fact] - public async Task returns_result_with_normal_user_credentials() { - var result = await _fixture.Client.GetInfoToAllAsync(GroupName, userCredentials: TestCredentials.TestUser1); - - Assert.Equal("$all", result.EventSource); - } - - private void AssertKeyAndValue(IDictionary items, string key) { - Assert.True(items.ContainsKey(key)); - Assert.True(items[key] > 0); - } - - public class Fixture : EventStoreClientFixture { - private EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? _subscription; - private IAsyncEnumerator? _enumerator; - public Fixture() : base(noDefaultCredentials: true) { } - - protected override async Task Given() { - if (SupportsPSToAll.No) - return; - - await Client.CreateToAllAsync(GroupName, get_info.Settings, userCredentials: TestCredentials.Root); - - foreach (var eventData in CreateTestEvents(20)) { - await StreamsClient.AppendToStreamAsync($"test-{Guid.NewGuid():n}", StreamState.NoStream, - new[] { eventData }, userCredentials: TestCredentials.Root); - } - } - - protected override async Task When() { - if (SupportsPSToAll.No) - return; - - var counter = 0; - - _subscription = Client.SubscribeToAll(GroupName, userCredentials: TestCredentials.Root); - _enumerator = _subscription.Messages.GetAsyncEnumerator(); - - while (await _enumerator.MoveNextAsync()) { - if (_enumerator.Current is not PersistentSubscriptionMessage.Event (var resolvedEvent, _)) { - continue; - } - - counter++; - - if (counter == 1) { - await _subscription.Nack(PersistentSubscriptionNakEventAction.Park, "Test", resolvedEvent); - } - - if (counter > 10) { - return; - } - } - } - - public override async Task DisposeAsync() { - if (_enumerator is not null) { - await _enumerator.DisposeAsync(); - } - - if (_subscription is not null) { - await _subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_catching_up_to_link_to_events_manual_ack.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_catching_up_to_link_to_events_manual_ack.cs deleted file mode 100644 index dbcc44b43..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_catching_up_to_link_to_events_manual_ack.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System.Text; - -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class happy_case_catching_up_to_link_to_events_manual_ack - : IClassFixture { - private const string Group = nameof(Group); - private const int BufferCount = 10; - private const int EventWriteCount = BufferCount * 2; - - private readonly Fixture _fixture; - - public happy_case_catching_up_to_link_to_events_manual_ack(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task Test() { - await _fixture.Subscription!.Messages.OfType() - .Take(_fixture.Events.Length) - .ForEachAwaitAsync(e => _fixture.Subscription.Ack(e.ResolvedEvent)) - .WithTimeout(); - - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(EventWriteCount) - .Select((e, i) => new EventData(e.EventId, SystemEventTypes.LinkTo, Encoding.UTF8.GetBytes($"{i}@test"), - contentType: Constants.Metadata.ContentTypes.ApplicationOctetStream)) - .ToArray(); - } - - protected override async Task Given() { - foreach (var e in Events) { - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); - } - - await Client.CreateToAllAsync(Group, new(startFrom: Position.Start, resolveLinkTos: true), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToAll(Group, bufferSize: BufferCount, userCredentials: TestCredentials.Root); - } - - protected override Task When() => Task.CompletedTask; - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_catching_up_to_normal_events_manual_ack.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_catching_up_to_normal_events_manual_ack.cs deleted file mode 100644 index 05612443d..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_catching_up_to_normal_events_manual_ack.cs +++ /dev/null @@ -1,51 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class happy_case_catching_up_to_normal_events_manual_ack - : IClassFixture { - private const string Group = nameof(Group); - private const int BufferCount = 10; - private const int EventWriteCount = BufferCount * 2; - - private readonly Fixture _fixture; - - public happy_case_catching_up_to_normal_events_manual_ack(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task Test() { - await _fixture.Subscription!.Messages.OfType() - .Take(_fixture.Events.Length) - .ForEachAwaitAsync(e => _fixture.Subscription.Ack(e.ResolvedEvent)) - .WithTimeout(); - } - - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(EventWriteCount).ToArray(); - } - - protected override async Task Given() { - foreach (var e in Events) - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); - - await Client.CreateToAllAsync(Group, new(startFrom: Position.Start, resolveLinkTos: true), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToAll(Group, bufferSize: BufferCount, userCredentials: TestCredentials.Root); - } - - protected override Task When() => Task.CompletedTask; - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_filtered.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_filtered.cs deleted file mode 100644 index 9d89fddb1..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_filtered.cs +++ /dev/null @@ -1,54 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class happy_case_filtered : IClassFixture { - private readonly Fixture _fixture; - - public happy_case_filtered(Fixture fixture) => _fixture = fixture; - - public static IEnumerable FilterCases() => Filters.All.Select(filter => new object[] { filter }); - - [SupportsPSToAll.Theory] - [MemberData(nameof(FilterCases))] - public async Task reads_all_existing_filtered_events(string filterName) { - var streamPrefix = $"{filterName}-{_fixture.GetStreamName()}"; - var (getFilter, prepareEvent) = Filters.GetFilter(filterName); - var filter = getFilter(streamPrefix); - - var appearedEvents = new List(); - var events = _fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)).ToArray(); - - foreach (var e in events) { - await _fixture.StreamsClient.AppendToStreamAsync($"{streamPrefix}_{Guid.NewGuid():n}", StreamState.NoStream, - new[] { e }); - } - - await _fixture.Client.CreateToAllAsync(filterName, filter, new(startFrom: Position.Start), - userCredentials: TestCredentials.Root); - - await using var subscription = - _fixture.Client.SubscribeToAll(filterName, userCredentials: TestCredentials.Root); - await subscription.Messages - .OfType() - .Take(events.Length) - .ForEachAwaitAsync(async e => { - var (resolvedEvent, _) = e; - appearedEvents.Add(resolvedEvent.Event); - await subscription.Ack(resolvedEvent); - }) - .WithTimeout(); - - Assert.Equal(events.Select(x => x.EventId), appearedEvents.Select(x => x.EventId)); - } - - public class Fixture : EventStoreClientFixture { - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Guid.NewGuid().ToString(), StreamState.NoStream, - CreateTestEvents(256)); - - await StreamsClient.SetStreamMetadataAsync(SystemStreams.AllStream, StreamState.Any, - new(acl: new(SystemRoles.All)), userCredentials: TestCredentials.Root); - } - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_filtered_with_start_from_set.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_filtered_with_start_from_set.cs deleted file mode 100644 index 065782783..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_filtered_with_start_from_set.cs +++ /dev/null @@ -1,62 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class happy_case_filtered_with_start_from_set : IClassFixture { - private readonly Fixture _fixture; - - public happy_case_filtered_with_start_from_set(Fixture fixture) => _fixture = fixture; - - public static IEnumerable FilterCases() => Filters.All.Select(filter => new object[] { filter }); - - [SupportsPSToAll.Theory] - [MemberData(nameof(FilterCases))] - public async Task reads_all_existing_filtered_events_from_specified_start(string filterName) { - var streamPrefix = $"{filterName}-{_fixture.GetStreamName()}"; - var (getFilter, prepareEvent) = Filters.GetFilter(filterName); - var filter = getFilter(streamPrefix); - - var events = _fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)).ToArray(); - var eventsToSkip = events.Take(10).ToArray(); - var eventsToCapture = events.Skip(10).ToArray(); - - IWriteResult? eventToCaptureResult = null; - - foreach (var e in eventsToSkip) { - await _fixture.StreamsClient.AppendToStreamAsync($"{streamPrefix}_{Guid.NewGuid():n}", StreamState.NoStream, - new[] { e }); - } - - foreach (var e in eventsToCapture) { - var result = await _fixture.StreamsClient.AppendToStreamAsync($"{streamPrefix}_{Guid.NewGuid():n}", - StreamState.NoStream, new[] { e }); - - eventToCaptureResult ??= result; - } - - await _fixture.Client.CreateToAllAsync(filterName, filter, new(startFrom: eventToCaptureResult!.LogPosition), - userCredentials: TestCredentials.Root); - - await using var subscription = - _fixture.Client.SubscribeToAll(filterName, userCredentials: TestCredentials.Root); - - var appearedEvents = await subscription.Messages.OfType() - .Take(10) - .Select(e => e.ResolvedEvent.Event) - .ToArrayAsync() - .AsTask() - .WithTimeout(); - - Assert.Equal(eventsToCapture.Select(x => x.EventId), appearedEvents.Select(x => x.EventId)); - } - - public class Fixture : EventStoreClientFixture { - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Guid.NewGuid().ToString(), StreamState.NoStream, - CreateTestEvents(256)); - - await StreamsClient.SetStreamMetadataAsync(SystemStreams.AllStream, StreamState.Any, - new(acl: new(SystemRoles.All)), userCredentials: TestCredentials.Root); - } - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_writing_and_subscribing_to_normal_events_manual_ack.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_writing_and_subscribing_to_normal_events_manual_ack.cs deleted file mode 100644 index 100e49f27..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/happy_case_writing_and_subscribing_to_normal_events_manual_ack.cs +++ /dev/null @@ -1,57 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class happy_case_writing_and_subscribing_to_normal_events_manual_ack - : IClassFixture { - private const string Group = nameof(Group); - private const int BufferCount = 10; - private const int EventWriteCount = BufferCount * 2; - - private readonly Fixture _fixture; - - public happy_case_writing_and_subscribing_to_normal_events_manual_ack(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task Test() { - await _fixture.Subscription!.Messages.OfType() - .SelectAwait(async e => { - await _fixture.Subscription.Ack(e.ResolvedEvent); - return e; - }) - .Where(e => e.ResolvedEvent.OriginalStreamId.StartsWith("test-")) - .Take(_fixture.Events.Length) - .ToArrayAsync() - .AsTask() - .WithTimeout(); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(EventWriteCount).ToArray(); - } - - protected override async Task Given() { - await Client.CreateToAllAsync(Group, new(startFrom: Position.End, resolveLinkTos: true), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToAll(Group, bufferSize: BufferCount, userCredentials: TestCredentials.Root); - } - - protected override async Task When() { - foreach (var e in Events) { - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); - } - } - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/list_with_persistent_subscriptions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/list_with_persistent_subscriptions.cs deleted file mode 100644 index 443a9d04e..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/list_with_persistent_subscriptions.cs +++ /dev/null @@ -1,82 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class list_with_persistent_subscriptions : IClassFixture { - const int AllStreamSubscriptionCount = 3; - const int StreamSubscriptionCount = 4; - const string GroupName = nameof(list_with_persistent_subscriptions); - const string StreamName = nameof(list_with_persistent_subscriptions); - - readonly Fixture _fixture; - - public list_with_persistent_subscriptions(Fixture fixture) => _fixture = fixture; - - int TotalSubscriptionCount => - SupportsPSToAll.No - ? StreamSubscriptionCount - : StreamSubscriptionCount + AllStreamSubscriptionCount; - - [Fact] - public async Task throws_when_not_supported() { - if (SupportsPSToAll.No) - await Assert.ThrowsAsync(async () => { await _fixture.Client.ListToAllAsync(userCredentials: TestCredentials.Root); }); - } - - [SupportsPSToAll.Fact] - public async Task returns_subscriptions_to_all_stream() { - var result = (await _fixture.Client.ListToAllAsync(userCredentials: TestCredentials.Root)).ToList(); - Assert.Equal(AllStreamSubscriptionCount, result.Count); - Assert.All(result, s => Assert.Equal("$all", s.EventSource)); - } - - [Fact] - public async Task returns_all_subscriptions() { - var result = (await _fixture.Client.ListAllAsync(userCredentials: TestCredentials.Root)).ToList(); - Assert.Equal(TotalSubscriptionCount, result.Count()); - } - - [SupportsPSToAll.Fact] - public async Task throws_with_no_credentials() => - await Assert.ThrowsAsync( - async () => - await _fixture.Client.ListToAllAsync() - ); - - [SupportsPSToAll.Fact] - public async Task throws_with_non_existing_user() => - await Assert.ThrowsAsync( - async () => - await _fixture.Client.ListToAllAsync(userCredentials: TestCredentials.TestBadUser) - ); - - [SupportsPSToAll.Fact] - public async Task returns_result_with_normal_user_credentials() { - var result = await _fixture.Client.ListToAllAsync(userCredentials: TestCredentials.TestUser1); - Assert.Equal(AllStreamSubscriptionCount, result.Count()); - } - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(skipPSWarmUp: true, noDefaultCredentials: true) { } - - protected override async Task Given() { - for (var i = 0; i < StreamSubscriptionCount; i++) - await Client.CreateToStreamAsync( - StreamName, - GroupName + i, - new(), - userCredentials: TestCredentials.Root - ); - - if (SupportsPSToAll.No) - return; - - for (var i = 0; i < AllStreamSubscriptionCount; i++) - await Client.CreateToAllAsync( - GroupName + i, - new(), - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/list_without_persistent_subscriptions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/list_without_persistent_subscriptions.cs deleted file mode 100644 index 0a9c435be..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/list_without_persistent_subscriptions.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class list_without_persistent_subscriptions : IClassFixture { - readonly Fixture _fixture; - - public list_without_persistent_subscriptions(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task throws() { - if (SupportsPSToAll.No) { - await Assert.ThrowsAsync(async () => { await _fixture.Client.ListToAllAsync(userCredentials: TestCredentials.Root); }); - - return; - } - - await Assert.ThrowsAsync( - async () => - await _fixture.Client.ListToAllAsync(userCredentials: TestCredentials.Root) - ); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/replay_parked.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/replay_parked.cs deleted file mode 100644 index 501500abd..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/replay_parked.cs +++ /dev/null @@ -1,90 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class replay_parked : IClassFixture { - const string GroupName = nameof(replay_parked); - - readonly Fixture _fixture; - - public replay_parked(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task throws_when_not_supported() { - if (SupportsPSToAll.No) - await Assert.ThrowsAsync( - async () => { - await _fixture.Client.ReplayParkedMessagesToAllAsync( - GroupName, - userCredentials: TestCredentials.Root - ); - } - ); - } - - [SupportsPSToAll.Fact] - public async Task does_not_throw() { - await _fixture.Client.ReplayParkedMessagesToAllAsync( - GroupName, - userCredentials: TestCredentials.Root - ); - - await _fixture.Client.ReplayParkedMessagesToAllAsync( - GroupName, - 100, - userCredentials: TestCredentials.Root - ); - } - - [SupportsPSToAll.Fact] - public async Task throws_when_given_non_existing_subscription() => - await Assert.ThrowsAsync( - () => - _fixture.Client.ReplayParkedMessagesToAllAsync( - "NonExisting", - userCredentials: TestCredentials.Root - ) - ); - - [SupportsPSToAll.Fact] - public async Task throws_with_no_credentials() => - await Assert.ThrowsAsync( - () => - _fixture.Client.ReplayParkedMessagesToAllAsync(GroupName) - ); - - [SupportsPSToAll.Fact] - public async Task throws_with_non_existing_user() => - await Assert.ThrowsAsync( - () => - _fixture.Client.ReplayParkedMessagesToAllAsync( - GroupName, - userCredentials: TestCredentials.TestBadUser - ) - ); - - [SupportsPSToAll.Fact] - public async Task throws_with_normal_user_credentials() => - await Assert.ThrowsAsync( - () => - _fixture.Client.ReplayParkedMessagesToAllAsync( - GroupName, - userCredentials: TestCredentials.TestUser1 - ) - ); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override async Task Given() { - if (SupportsPSToAll.No) - return; - - await Client.CreateToAllAsync( - GroupName, - new(), - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing.cs deleted file mode 100644 index c1fac1c1f..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class update_existing : IClassFixture { - const string Group = "existing"; - - readonly Fixture _fixture; - - public update_existing(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_completion_succeeds() => - await _fixture.Client.UpdateToAllAsync( - Group, - new(), - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override async Task Given() => - await Client.CreateToAllAsync( - Group, - new(), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_filtered.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_filtered.cs deleted file mode 100644 index ff0f5ab5d..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_filtered.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class update_existing_filtered - : IClassFixture { - const string Group = "existing-filtered"; - - readonly Fixture _fixture; - - public update_existing_filtered(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_completion_succeeds() => - await _fixture.Client.UpdateToAllAsync( - Group, - new(true), - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override async Task Given() => - await Client.CreateToAllAsync( - Group, - EventTypeFilter.Prefix("prefix-filter-"), - new(), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_check_point.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_check_point.cs deleted file mode 100644 index 05d6a70e3..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_check_point.cs +++ /dev/null @@ -1,108 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class update_existing_with_check_point : IClassFixture { - private const string Group = "existing-with-check-point"; - - private readonly Fixture _fixture; - - public update_existing_with_check_point(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public void resumes_from_check_point() { - Assert.True(_fixture.Resumed.Event.Position > _fixture.CheckPoint); - } - - public class Fixture : EventStoreClientFixture { - private readonly List _appearedEvents; - private readonly EventData[] _events; - - private EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? _subscription; - private IAsyncEnumerator? _enumerator; - - public ResolvedEvent Resumed { get; private set; } - public Position CheckPoint { get; private set; } - - public Fixture() { - _appearedEvents = new(); - _events = CreateTestEvents(5).ToArray(); - } - - protected override async Task Given() { - foreach (var e in _events) { - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); - } - - await Client.CreateToAllAsync(Group, - new(checkPointLowerBound: 5, checkPointAfter: TimeSpan.FromSeconds(1), startFrom: Position.Start), - userCredentials: TestCredentials.Root); - - _subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - _enumerator = _subscription.Messages.GetAsyncEnumerator(); - await _enumerator.MoveNextAsync(); - - await Task.WhenAll(Subscribe().WithTimeout(), WaitForCheckpoint().WithTimeout()); - - return; - - async Task Subscribe() { - while (await _enumerator.MoveNextAsync()) { - if (_enumerator.Current is not PersistentSubscriptionMessage.Event(var resolvedEvent, _)) { - continue; - } - - _appearedEvents.Add(resolvedEvent); - await _subscription.Ack(resolvedEvent); - if (_appearedEvents.Count == _events.Length) { - break; - } - } - } - - async Task WaitForCheckpoint() { - await using var subscription = StreamsClient.SubscribeToStream( - $"$persistentsubscription-$all::{Group}-checkpoint", FromStream.Start, - userCredentials: TestCredentials.Root); - await foreach (var message in subscription.Messages) { - if (message is not StreamMessage.Event(var resolvedEvent)) { - continue; - } - - CheckPoint = resolvedEvent.Event.Data.ParsePosition(); - return; - } - } } - - protected override async Task When() { - // Force restart of the subscription - await Client.UpdateToAllAsync(Group, new(), userCredentials: TestCredentials.Root); - - try { - while (await _enumerator!.MoveNextAsync()) { } - } catch (PersistentSubscriptionDroppedByServerException) { } - - foreach (var e in _events) { - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.NoStream, new[] { e }); - } - - await using var subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - Resumed = await subscription.Messages.OfType() - .Select(e => e.ResolvedEvent) - .Take(1) - .FirstAsync() - .AsTask() - .WithTimeout(); - } - - public override async Task DisposeAsync() { - if (_enumerator is not null) { - await _enumerator.DisposeAsync(); - } - - if (_subscription is not null) { - await _subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_check_point_filtered.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_check_point_filtered.cs deleted file mode 100644 index 829aca768..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_check_point_filtered.cs +++ /dev/null @@ -1,111 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class update_existing_with_check_point_filtered - : IClassFixture { - private const string Group = "existing-with-check-point-filtered"; - - private readonly Fixture _fixture; - - public update_existing_with_check_point_filtered(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public void resumes_from_check_point() { - Assert.True(_fixture.Resumed.Event.Position > _fixture.CheckPoint); - } - - public class Fixture : EventStoreClientFixture { - private readonly List _appearedEvents; - private readonly EventData[] _events; - - private EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? _subscription; - private IAsyncEnumerator? _enumerator; - - public ResolvedEvent Resumed { get; private set; } - public Position CheckPoint { get; private set; } - - public Fixture() { - _appearedEvents = new(); - _events = CreateTestEvents(5).ToArray(); - } - - - protected override async Task Given() { - foreach (var e in _events) { - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.NoStream, new[] { e }); - } - - await Client.CreateToAllAsync(Group, StreamFilter.Prefix("test"), - new(checkPointLowerBound: 5, checkPointAfter: TimeSpan.FromSeconds(1), startFrom: Position.Start), - userCredentials: TestCredentials.Root); - - _subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - _enumerator = _subscription.Messages.GetAsyncEnumerator(); - await _enumerator.MoveNextAsync(); - - await Task.WhenAll(Subscribe().WithTimeout(), WaitForCheckpoint().WithTimeout()); - - return; - - async Task Subscribe() { - while (await _enumerator.MoveNextAsync()) { - if (_enumerator.Current is not PersistentSubscriptionMessage.Event(var resolvedEvent, _)) { - continue; - } - - _appearedEvents.Add(resolvedEvent); - await _subscription.Ack(resolvedEvent); - if (_appearedEvents.Count == _events.Length) { - break; - } - } - } - - async Task WaitForCheckpoint() { - await using var subscription = StreamsClient.SubscribeToStream( - $"$persistentsubscription-$all::{Group}-checkpoint", FromStream.Start, - userCredentials: TestCredentials.Root); - await foreach (var message in subscription.Messages) { - if (message is not StreamMessage.Event(var resolvedEvent)) { - continue; - } - - CheckPoint = resolvedEvent.Event.Data.ParsePosition(); - return; - } - } - } - - protected override async Task When() { - // Force restart of the subscription - await Client.UpdateToAllAsync(Group, new(), userCredentials: TestCredentials.Root); - - try { - while (await _enumerator!.MoveNextAsync()) { } - } catch (PersistentSubscriptionDroppedByServerException) { } - - foreach (var e in _events) { - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.NoStream, new[] { e }); - } - - await using var subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - Resumed = await subscription.Messages.OfType() - .Select(e => e.ResolvedEvent) - .Take(1) - .FirstAsync() - .AsTask() - .WithTimeout(); - } - - public override async Task DisposeAsync() { - if (_enumerator is not null) { - await _enumerator.DisposeAsync(); - } - - if (_subscription is not null) { - await _subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_commit_position_equal_to_last_indexed_position.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_commit_position_equal_to_last_indexed_position.cs deleted file mode 100644 index 983349b85..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_commit_position_equal_to_last_indexed_position.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class update_existing_with_commit_position_equal_to_last_indexed_position - : IClassFixture { - const string Group = "existing"; - - readonly Fixture _fixture; - - public update_existing_with_commit_position_equal_to_last_indexed_position(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_completion_succeeds() => - await _fixture.Client.UpdateToAllAsync( - Group, - new(startFrom: new Position(_fixture.LastCommitPosition, _fixture.LastCommitPosition)), - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - public ulong LastCommitPosition; - - protected override async Task Given() { - await Client.CreateToAllAsync( - Group, - new(), - userCredentials: TestCredentials.Root - ); - - var lastEvent = await StreamsClient.ReadAllAsync( - Direction.Backwards, - Position.End, - 1, - userCredentials: TestCredentials.Root - ).FirstAsync(); - - LastCommitPosition = lastEvent.OriginalPosition?.CommitPosition ?? throw new(); - } - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_commit_position_larger_than_last_indexed_position.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_commit_position_larger_than_last_indexed_position.cs deleted file mode 100644 index 864e6a806..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_commit_position_larger_than_last_indexed_position.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Grpc.Core; - -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class update_existing_with_commit_position_larger_than_last_indexed_position - : IClassFixture { - const string Group = "existing"; - - readonly Fixture _fixture; - - public update_existing_with_commit_position_larger_than_last_indexed_position(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task fails() { - var ex = await Assert.ThrowsAsync( - () => - _fixture.Client.UpdateToAllAsync( - Group, - new(startFrom: new Position(_fixture.LastCommitPosition + 1, _fixture.LastCommitPosition)), - userCredentials: TestCredentials.Root - ) - ); - - Assert.Equal(StatusCode.Internal, ex.StatusCode); - } - - public class Fixture : EventStoreClientFixture { - public ulong LastCommitPosition; - - protected override async Task When() { - await Client.CreateToAllAsync( - Group, - new(), - userCredentials: TestCredentials.Root - ); - - var lastEvent = await StreamsClient.ReadAllAsync( - Direction.Backwards, - Position.End, - 1, - userCredentials: TestCredentials.Root - ).FirstAsync(); - - LastCommitPosition = lastEvent.OriginalPosition?.CommitPosition ?? throw new(); - } - - protected override Task Given() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_subscribers.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_subscribers.cs deleted file mode 100644 index 71e89d260..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_with_subscribers.cs +++ /dev/null @@ -1,49 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class update_existing_with_subscribers : IClassFixture { - private const string Group = "existing"; - - private readonly Fixture _fixture; - - public update_existing_with_subscribers(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task existing_subscriptions_are_dropped() { - var ex = await Assert.ThrowsAsync(async () => { - while (await _fixture.Enumerator!.MoveNextAsync()) { - } - }).WithTimeout(); - - Assert.Equal(SystemStreams.AllStream, ex.StreamName); - Assert.Equal(Group, ex.GroupName); - } - - public class Fixture : EventStoreClientFixture { - private EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? _subscription; - public IAsyncEnumerator? Enumerator { get; private set; } - - protected override async Task Given() { - await Client.CreateToAllAsync(Group, new(startFrom: Position.Start), userCredentials: TestCredentials.Root); - - _subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - - Enumerator = _subscription.Messages.GetAsyncEnumerator(); - - await Enumerator.MoveNextAsync(); - } - - protected override Task When() => Client.UpdateToAllAsync(Group, new(), userCredentials: TestCredentials.Root); - - public override async Task DisposeAsync() { - if (Enumerator is not null) { - await Enumerator.DisposeAsync(); - } - - if (_subscription is not null) { - await _subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_without_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_without_permissions.cs deleted file mode 100644 index fa72629ca..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_existing_without_permissions.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class update_existing_without_permissions - : IClassFixture { - const string Group = "existing"; - - readonly Fixture _fixture; - - public update_existing_without_permissions(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_completion_fails_with_access_denied() => - await Assert.ThrowsAsync( - () => _fixture.Client.UpdateToAllAsync( - Group, - new() - ) - ); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override async Task Given() => - await Client.CreateToAllAsync( - Group, - new(), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_non_existent.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_non_existent.cs deleted file mode 100644 index 5082e86d0..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_non_existent.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class update_non_existent - : IClassFixture { - const string Group = "nonexistent"; - - readonly Fixture _fixture; - - public update_non_existent(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task the_completion_fails_with_not_found() => - await Assert.ThrowsAsync( - () => _fixture.Client.UpdateToAllAsync( - Group, - new(), - userCredentials: TestCredentials.Root - ) - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_with_prepare_position_larger_than_commit_position.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_with_prepare_position_larger_than_commit_position.cs deleted file mode 100644 index ce53d81ae..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/update_with_prepare_position_larger_than_commit_position.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class update_with_prepare_position_larger_than_commit_position - : IClassFixture { - const string Group = "existing"; - - readonly Fixture _fixture; - - public update_with_prepare_position_larger_than_commit_position(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public Task fails_with_argument_out_of_range_exception() => - Assert.ThrowsAsync( - () => - _fixture.Client.UpdateToAllAsync( - Group, - new(startFrom: new Position(0, 1)), - userCredentials: TestCredentials.Root - ) - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/when_writing_and_filtering_out_events.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/when_writing_and_filtering_out_events.cs deleted file mode 100644 index cda94d8b3..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/when_writing_and_filtering_out_events.cs +++ /dev/null @@ -1,87 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class when_writing_and_filtering_out_events : IClassFixture { - private const string Group = "filtering-out-events"; - - private readonly Fixture _fixture; - - public when_writing_and_filtering_out_events(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public void it_should_write_a_check_point() { - Assert.True(_fixture.SecondCheckPoint > _fixture.FirstCheckPoint); - Assert.Equal(_fixture.Events.Select(e => e.EventId), _fixture.AppearedEvents.Select(e => e.Event.EventId)); - } - - public class Fixture : EventStoreClientFixture { - private readonly List _appearedEvents; - - public Fixture() { - Events = CreateTestEvents(10).ToArray(); - _appearedEvents = new(); - } - - public Position SecondCheckPoint { get; private set; } - public Position FirstCheckPoint { get; private set; } - public EventData[] Events { get; } - public ResolvedEvent[] AppearedEvents => _appearedEvents.ToArray(); - - protected override async Task Given() { - foreach (var e in Events) { - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); - } - - await Client.CreateToAllAsync(Group, StreamFilter.Prefix("test"), - new(checkPointLowerBound: 1, checkPointUpperBound: 5, checkPointAfter: TimeSpan.FromSeconds(1), - startFrom: Position.Start), userCredentials: TestCredentials.Root); - - await using var subscription = Client.SubscribeToAll(Group, userCredentials: TestCredentials.Root); - await using var enumerator = subscription.Messages.GetAsyncEnumerator(); - - await Task.WhenAll(Subscribe().WithTimeout(), WaitForCheckpoints().WithTimeout()); - - return; - - async Task Subscribe() { - while (await enumerator.MoveNextAsync()) { - if (enumerator.Current is not PersistentSubscriptionMessage.Event(var resolvedEvent, _)) { - continue; - } - - _appearedEvents.Add(resolvedEvent); - await subscription.Ack(resolvedEvent); - if (_appearedEvents.Count == Events.Length) { - break; - } - } - } - - async Task WaitForCheckpoints() { - bool firstCheckpointSet = false; - await using var subscription = StreamsClient.SubscribeToStream( - $"$persistentsubscription-$all::{Group}-checkpoint", FromStream.Start, - userCredentials: TestCredentials.Root); - await foreach (var message in subscription.Messages) { - if (message is not StreamMessage.Event(var resolvedEvent)) { - continue; - } - - if (!firstCheckpointSet) { - FirstCheckPoint = resolvedEvent.Event.Data.ParsePosition(); - firstCheckpointSet = true; - } else { - SecondCheckPoint = resolvedEvent.Event.Data.ParsePosition(); - return; - } - } - } - } - - protected override async Task When() { - foreach (var e in Events) { - await StreamsClient.AppendToStreamAsync("filtered-out-stream-" + Guid.NewGuid(), StreamState.Any, - new[] { e }); - } - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/when_writing_and_subscribing_to_normal_events_manual_nack.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/when_writing_and_subscribing_to_normal_events_manual_nack.cs deleted file mode 100644 index 72e0cfd00..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/when_writing_and_subscribing_to_normal_events_manual_nack.cs +++ /dev/null @@ -1,57 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll; - -public class when_writing_and_subscribing_to_normal_events_manual_nack - : IClassFixture { - private const string Group = nameof(Group); - private const int BufferCount = 10; - private const int EventWriteCount = BufferCount * 2; - - private readonly Fixture _fixture; - - public when_writing_and_subscribing_to_normal_events_manual_nack(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task Test() { - await _fixture.Subscription!.Messages.OfType() - .SelectAwait(async e => { - await _fixture.Subscription.Nack(PersistentSubscriptionNakEventAction.Park, "fail", e.ResolvedEvent); - return e; - }) - .Where(e => e.ResolvedEvent.OriginalStreamId.StartsWith("test-")) - .Take(_fixture.Events.Length) - .ToArrayAsync() - .AsTask() - .WithTimeout(); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(EventWriteCount).ToArray(); - } - - protected override async Task Given() { - await Client.CreateToAllAsync(Group, new(startFrom: Position.Start, resolveLinkTos: true), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToAll(Group, bufferSize: BufferCount, userCredentials: TestCredentials.Root); - } - - protected override async Task When() { - foreach (var e in Events) { - await StreamsClient.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); - } - } - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_max_one_client_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_max_one_client_obsolete.cs deleted file mode 100644 index 8f290088c..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_max_one_client_obsolete.cs +++ /dev/null @@ -1,47 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_max_one_client_obsolete - : IClassFixture { - const string Group = "startinbeginning1"; - const string Stream = nameof(connect_to_existing_with_max_one_client_obsolete); - readonly Fixture _fixture; - - public connect_to_existing_with_max_one_client_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_second_subscription_fails_to_connect() { - using var first = await _fixture.Client.SubscribeToStreamAsync( - Stream, - Group, - delegate { return Task.CompletedTask; }, - userCredentials: TestCredentials.Root - ).WithTimeout(); - - var ex = await Assert.ThrowsAsync( - async () => { - using var _ = await _fixture.Client.SubscribeToStreamAsync( - Stream, - Group, - delegate { return Task.CompletedTask; }, - userCredentials: TestCredentials.Root - ); - } - ).WithTimeout(); - - Assert.Equal(Stream, ex.StreamName); - Assert.Equal(Group, ex.GroupName); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => - Client.CreateToStreamAsync( - Stream, - Group, - new(maxSubscriberCount: 1), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_permissions_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_permissions_obsolete.cs deleted file mode 100644 index 70ada6f17..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_permissions_obsolete.cs +++ /dev/null @@ -1,39 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_permissions_obsolete - : IClassFixture { - const string Stream = nameof(connect_to_existing_with_permissions_obsolete); - - readonly Fixture _fixture; - - public connect_to_existing_with_permissions_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_succeeds() { - var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); - using var subscription = await _fixture.Client.SubscribeToStreamAsync( - Stream, - "agroupname17", - delegate { return Task.CompletedTask; }, - (s, reason, ex) => dropped.TrySetResult((reason, ex)), - TestCredentials.Root - ).WithTimeout(); - - Assert.NotNull(subscription); - - await Assert.ThrowsAsync(() => dropped.Task.WithTimeout()); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => - Client.CreateToStreamAsync( - Stream, - "agroupname17", - new(), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_beginning_and_events_in_it_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_beginning_and_events_in_it_obsolete.cs deleted file mode 100644 index c023db1f8..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_beginning_and_events_in_it_obsolete.cs +++ /dev/null @@ -1,65 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_beginning_and_events_in_it_obsolete - : IClassFixture { - const string Group = "startinbeginning1"; - - const string Stream = - nameof(connect_to_existing_with_start_from_beginning_and_events_in_it_obsolete); - - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_beginning_and_events_in_it_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_event_zero_as_its_first_event() { - var resolvedEvent = await _fixture.FirstEvent.WithTimeout(TimeSpan.FromSeconds(10)); - Assert.Equal(StreamPosition.Start, resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events[0].EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - public readonly EventData[] Events; - PersistentSubscription? _subscription; - - public Fixture() { - _firstEventSource = new(); - Events = CreateTestEvents(10).ToArray(); - } - - public Task FirstEvent => _firstEventSource.Task; - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: StreamPosition.Start), - userCredentials: TestCredentials.Root - ); - } - - protected override async Task When() => - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.TestUser1 - ); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_beginning_and_no_stream_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_beginning_and_no_stream_obsolete.cs deleted file mode 100644 index 037ec52e5..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_beginning_and_no_stream_obsolete.cs +++ /dev/null @@ -1,65 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_beginning_and_no_stream_obsolete - : IClassFixture { - const string Group = "startinbeginning1"; - - const string Stream = - nameof(connect_to_existing_with_start_from_beginning_and_no_stream_obsolete); - - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_beginning_and_no_stream_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_event_zero_as_its_first_event() { - var firstEvent = await _fixture.FirstEvent.WithTimeout(TimeSpan.FromSeconds(10)); - Assert.Equal(StreamPosition.Start, firstEvent.Event.EventNumber); - Assert.Equal(_fixture.EventId, firstEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - public readonly EventData[] Events; - PersistentSubscription? _subscription; - - public Fixture() { - _firstEventSource = new(); - Events = CreateTestEvents().ToArray(); - } - - public Task FirstEvent => _firstEventSource.Task; - public Uuid EventId => Events.Single().EventId; - - protected override async Task Given() { - await Client.CreateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.TestUser1 - ); - } - - protected override Task When() => StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_not_set_and_events_in_it_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_not_set_and_events_in_it_obsolete.cs deleted file mode 100644 index f0bd49b06..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_not_set_and_events_in_it_obsolete.cs +++ /dev/null @@ -1,61 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_not_set_and_events_in_it_obsolete - : IClassFixture { - const string Group = "startinbeginning1"; - - const string Stream = - nameof(connect_to_existing_with_start_from_not_set_and_events_in_it_obsolete); - - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_not_set_and_events_in_it_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_no_events() => await Assert.ThrowsAsync(() => _fixture.FirstEvent.WithTimeout()); - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - public readonly EventData[] Events; - PersistentSubscription? _subscription; - - public Fixture() { - _firstEventSource = new(); - Events = CreateTestEvents(10).ToArray(); - } - - public Task FirstEvent => _firstEventSource.Task; - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - await Client.CreateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root - ); - } - - protected override async Task When() => - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.TestUser1 - ); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written_obsolete.cs deleted file mode 100644 index ea1987ceb..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written_obsolete.cs +++ /dev/null @@ -1,67 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written_obsolete - : IClassFixture { - const string Group = "startinbeginning1"; - const string Stream = nameof(connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written_obsolete); - - readonly Fixture _fixture; - - public - connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written_obsolete(Fixture fixture) => - _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_event() { - var resolvedEvent = await _fixture.FirstEvent.WithTimeout(); - Assert.Equal(new(10), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events.Last().EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - - public readonly EventData[] Events; - - PersistentSubscription? _subscription; - - public Fixture() { - _firstEventSource = new(); - Events = CreateTestEvents(11).ToArray(); - } - - public Task FirstEvent => _firstEventSource.Task; - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events.Take(10)); - await Client.CreateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.TestUser1 - ); - } - - protected override Task When() => StreamsClient.AppendToStreamAsync(Stream, new StreamRevision(9), Events.Skip(10)); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_obsolete.cs deleted file mode 100644 index b25765019..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_obsolete.cs +++ /dev/null @@ -1,60 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_obsolete - : IClassFixture { - const string Group = "startinbeginning1"; - - const string Stream = - nameof(connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_obsolete); - - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_no_events() => await Assert.ThrowsAsync(() => _fixture.FirstEvent.WithTimeout()); - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - public readonly EventData[] Events; - PersistentSubscription? _subscription; - - public Fixture() { - _firstEventSource = new(); - Events = CreateTestEvents(10).ToArray(); - } - - public Task FirstEvent => _firstEventSource.Task; - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: StreamPosition.End), - userCredentials: TestCredentials.Root - ); - } - - protected override async Task When() => - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.TestUser1 - ); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written_obsolete.cs deleted file mode 100644 index 9bc45141b..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written_obsolete.cs +++ /dev/null @@ -1,72 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class - connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written_obsolete - : IClassFixture< - connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written_obsolete - .Fixture> { - const string Group = "startinbeginning1"; - - const string Stream = - nameof( - connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written_obsolete - ); - - readonly Fixture _fixture; - - public - connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written_obsolete(Fixture fixture) => - _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_event() { - var resolvedEvent = await _fixture.FirstEvent.WithTimeout(); - Assert.Equal(new(10), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events.Last().EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - public readonly EventData[] Events; - PersistentSubscription? _subscription; - - public Fixture() { - _firstEventSource = new(); - Events = CreateTestEvents(11).ToArray(); - } - - public Task FirstEvent => _firstEventSource.Task; - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events.Take(10)); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: StreamPosition.End), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.TestUser1 - ); - } - - protected override Task When() => StreamsClient.AppendToStreamAsync(Stream, new StreamRevision(9), Events.Skip(10)); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_two_and_no_stream_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_two_and_no_stream_obsolete.cs deleted file mode 100644 index 09d6e4f21..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_two_and_no_stream_obsolete.cs +++ /dev/null @@ -1,65 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_two_and_no_stream_obsolete - : IClassFixture { - const string Group = "startinbeginning1"; - - const string Stream = - nameof(connect_to_existing_with_start_from_two_and_no_stream_obsolete); - - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_two_and_no_stream_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_event_two_as_its_first_event() { - var resolvedEvent = await _fixture.FirstEvent.WithTimeout(TimeSpan.FromSeconds(10)); - Assert.Equal(new(2), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - public readonly EventData[] Events; - PersistentSubscription? _subscription; - - public Fixture() { - _firstEventSource = new(); - Events = CreateTestEvents(3).ToArray(); - } - - public Task FirstEvent => _firstEventSource.Task; - public Uuid EventId => Events.Last().EventId; - - protected override async Task Given() { - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: new StreamPosition(2)), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.TestUser1 - ); - } - - protected override Task When() => StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_x_set_and_events_in_it_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_x_set_and_events_in_it_obsolete.cs deleted file mode 100644 index c74f8b45f..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_x_set_and_events_in_it_obsolete.cs +++ /dev/null @@ -1,65 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_x_set_and_events_in_it_obsolete - : IClassFixture { - const string Group = "startinx2"; - - const string Stream = - nameof(connect_to_existing_with_start_from_x_set_and_events_in_it_obsolete); - - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_x_set_and_events_in_it_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_event() { - var resolvedEvent = await _fixture.FirstEvent.WithTimeout(); - Assert.Equal(new(4), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events.Skip(4).First().EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - public readonly EventData[] Events; - PersistentSubscription? _subscription; - - public Fixture() { - _firstEventSource = new(); - Events = CreateTestEvents(10).ToArray(); - } - - public Task FirstEvent => _firstEventSource.Task; - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events.Take(10)); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: new StreamPosition(4)), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.TestUser1 - ); - } - - protected override Task When() => StreamsClient.AppendToStreamAsync(Stream, new StreamRevision(9), Events.Skip(10)); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written_obsolete.cs deleted file mode 100644 index a3fae30a1..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written_obsolete.cs +++ /dev/null @@ -1,68 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written_obsolete - : IClassFixture< - connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written_obsolete. - Fixture> { - const string Group = "startinbeginning1"; - - const string Stream = - nameof(connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written_obsolete - ); - - readonly Fixture _fixture; - - public connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_event() { - var resolvedEvent = await _fixture.FirstEvent.WithTimeout(); - Assert.Equal(new(10), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events.Last().EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - public readonly EventData[] Events; - PersistentSubscription? _subscription; - - public Fixture() { - _firstEventSource = new(); - Events = CreateTestEvents(11).ToArray(); - } - - public Task FirstEvent => _firstEventSource.Task; - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events.Take(10)); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: new StreamPosition(10)), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.TestUser1 - ); - } - - protected override Task When() => StreamsClient.AppendToStreamAsync(Stream, new StreamRevision(9), Events.Skip(10)); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written_obsolete.cs deleted file mode 100644 index 59198a660..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written_obsolete.cs +++ /dev/null @@ -1,72 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class - connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written_obsolete - : IClassFixture< - connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written_obsolete - .Fixture> { - const string Group = "startinbeginning1"; - - const string Stream = - nameof( - connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written_obsolete - ); - - readonly Fixture _fixture; - - public - connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written_obsolete(Fixture fixture) => - _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_event() { - var resolvedEvent = await _fixture.FirstEvent.WithTimeout(); - Assert.Equal(new(11), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events.Last().EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - public readonly EventData[] Events; - PersistentSubscription? _subscription; - - public Fixture() { - _firstEventSource = new(); - Events = CreateTestEvents(12).ToArray(); - } - - public Task FirstEvent => _firstEventSource.Task; - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events.Take(11)); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: new StreamPosition(11)), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.TestUser1 - ); - } - - protected override Task When() => StreamsClient.AppendToStreamAsync(Stream, new StreamRevision(10), Events.Skip(11)); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_without_permissions_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_without_permissions_obsolete.cs deleted file mode 100644 index 25942cd05..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_existing_without_permissions_obsolete.cs +++ /dev/null @@ -1,35 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_existing_without_permissions_obsolete - : IClassFixture { - const string Stream = "$" + nameof(connect_to_existing_without_permissions_obsolete); - readonly Fixture _fixture; - public connect_to_existing_without_permissions_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public Task throws_access_denied() => - Assert.ThrowsAsync( - async () => { - using var _ = await _fixture.Client.SubscribeToStreamAsync( - Stream, - "agroupname55", - delegate { return Task.CompletedTask; } - ); - } - ).WithTimeout(); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => - Client.CreateToStreamAsync( - Stream, - "agroupname55", - new(), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_non_existing_with_permissions_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_non_existing_with_permissions_obsolete.cs deleted file mode 100644 index dd9d74900..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_to_non_existing_with_permissions_obsolete.cs +++ /dev/null @@ -1,34 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_to_non_existing_with_permissions_obsolete - : IClassFixture { - const string Stream = nameof(connect_to_non_existing_with_permissions_obsolete); - const string Group = "foo"; - - readonly Fixture _fixture; - - public connect_to_non_existing_with_permissions_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task throws_persistent_subscription_not_found() { - var ex = await Assert.ThrowsAsync( - async () => { - using var _ = await _fixture.Client.SubscribeToStreamAsync( - Stream, - Group, - delegate { return Task.CompletedTask; }, - userCredentials: TestCredentials.Root - ); - } - ).WithTimeout(); - - Assert.Equal(Stream, ex.StreamName); - Assert.Equal(Group, ex.GroupName); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_with_retries_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_with_retries_obsolete.cs deleted file mode 100644 index d31fcc961..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connect_with_retries_obsolete.cs +++ /dev/null @@ -1,70 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class connect_with_retries_obsolete : IClassFixture { - const string Group = "retries"; - const string Stream = nameof(connect_with_retries_obsolete); - - readonly Fixture _fixture; - - public connect_with_retries_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task events_are_retried_until_success() => Assert.Equal(5, await _fixture.RetryCount.WithTimeout()); - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _retryCountSource; - - public readonly EventData[] Events; - - PersistentSubscription? _subscription; - - public Fixture() { - _retryCountSource = new(); - - Events = CreateTestEvents().ToArray(); - } - - public Task RetryCount => _retryCountSource.Task; - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: StreamPosition.Start), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, r, ct) => { - if (r > 4) { - _retryCountSource.TrySetResult(r.Value); - await subscription.Ack(e.Event.EventId); - } - else { - await subscription.Nack( - PersistentSubscriptionNakEventAction.Retry, - "Not yet tried enough times", - e - ); - } - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _retryCountSource.TrySetException(ex!); - }, - TestCredentials.TestUser1 - ); - } - - protected override Task When() => StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connecting_to_a_persistent_subscription_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connecting_to_a_persistent_subscription_obsolete.cs deleted file mode 100644 index af09f9867..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/connecting_to_a_persistent_subscription_obsolete.cs +++ /dev/null @@ -1,72 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class - connecting_to_a_persistent_subscription_obsolete - : IClassFixture< - connecting_to_a_persistent_subscription_obsolete - .Fixture> { - const string Group = "startinbeginning1"; - - const string Stream = - nameof( - connecting_to_a_persistent_subscription_obsolete - ); - - readonly Fixture _fixture; - - public - connecting_to_a_persistent_subscription_obsolete(Fixture fixture) => - _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_event() { - var resolvedEvent = await _fixture.FirstEvent.WithTimeout(); - Assert.Equal(new(11), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events.Last().EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _firstEventSource; - public readonly EventData[] Events; - PersistentSubscription? _subscription; - - public Fixture() { - _firstEventSource = new(); - Events = CreateTestEvents(12).ToArray(); - } - - public Task FirstEvent => _firstEventSource.Task; - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events.Take(11)); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: new StreamPosition(11)), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, r, ct) => { - _firstEventSource.TrySetResult(e); - await subscription.Ack(e); - }, - (subscription, reason, ex) => { - if (reason != SubscriptionDroppedReason.Disposed) - _firstEventSource.TrySetException(ex!); - }, - TestCredentials.TestUser1 - ); - } - - protected override Task When() => StreamsClient.AppendToStreamAsync(Stream, new StreamRevision(10), Events.Skip(11)); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/deleting_existing_with_subscriber_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/deleting_existing_with_subscriber_obsolete.cs deleted file mode 100644 index d684c76af..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/deleting_existing_with_subscriber_obsolete.cs +++ /dev/null @@ -1,67 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class deleting_existing_with_subscriber_obsolete - : IClassFixture { - const string Stream = nameof(deleting_existing_with_subscriber_obsolete); - readonly Fixture _fixture; - - public deleting_existing_with_subscriber_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_is_dropped() { - var (reason, exception) = await _fixture.Dropped.WithTimeout(); - Assert.Equal(SubscriptionDroppedReason.ServerError, reason); - var ex = Assert.IsType(exception); - - Assert.Equal(Stream, ex.StreamName); - Assert.Equal("groupname123", ex.GroupName); - } - - [Fact(Skip = "Isn't this how it should work?")] - public async Task the_subscription_is_dropped_with_not_found() { - var (reason, exception) = await _fixture.Dropped.WithTimeout(); - Assert.Equal(SubscriptionDroppedReason.ServerError, reason); - var ex = Assert.IsType(exception); - Assert.Equal(Stream, ex.StreamName); - Assert.Equal("groupname123", ex.GroupName); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource<(SubscriptionDroppedReason, Exception?)> _dropped; - PersistentSubscription? _subscription; - - public Fixture() => _dropped = new(); - - public Task<(SubscriptionDroppedReason, Exception?)> Dropped => _dropped.Task; - - protected override async Task Given() { - await Client.CreateToStreamAsync( - Stream, - "groupname123", - new(), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - "groupname123", - (_, _, _, _) => Task.CompletedTask, - (_, r, e) => _dropped.TrySetResult((r, e)), - TestCredentials.Root - ); - } - - protected override Task When() => - Client.DeleteToStreamAsync( - Stream, - "groupname123", - userCredentials: TestCredentials.Root - ); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/happy_case_catching_up_to_link_to_events_manual_ack_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/happy_case_catching_up_to_link_to_events_manual_ack_obsolete.cs deleted file mode 100644 index e69e88fb2..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/happy_case_catching_up_to_link_to_events_manual_ack_obsolete.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System.Text; - -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class happy_case_catching_up_to_link_to_events_manual_ack_obsolete - : IClassFixture { - const string Stream = nameof(happy_case_catching_up_to_link_to_events_manual_ack_obsolete); - const string Group = nameof(Group); - const int BufferCount = 10; - const int EventWriteCount = BufferCount * 2; - - readonly Fixture _fixture; - - public happy_case_catching_up_to_link_to_events_manual_ack_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task Test() => await _fixture.EventsReceived.WithTimeout(); - - public class Fixture : EventStoreClientFixture { - readonly EventData[] _events; - readonly TaskCompletionSource _eventsReceived; - int _eventReceivedCount; - - PersistentSubscription? _subscription; - - public Fixture() { - _events = CreateTestEvents(EventWriteCount) - .Select( - (e, i) => new EventData( - e.EventId, - SystemEventTypes.LinkTo, - Encoding.UTF8.GetBytes($"{i}@{Stream}"), - contentType: Constants.Metadata.ContentTypes.ApplicationOctetStream - ) - ) - .ToArray(); - - _eventsReceived = new(); - } - - public Task EventsReceived => _eventsReceived.Task; - - protected override async Task Given() { - foreach (var e in _events) - await StreamsClient.AppendToStreamAsync(Stream, StreamState.Any, new[] { e }); - - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: StreamPosition.Start, resolveLinkTos: true), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, retryCount, ct) => { - await subscription.Ack(e); - - if (Interlocked.Increment(ref _eventReceivedCount) == _events.Length) - _eventsReceived.TrySetResult(true); - }, - (s, r, e) => { - if (e != null) - _eventsReceived.TrySetException(e); - }, - bufferSize: BufferCount, - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() => Task.CompletedTask; - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/happy_case_catching_up_to_normal_events_manual_ack_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/happy_case_catching_up_to_normal_events_manual_ack_obsolete.cs deleted file mode 100644 index 6973087cc..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/happy_case_catching_up_to_normal_events_manual_ack_obsolete.cs +++ /dev/null @@ -1,67 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class happy_case_catching_up_to_normal_events_manual_ack_obsolete : IClassFixture { - const string Stream = nameof(happy_case_catching_up_to_normal_events_manual_ack_obsolete); - const string Group = nameof(Group); - const int BufferCount = 10; - const int EventWriteCount = BufferCount * 2; - - readonly Fixture _fixture; - - public happy_case_catching_up_to_normal_events_manual_ack_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task Test() => await _fixture.EventsReceived.WithTimeout(); - - public class Fixture : EventStoreClientFixture { - readonly EventData[] _events; - readonly TaskCompletionSource _eventsReceived; - int _eventReceivedCount; - - PersistentSubscription? _subscription; - - public Fixture() { - _events = CreateTestEvents(EventWriteCount).ToArray(); - _eventsReceived = new(); - } - - public Task EventsReceived => _eventsReceived.Task; - - protected override async Task Given() { - foreach (var e in _events) - await StreamsClient.AppendToStreamAsync(Stream, StreamState.Any, new[] { e }); - - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: StreamPosition.Start, resolveLinkTos: true), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, retryCount, ct) => { - await subscription.Ack(e); - - if (Interlocked.Increment(ref _eventReceivedCount) == _events.Length) - _eventsReceived.TrySetResult(true); - }, - (s, r, e) => { - if (e != null) - _eventsReceived.TrySetException(e); - }, - bufferSize: BufferCount, - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() => Task.CompletedTask; - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/happy_case_writing_and_subscribing_to_normal_events_manual_ack_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/happy_case_writing_and_subscribing_to_normal_events_manual_ack_obsolete.cs deleted file mode 100644 index af07bcb4c..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/happy_case_writing_and_subscribing_to_normal_events_manual_ack_obsolete.cs +++ /dev/null @@ -1,67 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class happy_case_writing_and_subscribing_to_normal_events_manual_ack_obsolete - : IClassFixture { - const string Stream = nameof(happy_case_writing_and_subscribing_to_normal_events_manual_ack_obsolete); - const string Group = nameof(Group); - const int BufferCount = 10; - const int EventWriteCount = BufferCount * 2; - - readonly Fixture _fixture; - - public happy_case_writing_and_subscribing_to_normal_events_manual_ack_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task Test() => await _fixture.EventsReceived.WithTimeout(); - - public class Fixture : EventStoreClientFixture { - readonly EventData[] _events; - readonly TaskCompletionSource _eventsReceived; - int _eventReceivedCount; - - PersistentSubscription? _subscription; - - public Fixture() { - _events = CreateTestEvents(EventWriteCount).ToArray(); - _eventsReceived = new(); - } - - public Task EventsReceived => _eventsReceived.Task; - - protected override async Task Given() { - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: StreamPosition.End, resolveLinkTos: true), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, retryCount, ct) => { - await subscription.Ack(e); - if (Interlocked.Increment(ref _eventReceivedCount) == _events.Length) - _eventsReceived.TrySetResult(true); - }, - (s, r, e) => { - if (e != null) - _eventsReceived.TrySetException(e); - }, - bufferSize: BufferCount, - userCredentials: TestCredentials.Root - ); - } - - protected override async Task When() { - foreach (var e in _events) - await StreamsClient.AppendToStreamAsync(Stream, StreamState.Any, new[] { e }); - } - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/update_existing_with_check_point_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/update_existing_with_check_point_obsolete.cs deleted file mode 100644 index f5922c746..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/update_existing_with_check_point_obsolete.cs +++ /dev/null @@ -1,124 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class update_existing_with_check_point_obsolete - : IClassFixture { - const string Stream = nameof(update_existing_with_check_point_obsolete); - const string Group = "existing-with-check-point"; - readonly Fixture _fixture; - - public update_existing_with_check_point_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task resumes_from_check_point() { - var resumedEvent = await _fixture.Resumed.WithTimeout(TimeSpan.FromSeconds(10)); - Assert.Equal(_fixture.CheckPoint.Next(), resumedEvent.Event.EventNumber); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource _appeared; - readonly List _appearedEvents; - - readonly TaskCompletionSource<(SubscriptionDroppedReason, Exception?)> _droppedSource; - readonly EventData[] _events; - readonly TaskCompletionSource _resumedSource; - PersistentSubscription? _firstSubscription; - PersistentSubscription? _secondSubscription; - - public Fixture() { - _droppedSource = new(); - _resumedSource = new(); - _appeared = new(); - _appearedEvents = new(); - _events = CreateTestEvents(5).ToArray(); - } - - public Task Resumed => _resumedSource.Task; - public StreamPosition CheckPoint { get; private set; } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, _events); - - await Client.CreateToStreamAsync( - Stream, - Group, - new( - checkPointLowerBound: 5, - checkPointAfter: TimeSpan.FromSeconds(1), - startFrom: StreamPosition.Start - ), - userCredentials: TestCredentials.Root - ); - - var checkPointStream = $"$persistentsubscription-{Stream}::{Group}-checkpoint"; - - _firstSubscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (s, e, _, _) => { - _appearedEvents.Add(e); - await s.Ack(e); - - if (_appearedEvents.Count == _events.Length) - _appeared.TrySetResult(true); - }, - (_, reason, ex) => _droppedSource.TrySetResult((reason, ex)), - TestCredentials.Root - ); - - await Task.WhenAll(_appeared.Task.WithTimeout(), Checkpointed()); - - return; - - async Task Checkpointed() { - await using var subscription = StreamsClient.SubscribeToStream(checkPointStream, FromStream.Start, - userCredentials: TestCredentials.Root); - await foreach (var message in subscription.Messages) { - if (message is not StreamMessage.Event(var resolvedEvent)) { - continue; - } - CheckPoint = resolvedEvent.Event.Data.ParseStreamPosition(); - return; - } - - throw new InvalidOperationException(); - } - } - - protected override async Task When() { - // Force restart of the subscription - await Client.UpdateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root - ); - - await _droppedSource.Task.WithTimeout(); - - _secondSubscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (s, e, _, _) => { - _resumedSource.TrySetResult(e); - await s.Ack(e); - }, - (_, reason, ex) => { - if (ex is not null) - _resumedSource.TrySetException(ex); - else - _resumedSource.TrySetResult(default); - }, - TestCredentials.Root - ); - - await StreamsClient.AppendToStreamAsync(Stream, StreamState.Any, CreateTestEvents(1)); - } - - public override Task DisposeAsync() { - _firstSubscription?.Dispose(); - _secondSubscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/update_existing_with_subscribers_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/update_existing_with_subscribers_obsolete.cs deleted file mode 100644 index 7ff215206..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/update_existing_with_subscribers_obsolete.cs +++ /dev/null @@ -1,61 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class update_existing_with_subscribers_obsolete - : IClassFixture { - const string Stream = nameof(update_existing_with_subscribers_obsolete); - const string Group = "existing"; - readonly Fixture _fixture; - - public update_existing_with_subscribers_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task existing_subscriptions_are_dropped() { - var (reason, exception) = await _fixture.Dropped.WithTimeout(TimeSpan.FromSeconds(10)); - Assert.Equal(SubscriptionDroppedReason.ServerError, reason); - var ex = Assert.IsType(exception); - - Assert.Equal(Stream, ex.StreamName); - Assert.Equal(Group, ex.GroupName); - } - - public class Fixture : EventStoreClientFixture { - readonly TaskCompletionSource<(SubscriptionDroppedReason, Exception?)> _droppedSource; - PersistentSubscription? _subscription; - - public Fixture() => _droppedSource = new(); - - public Task<(SubscriptionDroppedReason, Exception?)> Dropped => _droppedSource.Task; - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, CreateTestEvents()); - await Client.CreateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - delegate { return Task.CompletedTask; }, - (_, reason, ex) => _droppedSource.TrySetResult((reason, ex)), - TestCredentials.Root - ); - } - - protected override Task When() => - Client.UpdateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root - ); - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/when_writing_and_subscribing_to_normal_events_manual_nack_obsolete.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/when_writing_and_subscribing_to_normal_events_manual_nack_obsolete.cs deleted file mode 100644 index 96a2d0af0..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/when_writing_and_subscribing_to_normal_events_manual_nack_obsolete.cs +++ /dev/null @@ -1,70 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class when_writing_and_subscribing_to_normal_events_manual_nack_obsolete - : IClassFixture { - const string Stream = nameof(when_writing_and_subscribing_to_normal_events_manual_nack_obsolete); - const string Group = nameof(Group); - const int BufferCount = 10; - const int EventWriteCount = BufferCount * 2; - - readonly Fixture _fixture; - - public when_writing_and_subscribing_to_normal_events_manual_nack_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task Test() => await _fixture.EventsReceived.WithTimeout(); - - public class Fixture : EventStoreClientFixture { - readonly EventData[] _events; - readonly TaskCompletionSource _eventsReceived; - int _eventReceivedCount; - - PersistentSubscription? _subscription; - - public Fixture() { - _events = CreateTestEvents(EventWriteCount) - .ToArray(); - - _eventsReceived = new(); - } - - public Task EventsReceived => _eventsReceived.Task; - - protected override async Task Given() { - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: StreamPosition.Start, resolveLinkTos: true), - userCredentials: TestCredentials.Root - ); - - _subscription = await Client.SubscribeToStreamAsync( - Stream, - Group, - async (subscription, e, retryCount, ct) => { - await subscription.Nack(PersistentSubscriptionNakEventAction.Park, "fail", e); - - if (Interlocked.Increment(ref _eventReceivedCount) == _events.Length) - _eventsReceived.TrySetResult(true); - }, - (s, r, e) => { - if (e != null) - _eventsReceived.TrySetException(e); - }, - bufferSize: BufferCount, - userCredentials: TestCredentials.Root - ); - } - - protected override async Task When() { - foreach (var e in _events) - await StreamsClient.AppendToStreamAsync(Stream, StreamState.Any, new[] { e }); - } - - public override Task DisposeAsync() { - _subscription?.Dispose(); - return base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/can_create_duplicate_name_on_different_streams.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/can_create_duplicate_name_on_different_streams.cs deleted file mode 100644 index cb9af1bd6..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/can_create_duplicate_name_on_different_streams.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class can_create_duplicate_name_on_different_streams - : IClassFixture { - const string Stream = - nameof(can_create_duplicate_name_on_different_streams); - - readonly Fixture _fixture; - - public can_create_duplicate_name_on_different_streams(Fixture fixture) => _fixture = fixture; - - [Fact] - public Task the_completion_succeeds() => - _fixture.Client.CreateToStreamAsync( - "someother" + Stream, - "group3211", - new(), - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - - protected override Task When() => - Client.CreateToStreamAsync( - Stream, - "group3211", - new(), - userCredentials: TestCredentials.Root - ); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_max_one_client.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_max_one_client.cs deleted file mode 100644 index eb5e442ae..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_max_one_client.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_existing_with_max_one_client - : IClassFixture { - private const string Group = "startinbeginning1"; - private const string Stream = nameof(connect_to_existing_with_max_one_client); - private readonly Fixture _fixture; - - public connect_to_existing_with_max_one_client(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_second_subscription_fails_to_connect() { - var ex = await Assert.ThrowsAsync( - () => Task.WhenAll(Subscribe().WithTimeout(), Subscribe().WithTimeout())); - - Assert.Equal(Stream, ex.StreamName); - Assert.Equal(Group, ex.GroupName); - return; - - async Task Subscribe() { - await using var subscription = - _fixture.Client.SubscribeToStream(Stream, Group, userCredentials: TestCredentials.Root); - await subscription.Messages.AnyAsync(); - } - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Client.CreateToStreamAsync(Stream, Group, new(maxSubscriberCount: 1), - userCredentials: TestCredentials.Root); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_permissions.cs deleted file mode 100644 index 70f4b51f0..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_permissions.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_existing_with_permissions - : IClassFixture { - private const string Stream = nameof(connect_to_existing_with_permissions); - - private readonly Fixture _fixture; - - public connect_to_existing_with_permissions(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_succeeds() { - await using var subscription = - _fixture.Client.SubscribeToStream(Stream, "agroupname17", userCredentials: TestCredentials.Root); - - Assert.True(await subscription.Messages - .FirstAsync().AsTask().WithTimeout() is PersistentSubscriptionMessage.SubscriptionConfirmation); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => - Client.CreateToStreamAsync(Stream, "agroupname17", new(), userCredentials: TestCredentials.Root); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_beginning_and_events_in_it.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_beginning_and_events_in_it.cs deleted file mode 100644 index 2c0f5225e..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_beginning_and_events_in_it.cs +++ /dev/null @@ -1,51 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_existing_with_start_from_beginning_and_events_in_it - : IClassFixture { - private const string Group = "startinbeginning1"; - private const string Stream = nameof(connect_to_existing_with_start_from_beginning_and_events_in_it); - - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_beginning_and_events_in_it(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_event_zero_as_its_first_event() { - var resolvedEvent = await _fixture.Subscription!.Messages.OfType() - .Select(e => e.ResolvedEvent) - .FirstOrDefaultAsync().AsTask().WithTimeout(); - - Assert.Equal(StreamPosition.Start, resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events[0].EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(10).ToArray(); - } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - await Client.CreateToStreamAsync(Stream, Group, new(startFrom: StreamPosition.Start), - userCredentials: TestCredentials.Root); - } - - protected override Task When() { - Subscription = Client.SubscribeToStream(Stream, Group, userCredentials: TestCredentials.TestUser1); - - return Task.CompletedTask; - } - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_beginning_and_no_stream.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_beginning_and_no_stream.cs deleted file mode 100644 index a6e9cb26b..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_beginning_and_no_stream.cs +++ /dev/null @@ -1,51 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_existing_with_start_from_beginning_and_no_stream - : IClassFixture { - private const string Group = "startinbeginning1"; - private const string Stream = nameof(connect_to_existing_with_start_from_beginning_and_no_stream); - - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_beginning_and_no_stream(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_event_zero_as_its_first_event() { - var resolvedEvent = await _fixture.Subscription!.Messages.OfType() - .Select(e => e.ResolvedEvent) - .FirstOrDefaultAsync().AsTask().WithTimeout(); - - Assert.Equal(StreamPosition.Start, resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents().ToArray(); - } - - public Uuid EventId => Events.Single().EventId; - - protected override async Task Given() { - await Client.CreateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToStream(Stream, Group, userCredentials: TestCredentials.TestUser1); - } - - protected override Task When() => StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_not_set_and_events_in_it.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_not_set_and_events_in_it.cs deleted file mode 100644 index cef6a28a7..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_not_set_and_events_in_it.cs +++ /dev/null @@ -1,52 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -[Obsolete] -public class connect_to_existing_with_start_from_not_set_and_events_in_it - : IClassFixture { - private const string Group = "startinbeginning1"; - - private const string Stream = nameof(connect_to_existing_with_start_from_not_set_and_events_in_it); - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_not_set_and_events_in_it(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_no_events() => - await Assert.ThrowsAsync( - () => _fixture.Subscription!.Messages.AnyAsync(message => message is PersistentSubscriptionMessage.Event) - .AsTask().WithTimeout(TimeSpan.FromMilliseconds(250))); - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(10).ToArray(); - } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - await Client.CreateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() { - Subscription = Client.SubscribeToStream( - Stream, - Group, - userCredentials: TestCredentials.TestUser1); - return Task.CompletedTask; - } - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written.cs deleted file mode 100644 index 08a2172d4..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written.cs +++ /dev/null @@ -1,58 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written - : IClassFixture { - private const string Group = "startinbeginning1"; - - private const string Stream = - nameof(connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written); - - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written(Fixture fixture) => - _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_event() { - var resolvedEvent = await _fixture.Subscription!.Messages.OfType() - .Select(e => e.ResolvedEvent) - .FirstOrDefaultAsync().AsTask().WithTimeout(); - - Assert.Equal(new(10), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events.Last().EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(11).ToArray(); - } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events.Take(10)); - await Client.CreateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root - ); - - Subscription = Client.SubscribeToStream( - Stream, - Group, - userCredentials: TestCredentials.TestUser1); - } - - protected override Task When() => - StreamsClient.AppendToStreamAsync(Stream, new StreamRevision(9), Events.Skip(10)); - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it.cs deleted file mode 100644 index f2bf5e807..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it.cs +++ /dev/null @@ -1,53 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_existing_with_start_from_set_to_end_position_and_events_in_it - : IClassFixture { - private const string Group = "startinbeginning1"; - private const string Stream = nameof(connect_to_existing_with_start_from_set_to_end_position_and_events_in_it); - - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_set_to_end_position_and_events_in_it(Fixture fixture) => - _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_no_events() => - await Assert.ThrowsAsync( - () => _fixture.Subscription!.Messages.AnyAsync(message => message is PersistentSubscriptionMessage.Event) - .AsTask().WithTimeout(TimeSpan.FromMilliseconds(250))); - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(10).ToArray(); - } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: StreamPosition.End), - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() { - Subscription = Client.SubscribeToStream( - Stream, - Group, - userCredentials: TestCredentials.TestUser1); - return Task.CompletedTask; - } - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written.cs deleted file mode 100644 index 2e7b8a4c1..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written.cs +++ /dev/null @@ -1,57 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written - : IClassFixture { - private const string Group = "startinbeginning1"; - - private const string Stream = - nameof(connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written); - - private readonly Fixture _fixture; - - public - connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written(Fixture fixture) => - _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_event() { - var resolvedEvent = await _fixture.Subscription!.Messages.OfType() - .Select(e => e.ResolvedEvent) - .FirstOrDefaultAsync().AsTask().WithTimeout(); - - Assert.Equal(new(10), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events.Last().EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(11).ToArray(); - } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events.Take(10)); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: StreamPosition.End), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToStream(Stream, Group, userCredentials: TestCredentials.TestUser1); - } - - protected override Task When() => - StreamsClient.AppendToStreamAsync(Stream, new StreamRevision(9), Events.Skip(10)); - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_two_and_no_stream.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_two_and_no_stream.cs deleted file mode 100644 index 0199eaa3b..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_two_and_no_stream.cs +++ /dev/null @@ -1,55 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_existing_with_start_from_two_and_no_stream - : IClassFixture { - private const string Group = "startinbeginning1"; - private const string Stream = nameof(connect_to_existing_with_start_from_two_and_no_stream); - - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_two_and_no_stream(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_event_two_as_its_first_event() { - var resolvedEvent = await _fixture.Subscription!.Messages.OfType() - .Select(e => e.ResolvedEvent) - .FirstOrDefaultAsync().AsTask().WithTimeout(); - - Assert.Equal(new(2), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(3).ToArray(); - } - - public Uuid EventId => Events.Last().EventId; - - protected override async Task Given() { - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: new StreamPosition(2)), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToStream( - Stream, - Group, - userCredentials: TestCredentials.TestUser1); - } - - protected override Task When() => StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_x_set_and_events_in_it.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_x_set_and_events_in_it.cs deleted file mode 100644 index 3a7edafba..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_x_set_and_events_in_it.cs +++ /dev/null @@ -1,55 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_existing_with_start_from_x_set_and_events_in_it - : IClassFixture { - private const string Group = "startinx2"; - private const string Stream = nameof(connect_to_existing_with_start_from_x_set_and_events_in_it); - - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_x_set_and_events_in_it(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_event() { - var resolvedEvent = await _fixture.Subscription!.Messages - .OfType() - .Select(e => e.ResolvedEvent) - .FirstOrDefaultAsync().AsTask().WithTimeout(); - Assert.Equal(new(4), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events.Skip(4).First().EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(10).ToArray(); - } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events.Take(10)); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: new StreamPosition(4)), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToStream( - Stream, - Group, - userCredentials: TestCredentials.TestUser1); - } - - protected override Task When() => - StreamsClient.AppendToStreamAsync(Stream, new StreamRevision(9), Events.Skip(10)); - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written.cs deleted file mode 100644 index 276bae9aa..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written.cs +++ /dev/null @@ -1,54 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written - : IClassFixture { - private const string Group = "startinbeginning1"; - private const string Stream = nameof(connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written); - private readonly Fixture _fixture; - - public connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written(Fixture fixture) => - _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_event() { - var resolvedEvent = await _fixture.Subscription!.Messages.OfType() - .Select(e => e.ResolvedEvent) - .FirstOrDefaultAsync().AsTask().WithTimeout(); - Assert.Equal(new(10), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events.Last().EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(11).ToArray(); - } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events.Take(10)); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: new StreamPosition(10)), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToStream( - Stream, - Group, - userCredentials: TestCredentials.TestUser1); - } - - protected override Task When() => - StreamsClient.AppendToStreamAsync(Stream, new StreamRevision(9), Events.Skip(10)); - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written.cs deleted file mode 100644 index f4b249372..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written.cs +++ /dev/null @@ -1,58 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written : - IClassFixture { - private const string Group = "startinbeginning1"; - private const string Stream = - nameof(connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written); - - private readonly Fixture _fixture; - - public - connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written(Fixture fixture) => - _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_event() { - var resolvedEvent = await _fixture.Subscription!.Messages.OfType() - .Select(e => e.ResolvedEvent) - .FirstOrDefaultAsync().AsTask().WithTimeout(); - Assert.Equal(new(11), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events.Last().EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(12).ToArray(); - } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events.Take(11)); - await Client.CreateToStreamAsync( - Stream, - Group, - new(startFrom: new StreamPosition(11)), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToStream( - Stream, - Group, - userCredentials: TestCredentials.TestUser1); - } - - protected override Task When() => - StreamsClient.AppendToStreamAsync(Stream, new StreamRevision(10), Events.Skip(11)); - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_without_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_without_permissions.cs deleted file mode 100644 index 756de2519..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_existing_without_permissions.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_existing_without_permissions : IClassFixture { - private const string Stream = $"${nameof(connect_to_existing_without_permissions)}"; - private readonly Fixture _fixture; - public connect_to_existing_without_permissions(Fixture fixture) => _fixture = fixture; - - [Fact] - public Task throws_access_denied() => - Assert.ThrowsAsync( - async () => { - await using var subscription = _fixture.Client.SubscribeToStream(Stream, "agroupname55"); - await subscription.Messages.AnyAsync(); - }).WithTimeout(); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => - Client.CreateToStreamAsync( - Stream, - "agroupname55", - new(), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_non_existing_with_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_non_existing_with_permissions.cs deleted file mode 100644 index 3e13c3983..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_to_non_existing_with_permissions.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_to_non_existing_with_permissions : IClassFixture { - private const string Stream = nameof(connect_to_non_existing_with_permissions); - private const string Group = "foo"; - - private readonly Fixture _fixture; - - public connect_to_non_existing_with_permissions(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task throws_persistent_subscription_not_found() { - await using var subscription = _fixture.Client.SubscribeToStream(Stream, Group, userCredentials: TestCredentials.Root); - Assert.True(await subscription.Messages.OfType() - .AnyAsync() - .AsTask() - .WithTimeout()); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_with_retries.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_with_retries.cs deleted file mode 100644 index 89995fedf..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connect_with_retries.cs +++ /dev/null @@ -1,60 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connect_with_retries : IClassFixture { - private const string Group = "retries"; - private const string Stream = nameof(connect_with_retries); - - private readonly Fixture _fixture; - - public connect_with_retries(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task events_are_retried_until_success() { - var retryCount = await _fixture.Subscription!.Messages.OfType() - .SelectAwait(async e => { - if (e.RetryCount > 4) { - await _fixture.Subscription.Ack(e.ResolvedEvent); - } else { - await _fixture.Subscription.Nack(PersistentSubscriptionNakEventAction.Retry, - "Not yet tried enough times", e.ResolvedEvent); - } - - return e.RetryCount; - }) - .Where(retryCount => retryCount > 4) - .FirstOrDefaultAsync() - .AsTask() - .WithTimeout(); - - Assert.Equal(5, retryCount); - } - - public class Fixture : EventStoreClientFixture { - - public readonly EventData[] Events; - - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents().ToArray(); - } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - await Client.CreateToStreamAsync(Stream, Group, new(startFrom: StreamPosition.Start), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToStream(Stream, Group, userCredentials: TestCredentials.TestUser1); - } - - protected override Task When() => StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events); - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connecting_to_a_persistent_subscription.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connecting_to_a_persistent_subscription.cs deleted file mode 100644 index a9dbb4b59..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/connecting_to_a_persistent_subscription.cs +++ /dev/null @@ -1,47 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class connecting_to_a_persistent_subscription : IClassFixture { - private const string Group = "startinbeginning1"; - private const string Stream = nameof(connecting_to_a_persistent_subscription); - - private readonly Fixture _fixture; - - public connecting_to_a_persistent_subscription(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_gets_the_written_event_as_its_first_event() { - var resolvedEvent = await _fixture.Subscription!.Messages.OfType() - .Select(e => e.ResolvedEvent) - .FirstOrDefaultAsync().AsTask().WithTimeout(); - Assert.Equal(new(11), resolvedEvent.Event.EventNumber); - Assert.Equal(_fixture.Events.Last().EventId, resolvedEvent.Event.EventId); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(12).ToArray(); - } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, Events.Take(11)); - await Client.CreateToStreamAsync(Stream, Group, new(startFrom: new StreamPosition(11)), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToStream(Stream, Group, userCredentials: TestCredentials.TestUser1); - } - - protected override Task When() => - StreamsClient.AppendToStreamAsync(Stream, new StreamRevision(10), Events.Skip(11)); - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_after_deleting_the_same.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_after_deleting_the_same.cs deleted file mode 100644 index 3e8e0a6c5..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_after_deleting_the_same.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class create_after_deleting_the_same - : IClassFixture { - const string Stream = nameof(create_after_deleting_the_same); - readonly Fixture _fixture; - - public create_after_deleting_the_same(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_completion_succeeds() => - await _fixture.Client.CreateToStreamAsync( - Stream, - "existing", - new(), - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - - protected override async Task When() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.Any, CreateTestEvents()); - await Client.CreateToStreamAsync( - Stream, - "existing", - new(), - userCredentials: TestCredentials.Root - ); - - await Client.DeleteToStreamAsync( - Stream, - "existing", - userCredentials: TestCredentials.Root - ); - } - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_duplicate.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_duplicate.cs deleted file mode 100644 index c67748a7a..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_duplicate.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Grpc.Core; - -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class create_duplicate - : IClassFixture { - const string Stream = nameof(create_duplicate); - readonly Fixture _fixture; - - public create_duplicate(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_completion_fails() { - var ex = await Assert.ThrowsAsync( - () => _fixture.Client.CreateToStreamAsync( - Stream, - "group32", - new(), - userCredentials: TestCredentials.Root - ) - ); - - Assert.Equal(StatusCode.AlreadyExists, ex.StatusCode); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - - protected override Task When() => - Client.CreateToStreamAsync( - Stream, - "group32", - new(), - userCredentials: TestCredentials.Root - ); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_on_existing_stream.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_on_existing_stream.cs deleted file mode 100644 index 6ad81a6db..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_on_existing_stream.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class create_on_existing_stream - : IClassFixture { - const string Stream = nameof(create_on_existing_stream); - readonly Fixture _fixture; - - public create_on_existing_stream(Fixture fixture) => _fixture = fixture; - - [Fact] - public Task the_completion_succeeds() => - _fixture.Client.CreateToStreamAsync( - Stream, - "existing", - new(), - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - - protected override async Task When() => await StreamsClient.AppendToStreamAsync(Stream, StreamState.Any, CreateTestEvents()); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_on_non_existing_stream.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_on_non_existing_stream.cs deleted file mode 100644 index f0d7e0fba..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_on_non_existing_stream.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class create_on_non_existing_stream - : IClassFixture { - const string Stream = nameof(create_on_non_existing_stream); - readonly Fixture _fixture; - - public create_on_non_existing_stream(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_completion_succeeds() => - await _fixture.Client.CreateToStreamAsync( - Stream, - "nonexistinggroup", - new(), - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_persistent_subscription_with_dont_timeout.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_persistent_subscription_with_dont_timeout.cs deleted file mode 100644 index d32c65b4c..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_persistent_subscription_with_dont_timeout.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class create_with_dont_timeout - : IClassFixture { - const string Stream = nameof(create_with_dont_timeout); - readonly Fixture _fixture; - - public create_with_dont_timeout(Fixture fixture) => _fixture = fixture; - - [Fact] - public Task the_subscription_is_created_without_error() => - _fixture.Client.CreateToStreamAsync( - Stream, - "dont-timeout", - new(messageTimeout: TimeSpan.Zero), - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_without_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_without_permissions.cs deleted file mode 100644 index d2838cf34..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/create_without_permissions.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class create_without_permissions - : IClassFixture { - const string Stream = nameof(create_without_permissions); - readonly Fixture _fixture; - - public create_without_permissions(Fixture fixture) => _fixture = fixture; - - [Fact] - public Task the_completion_fails_with_access_denied() => - Assert.ThrowsAsync( - () => - _fixture.Client.CreateToStreamAsync( - Stream, - "group57", - new() - ) - ); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_existing_with_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_existing_with_permissions.cs deleted file mode 100644 index 4d3a0f17d..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_existing_with_permissions.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class deleting_existing_with_permissions - : IClassFixture { - const string Stream = nameof(deleting_existing_with_permissions); - readonly Fixture _fixture; - - public deleting_existing_with_permissions(Fixture fixture) => _fixture = fixture; - - [Fact] - public Task the_delete_of_group_succeeds() => - _fixture.Client.DeleteToStreamAsync( - Stream, - "groupname123", - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - - protected override Task When() => - Client.CreateToStreamAsync( - Stream, - "groupname123", - new(), - userCredentials: TestCredentials.Root - ); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_existing_with_subscriber.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_existing_with_subscriber.cs deleted file mode 100644 index dae83cec6..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_existing_with_subscriber.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class deleting_existing_with_subscriber : IClassFixture { - private const string Stream = nameof(deleting_existing_with_subscriber); - private readonly Fixture _fixture; - - public deleting_existing_with_subscriber(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_subscription_is_dropped_with_not_found() { - await using var subscription = _fixture.Client.SubscribeToStream(Stream, "groupname123", userCredentials: TestCredentials.Root); - - Assert.True(await subscription.Messages.OfType().AnyAsync() - .AsTask() - .WithTimeout()); - } - - public class Fixture : EventStoreClientFixture { - protected override async Task Given() { - await Client.CreateToStreamAsync(Stream, "groupname123", new(), userCredentials: TestCredentials.Root); - } - - protected override Task When() => - Client.DeleteToStreamAsync(Stream, "groupname123", userCredentials: TestCredentials.Root); - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_nonexistent.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_nonexistent.cs deleted file mode 100644 index 58ad6bc13..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_nonexistent.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class deleting_nonexistent - : IClassFixture { - const string Stream = nameof(deleting_nonexistent); - readonly Fixture _fixture; - - public deleting_nonexistent(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_delete_fails_with_argument_exception() => - await Assert.ThrowsAsync( - () => _fixture.Client.DeleteToStreamAsync( - Stream, - Guid.NewGuid().ToString(), - userCredentials: TestCredentials.Root - ) - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_without_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_without_permissions.cs deleted file mode 100644 index 31dab0ba4..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/deleting_without_permissions.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class deleting_without_permissions - : IClassFixture { - const string Stream = nameof(deleting_without_permissions); - readonly Fixture _fixture; - - public deleting_without_permissions(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_delete_fails_with_access_denied() => - await Assert.ThrowsAsync( - () => _fixture.Client.DeleteToStreamAsync( - Stream, - Guid.NewGuid().ToString() - ) - ); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/get_info.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/get_info.cs deleted file mode 100644 index bec3c4118..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/get_info.cs +++ /dev/null @@ -1,198 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class get_info : IClassFixture { - private const string GroupName = nameof(get_info); - private const string StreamName = nameof(get_info); - - private static readonly PersistentSubscriptionSettings _settings = new( - true, - StreamPosition.Start, - true, - TimeSpan.FromSeconds(9), - 11, - 303, - 30, - 909, - TimeSpan.FromSeconds(1), - 1, - 1, - 500, - SystemConsumerStrategies.RoundRobin - ); - - private readonly Fixture _fixture; - - public get_info(Fixture fixture) => _fixture = fixture; - - public static IEnumerable AllowedUsers() { - yield return new object[] { TestCredentials.Root }; - yield return new object[] { TestCredentials.TestUser1 }; - } - - [Theory] - [MemberData(nameof(AllowedUsers))] - public async Task returns_expected_result(UserCredentials credentials) { - var result = await _fixture.Client.GetInfoToStreamAsync(StreamName, GroupName, userCredentials: credentials); - - Assert.Equal(StreamName, result.EventSource); - Assert.Equal(GroupName, result.GroupName); - Assert.NotNull(_settings.StartFrom); - Assert.True(result.Stats.TotalItems > 0); - Assert.True(result.Stats.OutstandingMessagesCount > 0); - Assert.True(result.Stats.AveragePerSecond >= 0); - Assert.True(result.Stats.ParkedMessageCount >= 0); - Assert.True(result.Stats.AveragePerSecond >= 0); - Assert.True(result.Stats.ReadBufferCount >= 0); - Assert.True(result.Stats.RetryBufferCount >= 0); - Assert.True(result.Stats.CountSinceLastMeasurement >= 0); - Assert.True(result.Stats.TotalInFlightMessages >= 0); - Assert.NotNull(result.Stats.LastKnownEventPosition); - Assert.NotNull(result.Stats.LastCheckpointedEventPosition); - Assert.True(result.Stats.LiveBufferCount >= 0); - - Assert.NotNull(result.Connections); - Assert.NotEmpty(result.Connections); - var connection = result.Connections.First(); - Assert.NotNull(connection.From); - Assert.Equal(TestCredentials.Root.Username, connection.Username); - Assert.NotEmpty(connection.ConnectionName); - Assert.True(connection.AverageItemsPerSecond >= 0); - Assert.True(connection.TotalItems >= 0); - Assert.True(connection.CountSinceLastMeasurement >= 0); - Assert.True(connection.AvailableSlots >= 0); - Assert.True(connection.InFlightMessages >= 0); - Assert.NotNull(connection.ExtraStatistics); - Assert.NotEmpty(connection.ExtraStatistics); - - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Highest); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Mean); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Median); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Fastest); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Quintile1); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Quintile2); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Quintile3); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Quintile4); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.Quintile5); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyPercent); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyFivePercent); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyNinePercent); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyNinePointFivePercent); - AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyNinePointNinePercent); - - Assert.NotNull(result.Settings); - Assert.Equal(_settings.StartFrom, result.Settings!.StartFrom); - Assert.Equal(_settings.ResolveLinkTos, result.Settings!.ResolveLinkTos); - Assert.Equal(_settings.ExtraStatistics, result.Settings!.ExtraStatistics); - Assert.Equal(_settings.MessageTimeout, result.Settings!.MessageTimeout); - Assert.Equal(_settings.MaxRetryCount, result.Settings!.MaxRetryCount); - Assert.Equal(_settings.LiveBufferSize, result.Settings!.LiveBufferSize); - Assert.Equal(_settings.ReadBatchSize, result.Settings!.ReadBatchSize); - Assert.Equal(_settings.HistoryBufferSize, result.Settings!.HistoryBufferSize); - Assert.Equal(_settings.CheckPointAfter, result.Settings!.CheckPointAfter); - Assert.Equal(_settings.CheckPointLowerBound, result.Settings!.CheckPointLowerBound); - Assert.Equal(_settings.CheckPointUpperBound, result.Settings!.CheckPointUpperBound); - Assert.Equal(_settings.MaxSubscriberCount, result.Settings!.MaxSubscriberCount); - Assert.Equal(_settings.ConsumerStrategyName, result.Settings!.ConsumerStrategyName); - } - - [Fact] - public async Task throws_when_given_non_existing_subscription() => - await Assert.ThrowsAsync( - async () => { - await _fixture.Client.GetInfoToStreamAsync( - "NonExisting", - "NonExisting", - userCredentials: TestCredentials.Root - ); - } - ); - - [Fact(Skip = "Unable to produce same behavior with HTTP fallback!")] - public async Task throws_with_non_existing_user() => - await Assert.ThrowsAsync( - async () => { - await _fixture.Client.GetInfoToStreamAsync( - "NonExisting", - "NonExisting", - userCredentials: TestCredentials.TestBadUser - ); - } - ); - - [Fact] - public async Task throws_with_no_credentials() => - await Assert.ThrowsAsync( - async () => { - await _fixture.Client.GetInfoToStreamAsync( - "NonExisting", - "NonExisting" - ); - } - ); - - [Fact] - public async Task returns_result_for_normal_user() { - var result = await _fixture.Client.GetInfoToStreamAsync( - StreamName, - GroupName, - userCredentials: TestCredentials.TestUser1 - ); - - Assert.NotNull(result); - } - - private void AssertKeyAndValue(IDictionary items, string key) { - Assert.True(items.ContainsKey(key)); - Assert.True(items[key] > 0); - } - - public class Fixture : EventStoreClientFixture { - private EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? _subscription; - private IAsyncEnumerator? _enumerator; - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => - Client.CreateToStreamAsync(groupName: GroupName, streamName: StreamName, settings: _settings, - userCredentials: TestCredentials.Root); - - protected override async Task When() { - var counter = 0; - _subscription = Client.SubscribeToStream(StreamName, GroupName, userCredentials: TestCredentials.Root); - _enumerator = _subscription.Messages.GetAsyncEnumerator(); - - for (var i = 0; i < 15; i++) { - await StreamsClient.AppendToStreamAsync(StreamName, StreamState.Any, - new[] { new EventData(Uuid.NewUuid(), "test-event", ReadOnlyMemory.Empty) }, - userCredentials: TestCredentials.Root); - } - - while (await _enumerator.MoveNextAsync()) { - if (_enumerator.Current is not PersistentSubscriptionMessage.Event(var resolvedEvent, _)) { - continue; - } - - counter++; - - if (counter == 1) { - await _subscription.Nack(PersistentSubscriptionNakEventAction.Park, "Test", resolvedEvent); - } - - if (counter > 10) { - return; - } - } - } - - public override async Task DisposeAsync() { - if (_enumerator is not null) { - await _enumerator.DisposeAsync(); - } - - if (_subscription is not null) { - await _subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/happy_case_catching_up_to_link_to_events_manual_ack.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/happy_case_catching_up_to_link_to_events_manual_ack.cs deleted file mode 100644 index 864eccd8a..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/happy_case_catching_up_to_link_to_events_manual_ack.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System.Text; - -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class happy_case_catching_up_to_link_to_events_manual_ack - : IClassFixture { - private const string Stream = nameof(happy_case_catching_up_to_link_to_events_manual_ack); - private const string Group = nameof(Group); - private const int BufferCount = 10; - private const int EventWriteCount = BufferCount * 2; - - private readonly Fixture _fixture; - - public happy_case_catching_up_to_link_to_events_manual_ack(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task Test() { - await _fixture.Subscription!.Messages.OfType() - .Take(_fixture.Events.Length) - .ForEachAwaitAsync(e => _fixture.Subscription.Ack(e.ResolvedEvent)) - .WithTimeout(); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(EventWriteCount) - .Select((e, i) => new EventData( - e.EventId, - SystemEventTypes.LinkTo, - Encoding.UTF8.GetBytes($"{i}@{Stream}"), - contentType: Constants.Metadata.ContentTypes.ApplicationOctetStream - )).ToArray(); - } - - protected override async Task Given() { - foreach (var e in Events) - await StreamsClient.AppendToStreamAsync(Stream, StreamState.Any, new[] { e }); - - await Client.CreateToStreamAsync(Stream, Group, new(startFrom: StreamPosition.Start, resolveLinkTos: true), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToStream(Stream, Group, bufferSize: BufferCount, - userCredentials: TestCredentials.Root); - } - - protected override Task When() => Task.CompletedTask; - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/happy_case_catching_up_to_normal_events_manual_ack.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/happy_case_catching_up_to_normal_events_manual_ack.cs deleted file mode 100644 index 5bcf18171..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/happy_case_catching_up_to_normal_events_manual_ack.cs +++ /dev/null @@ -1,53 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class happy_case_catching_up_to_normal_events_manual_ack - : IClassFixture { - private const string Stream = nameof(happy_case_catching_up_to_normal_events_manual_ack); - private const string Group = nameof(Group); - private const int BufferCount = 10; - private const int EventWriteCount = BufferCount * 2; - - private readonly Fixture _fixture; - - public happy_case_catching_up_to_normal_events_manual_ack(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task Test() { - await _fixture.Subscription!.Messages.OfType() - .Take(_fixture.Events.Length) - .ForEachAwaitAsync(e => _fixture.Subscription.Ack(e.ResolvedEvent)) - .WithTimeout(); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - - public Fixture() { - Events = CreateTestEvents(EventWriteCount).ToArray(); - } - - protected override async Task Given() { - foreach (var e in Events) - await StreamsClient.AppendToStreamAsync(Stream, StreamState.Any, new[] { e }); - - await Client.CreateToStreamAsync(Stream, Group, new(startFrom: StreamPosition.Start, resolveLinkTos: true), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToStream(Stream, Group, bufferSize: BufferCount, - userCredentials: TestCredentials.Root); - } - - protected override Task When() => Task.CompletedTask; - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/happy_case_writing_and_subscribing_to_normal_events_manual_ack.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/happy_case_writing_and_subscribing_to_normal_events_manual_ack.cs deleted file mode 100644 index b4f957d47..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/happy_case_writing_and_subscribing_to_normal_events_manual_ack.cs +++ /dev/null @@ -1,52 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class happy_case_writing_and_subscribing_to_normal_events_manual_ack - : IClassFixture { - private const string Stream = nameof(happy_case_writing_and_subscribing_to_normal_events_manual_ack); - private const string Group = nameof(Group); - private const int BufferCount = 10; - private const int EventWriteCount = BufferCount * 2; - - private readonly Fixture _fixture; - - public happy_case_writing_and_subscribing_to_normal_events_manual_ack(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task Test() { - await _fixture.Subscription!.Messages.OfType() - .Take(_fixture.Events.Length) - .ForEachAwaitAsync(e => _fixture.Subscription.Ack(e.ResolvedEvent)) - .WithTimeout(); - } - - public class Fixture : EventStoreClientFixture { - public readonly EventData[] Events; - - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - Events = CreateTestEvents(EventWriteCount).ToArray(); - } - - protected override async Task Given() { - await Client.CreateToStreamAsync(Stream, Group, new(startFrom: StreamPosition.End, resolveLinkTos: true), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToStream(Stream, Group, bufferSize: BufferCount, - userCredentials: TestCredentials.Root); - } - - protected override async Task When() { - foreach (var e in Events) - await StreamsClient.AppendToStreamAsync(Stream, StreamState.Any, new[] { e }); - } - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/list_with_persistent_subscriptions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/list_with_persistent_subscriptions.cs deleted file mode 100644 index 61f93cb11..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/list_with_persistent_subscriptions.cs +++ /dev/null @@ -1,82 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class list_with_persistent_subscriptions : IClassFixture { - const int AllStreamSubscriptionCount = 4; - const int StreamSubscriptionCount = 3; - const string GroupName = nameof(list_with_persistent_subscriptions); - const string StreamName = nameof(list_with_persistent_subscriptions); - readonly Fixture _fixture; - - public list_with_persistent_subscriptions(Fixture fixture) => _fixture = fixture; - - int TotalSubscriptionCount => - SupportsPSToAll.No - ? StreamSubscriptionCount - : AllStreamSubscriptionCount + StreamSubscriptionCount; - - [Fact] - public async Task returns_subscriptions_to_stream() { - var result = (await _fixture.Client.ListToStreamAsync(StreamName, userCredentials: TestCredentials.Root)).ToList(); - Assert.Equal(StreamSubscriptionCount, result.Count); - Assert.All(result, p => Assert.Equal(StreamName, p.EventSource)); - } - - [Fact] - public async Task returns_all_subscriptions() { - var result = (await _fixture.Client.ListAllAsync(userCredentials: TestCredentials.Root)).ToList(); - Assert.Equal(TotalSubscriptionCount, result.Count); - } - - [Fact] - public async Task throws_for_non_existing() => - await Assert.ThrowsAsync( - async () => - await _fixture.Client.ListToStreamAsync("NonExistingStream", userCredentials: TestCredentials.Root) - ); - - [Fact] - public async Task throws_with_no_credentials() => - await Assert.ThrowsAsync( - async () => - await _fixture.Client.ListToStreamAsync("NonExistingStream") - ); - - [Fact] - public async Task throws_with_non_existing_user() => - await Assert.ThrowsAsync( - async () => - await _fixture.Client.ListAllAsync(userCredentials: TestCredentials.TestBadUser) - ); - - [Fact] - public async Task returns_result_with_normal_user_credentials() { - var result = await _fixture.Client.ListAllAsync(userCredentials: TestCredentials.TestUser1); - Assert.Equal(TotalSubscriptionCount, result.Count()); - } - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(skipPSWarmUp: true, noDefaultCredentials: true) { } - - protected override async Task Given() { - for (var i = 0; i < StreamSubscriptionCount; i++) - await Client.CreateToStreamAsync( - StreamName, - GroupName + i, - new(), - userCredentials: TestCredentials.Root - ); - - if (SupportsPSToAll.No) - return; - - for (var i = 0; i < AllStreamSubscriptionCount; i++) - await Client.CreateToAllAsync( - GroupName + i, - new(), - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/list_without_persistent_subscriptions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/list_without_persistent_subscriptions.cs deleted file mode 100644 index 7e3ec3ad6..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/list_without_persistent_subscriptions.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class list_without_persistent_subscriptions : IClassFixture { - readonly Fixture _fixture; - - public list_without_persistent_subscriptions(Fixture fixture) => _fixture = fixture; - - [SupportsPSToAll.Fact] - public async Task throws() { - if (SupportsPSToAll.No) - return; - - await Assert.ThrowsAsync( - async () => - await _fixture.Client.ListToStreamAsync("stream", userCredentials: TestCredentials.Root) - ); - } - - [Fact] - public async Task returns_empty_collection() { - if (SupportsPSToAll.No) - return; - - var result = await _fixture.Client.ListAllAsync(userCredentials: TestCredentials.Root); - - Assert.Empty(result); - } - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(skipPSWarmUp: true) { } - - protected override Task Given() => Task.CompletedTask; - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/replay_parked.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/replay_parked.cs deleted file mode 100644 index 562449e52..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/replay_parked.cs +++ /dev/null @@ -1,80 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class replay_parked : IClassFixture { - const string GroupName = nameof(replay_parked); - const string StreamName = nameof(replay_parked); - - readonly Fixture _fixture; - - public replay_parked(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task does_not_throw() { - await _fixture.Client.ReplayParkedMessagesToStreamAsync( - StreamName, - GroupName, - userCredentials: TestCredentials.Root - ); - - await _fixture.Client.ReplayParkedMessagesToStreamAsync( - StreamName, - GroupName, - 100, - userCredentials: TestCredentials.Root - ); - } - - [Fact] - public async Task throws_when_given_non_existing_subscription() => - await Assert.ThrowsAsync( - () => - _fixture.Client.ReplayParkedMessagesToStreamAsync( - "NonExisting", - "NonExisting", - userCredentials: TestCredentials.Root - ) - ); - - [Fact] - public async Task throws_with_no_credentials() => - await Assert.ThrowsAsync( - () => - _fixture.Client.ReplayParkedMessagesToStreamAsync(StreamName, GroupName) - ); - - [Fact(Skip = "Unable to produce same behavior with HTTP fallback!")] - public async Task throws_with_non_existing_user() => - await Assert.ThrowsAsync( - () => - _fixture.Client.ReplayParkedMessagesToStreamAsync( - StreamName, - GroupName, - userCredentials: TestCredentials.TestBadUser - ) - ); - - [Fact] - public async Task throws_with_normal_user_credentials() => - await Assert.ThrowsAsync( - () => - _fixture.Client.ReplayParkedMessagesToStreamAsync( - StreamName, - GroupName, - userCredentials: TestCredentials.TestUser1 - ) - ); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => - Client.CreateToStreamAsync( - StreamName, - GroupName, - new(), - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing.cs deleted file mode 100644 index b76d5b189..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class update_existing - : IClassFixture { - const string Stream = nameof(update_existing); - const string Group = "existing"; - readonly Fixture _fixture; - - public update_existing(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_completion_succeeds() => - await _fixture.Client.UpdateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, CreateTestEvents()); - await Client.CreateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing_with_check_point.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing_with_check_point.cs deleted file mode 100644 index 09020a8df..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing_with_check_point.cs +++ /dev/null @@ -1,95 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class update_existing_with_check_point - : IClassFixture { - private const string Stream = nameof(update_existing_with_check_point); - private const string Group = "existing-with-check-point"; - private readonly Fixture _fixture; - - public update_existing_with_check_point(Fixture fixture) { - _fixture = fixture; - } - - [Fact] - public async Task resumes_from_check_point() { - await using var subscription = - _fixture.Client.SubscribeToStream(Stream, Group, userCredentials: TestCredentials.Root); - - var resolvedEvent = await subscription.Messages - .OfType() - .Select(e => e.ResolvedEvent) - .FirstAsync() - .AsTask() - .WithTimeout(); - - Assert.Equal(_fixture.CheckPoint.Next(), resolvedEvent.Event.EventNumber); - } - - public class Fixture : EventStoreClientFixture { - private readonly EventData[] _events; - - public Fixture() { - _events = CreateTestEvents(5).ToArray(); - } - - public StreamPosition CheckPoint { get; private set; } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, _events); - - await Client.CreateToStreamAsync(Stream, Group, - new(checkPointLowerBound: 5, checkPointAfter: TimeSpan.FromSeconds(1), startFrom: StreamPosition.Start), - userCredentials: TestCredentials.Root); - - await using var subscription = - Client.SubscribeToStream(Stream, Group, userCredentials: TestCredentials.Root); - - await using var enumerator = subscription.Messages.GetAsyncEnumerator(); - - await enumerator.MoveNextAsync(); - - await Task.WhenAll(Subscribe().WithTimeout(), WaitForCheckpoint().WithTimeout()); - - return; - - async Task Subscribe() { - var count = 0; - - while (await enumerator.MoveNextAsync()) { - if (enumerator.Current is not PersistentSubscriptionMessage.Event(var resolvedEvent, _)) { - continue; - } - - count++; - - await subscription.Ack(resolvedEvent); - if (count >= _events.Length) { - break; - } - } - } - - async Task WaitForCheckpoint() { - await using var subscription = StreamsClient.SubscribeToStream( - $"$persistentsubscription-{Stream}::{Group}-checkpoint", FromStream.Start, - userCredentials: TestCredentials.Root); - - await foreach (var message in subscription.Messages) { - if (message is not StreamMessage.Event (var resolvedEvent)) { - continue; - } - - CheckPoint = resolvedEvent.Event.Data.ParseStreamPosition(); - return; - } - } - } - - protected override async Task When() { - // Force restart of the subscription - await Client.UpdateToStreamAsync(Stream, Group, new(), userCredentials: TestCredentials.Root); - - await StreamsClient.AppendToStreamAsync(Stream, StreamState.Any, CreateTestEvents(1)); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing_with_subscribers.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing_with_subscribers.cs deleted file mode 100644 index e472aec9d..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing_with_subscribers.cs +++ /dev/null @@ -1,50 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class update_existing_with_subscribers : IClassFixture { - private const string Stream = nameof(update_existing_with_subscribers); - private const string Group = "existing"; - private readonly Fixture _fixture; - - public update_existing_with_subscribers(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task existing_subscriptions_are_dropped() { - var ex = await Assert.ThrowsAsync(async () => { - while (await _fixture.Enumerator!.MoveNextAsync()) { - } - }).WithTimeout(); - - Assert.Equal(Stream, ex.StreamName); - Assert.Equal(Group, ex.GroupName); - } - - public class Fixture : EventStoreClientFixture { - private EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? _subscription; - public IAsyncEnumerator? Enumerator { get; private set; } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.NoStream, CreateTestEvents()); - await Client.CreateToStreamAsync(Stream, Group, new(), userCredentials: TestCredentials.Root); - - _subscription = Client.SubscribeToStream(Stream, Group, userCredentials: TestCredentials.Root); - Enumerator = _subscription.Messages.GetAsyncEnumerator(); - - await Enumerator.MoveNextAsync(); - } - - protected override Task When() => - Client.UpdateToStreamAsync(Stream, Group, new(), userCredentials: TestCredentials.Root); - - public override async Task DisposeAsync() { - if (Enumerator is not null) { - await Enumerator.DisposeAsync(); - } - - if (_subscription is not null) { - await _subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing_without_permissions.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing_without_permissions.cs deleted file mode 100644 index 021aa47b9..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_existing_without_permissions.cs +++ /dev/null @@ -1,42 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class update_existing_without_permissions - : IClassFixture { - const string Stream = nameof(update_existing_without_permissions); - const string Group = "existing"; - readonly Fixture _fixture; - - public update_existing_without_permissions(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task the_completion_fails_with_access_denied() => - await Assert.ThrowsAsync( - () => _fixture.Client.UpdateToStreamAsync( - Stream, - Group, - new() - ) - ); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override async Task Given() { - await StreamsClient.AppendToStreamAsync( - Stream, - StreamState.NoStream, - CreateTestEvents(), - userCredentials: TestCredentials.Root - ); - - await Client.CreateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root - ); - } - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_non_existent.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_non_existent.cs deleted file mode 100644 index 9e1f37e86..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/update_non_existent.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -public class update_non_existent - : IClassFixture { - const string Stream = nameof(update_non_existent); - const string Group = "nonexistent"; - readonly Fixture _fixture; - - public update_non_existent(Fixture fixture) => _fixture = fixture; - - [Regression.Fact(21, "20.x returns the wrong exception")] - public async Task the_completion_fails_with_not_found() => - await Assert.ThrowsAsync( - () => _fixture.Client.UpdateToStreamAsync( - Stream, - Group, - new(), - userCredentials: TestCredentials.Root - ) - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/when_writing_and_subscribing_to_normal_events_manual_nack.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/when_writing_and_subscribing_to_normal_events_manual_nack.cs deleted file mode 100644 index 267baa684..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/when_writing_and_subscribing_to_normal_events_manual_nack.cs +++ /dev/null @@ -1,54 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream; - -[Obsolete] -public class when_writing_and_subscribing_to_normal_events_manual_nack - : IClassFixture { - private const string Stream = nameof(when_writing_and_subscribing_to_normal_events_manual_nack); - private const string Group = nameof(Group); - private const int BufferCount = 10; - private const int EventWriteCount = BufferCount * 2; - - private readonly Fixture _fixture; - - public when_writing_and_subscribing_to_normal_events_manual_nack(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task Test() { - await _fixture.Subscription!.Messages.OfType() - .Take(1) - .ForEachAwaitAsync(async message => - await _fixture.Subscription.Nack(PersistentSubscriptionNakEventAction.Park, "fail", - message.ResolvedEvent)) - .WithTimeout(); - } - - public class Fixture : EventStoreClientFixture { - private readonly EventData[] _events; - public EventStorePersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription { get; private set; } - - public Fixture() { - _events = CreateTestEvents(EventWriteCount).ToArray(); - } - - protected override async Task Given() { - await Client.CreateToStreamAsync(Stream, Group, new(startFrom: StreamPosition.Start, resolveLinkTos: true), - userCredentials: TestCredentials.Root); - - Subscription = Client.SubscribeToStream(Stream, Group, bufferSize: BufferCount, userCredentials: TestCredentials.Root); - } - - protected override async Task When() { - foreach (var e in _events) { - await StreamsClient.AppendToStreamAsync(Stream, StreamState.Any, new[] { e }); - } - } - - public override async Task DisposeAsync() { - if (Subscription is not null) { - await Subscription.DisposeAsync(); - } - - await base.DisposeAsync(); - } - } -} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/restart_subsystem.cs b/test/EventStore.Client.PersistentSubscriptions.Tests/restart_subsystem.cs deleted file mode 100644 index cc6047e00..000000000 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/restart_subsystem.cs +++ /dev/null @@ -1,74 +0,0 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests; - -public class restart_subsystem : IClassFixture { - readonly Fixture _fixture; - - public restart_subsystem(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task does_not_throw() => await _fixture.Client.RestartSubsystemAsync(userCredentials: TestCredentials.Root); - - [Fact] - public async Task throws_with_no_credentials() => - await Assert.ThrowsAsync( - async () => - await _fixture.Client.RestartSubsystemAsync() - ); - - [Fact(Skip = "Unable to produce same behavior with HTTP fallback!")] - public async Task throws_with_non_existing_user() => - await Assert.ThrowsAsync( - async () => await _fixture.Client.RestartSubsystemAsync(userCredentials: TestCredentials.TestBadUser) - ); - - [Fact] - public async Task throws_with_normal_user_credentials() => - await Assert.ThrowsAsync(async () => await _fixture.Client.RestartSubsystemAsync(userCredentials: TestCredentials.TestUser1)); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} - -// namespace EventStore.Client.PersistentSubscriptions.Tests; -// -// public class restart_subsystem : IClassFixture { -// readonly InsecureClientTestFixture _fixture; -// -// public restart_subsystem(InsecureClientTestFixture fixture) => _fixture = fixture; -// -// [Fact] -// public async Task does_not_throw() => -// await _fixture.PersistentSubscriptions.RestartSubsystemAsync(userCredentials: TestCredentials.Root); -// -// [Fact] -// public async Task throws_with_no_credentials() => -// await Assert.ThrowsAsync( -// async () => -// await _fixture.PersistentSubscriptions.RestartSubsystemAsync() -// ); -// -// [Fact(Skip = "Unable to produce same behavior with HTTP fallback!")] -// public async Task throws_with_non_existing_user() => -// await Assert.ThrowsAsync( -// async () => await _fixture.PersistentSubscriptions.RestartSubsystemAsync(userCredentials: TestCredentials.TestBadUser) -// ); -// -// [Fact] -// public async Task throws_with_normal_user_credentials() { -// await _fixture.Users.CreateUserWithRetry( -// TestCredentials.TestUser1.Username!, -// TestCredentials.TestUser1.Username!, -// Array.Empty(), -// TestCredentials.TestUser1.Password!, -// TestCredentials.Root -// ); -// -// await Assert.ThrowsAsync( -// async () => await _fixture.PersistentSubscriptions.RestartSubsystemAsync(userCredentials: TestCredentials.TestUser1) -// ); -// } -// } \ No newline at end of file diff --git a/test/EventStore.Client.Plugins.Tests/ClientCertificateTests.cs b/test/EventStore.Client.Plugins.Tests/ClientCertificateTests.cs deleted file mode 100644 index e50fde0a5..000000000 --- a/test/EventStore.Client.Plugins.Tests/ClientCertificateTests.cs +++ /dev/null @@ -1,67 +0,0 @@ -namespace EventStore.Client.Plugins.Tests; - -[Trait("Category", "Target:Plugins")] -[Trait("Category", "Type:UserCertificate")] -public class ClientCertificateTests(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { - [Theory, BadClientCertificatesTestCases] - async Task bad_certificates_combinations_should_return_authentication_error(string userCertFile, string userKeyFile, string tlsCaFile) { - var stream = Fixture.GetStreamName(); - var seedEvents = Fixture.CreateTestEvents(); - var connectionString = $"esdb://localhost:2113/?tls=true&userCertFile={userCertFile}&userKeyFile={userKeyFile}&tlsCaFile={tlsCaFile}"; - - var settings = EventStoreClientSettings.Create(connectionString); - settings.ConnectivitySettings.TlsVerifyCert.ShouldBeTrue(); - - await using var client = new EventStoreClient(settings); - - await client.AppendToStreamAsync(stream, StreamState.NoStream, seedEvents).ShouldThrowAsync(); - } - - [Theory, ValidClientCertificatesTestCases] - async Task valid_certificates_combinations_should_write_to_stream(string userCertFile, string userKeyFile, string tlsCaFile) { - var stream = Fixture.GetStreamName(); - var seedEvents = Fixture.CreateTestEvents(); - var connectionString = $"esdb://localhost:2113/?userCertFile={userCertFile}&userKeyFile={userKeyFile}&tlsCaFile={tlsCaFile}"; - - var settings = EventStoreClientSettings.Create(connectionString); - settings.ConnectivitySettings.TlsVerifyCert.ShouldBeTrue(); - - await using var client = new EventStoreClient(settings); - - var result = await client.AppendToStreamAsync(stream, StreamState.NoStream, seedEvents); - result.ShouldNotBeNull(); - } - - [Theory, BadClientCertificatesTestCases] - async Task basic_authentication_should_take_precedence(string userCertFile, string userKeyFile, string tlsCaFile) { - var stream = Fixture.GetStreamName(); - var seedEvents = Fixture.CreateTestEvents(); - var connectionString = $"esdb://admin:changeit@localhost:2113/?userCertFile={userCertFile}&userKeyFile={userKeyFile}&tlsCaFile={tlsCaFile}"; - - var settings = EventStoreClientSettings.Create(connectionString); - settings.ConnectivitySettings.TlsVerifyCert.ShouldBeTrue(); - - await using var client = new EventStoreClient(settings); - - var result = await client.AppendToStreamAsync(stream, StreamState.NoStream, seedEvents); - result.ShouldNotBeNull(); - } - - class BadClientCertificatesTestCases : TestCaseGenerator { - protected override IEnumerable Data() { - yield return [Certificates.Invalid.CertAbsolute, Certificates.Invalid.KeyAbsolute, Certificates.TlsCa.Absolute]; - yield return [Certificates.Invalid.CertRelative, Certificates.Invalid.KeyRelative, Certificates.TlsCa.Absolute]; - yield return [Certificates.Invalid.CertAbsolute, Certificates.Invalid.KeyAbsolute, Certificates.TlsCa.Relative]; - yield return [Certificates.Invalid.CertRelative, Certificates.Invalid.KeyRelative, Certificates.TlsCa.Relative]; - } - } - - class ValidClientCertificatesTestCases : TestCaseGenerator { - protected override IEnumerable Data() { - yield return [Certificates.Admin.CertAbsolute, Certificates.Admin.KeyAbsolute, Certificates.TlsCa.Absolute]; - yield return [Certificates.Admin.CertRelative, Certificates.Admin.KeyRelative, Certificates.TlsCa.Absolute]; - yield return [Certificates.Admin.CertAbsolute, Certificates.Admin.KeyAbsolute, Certificates.TlsCa.Relative]; - yield return [Certificates.Admin.CertRelative, Certificates.Admin.KeyRelative, Certificates.TlsCa.Relative]; - } - } -} diff --git a/test/EventStore.Client.Plugins.Tests/EventStore.Client.Plugins.Tests.csproj b/test/EventStore.Client.Plugins.Tests/EventStore.Client.Plugins.Tests.csproj deleted file mode 100644 index ee7d48512..000000000 --- a/test/EventStore.Client.Plugins.Tests/EventStore.Client.Plugins.Tests.csproj +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/test/EventStore.Client.ProjectionManagement.Tests/AssemblyInfo.cs b/test/EventStore.Client.ProjectionManagement.Tests/AssemblyInfo.cs deleted file mode 100644 index b0b47aa73..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/AssemblyInfo.cs +++ /dev/null @@ -1 +0,0 @@ -[assembly: CollectionBehavior(DisableTestParallelization = true)] \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/EventStore.Client.ProjectionManagement.Tests.csproj b/test/EventStore.Client.ProjectionManagement.Tests/EventStore.Client.ProjectionManagement.Tests.csproj deleted file mode 100644 index 31381e212..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/EventStore.Client.ProjectionManagement.Tests.csproj +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/EventStoreClientFixture.cs b/test/EventStore.Client.ProjectionManagement.Tests/EventStoreClientFixture.cs deleted file mode 100644 index 62d9ba053..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/EventStoreClientFixture.cs +++ /dev/null @@ -1,50 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public abstract class EventStoreClientFixture : EventStoreClientFixtureBase { - protected EventStoreClientFixture(EventStoreClientSettings? settings = null, bool noDefaultCredentials = false) : - base( - settings, - new Dictionary { - ["EVENTSTORE_RUN_PROJECTIONS"] = "ALL", - ["EVENTSTORE_START_STANDARD_PROJECTIONS"] = "True" - }, - noDefaultCredentials - ) { - Client = new(Settings); - UserManagementClient = new(Settings); - StreamsClient = new(Settings); - } - - public EventStoreUserManagementClient UserManagementClient { get; } - public EventStoreClient StreamsClient { get; } - public EventStoreProjectionManagementClient Client { get; } - - protected virtual bool RunStandardProjections => true; - - protected override async Task OnServerUpAsync() { - await StreamsClient.WarmUp(); - await UserManagementClient.WarmUp(); - await Client.WarmUp(); - await UserManagementClient.CreateUserWithRetry( - TestCredentials.TestUser1.Username!, - TestCredentials.TestUser1.Username!, - Array.Empty(), - TestCredentials.TestUser1.Password!, - TestCredentials.Root - ).WithTimeout(); - - await StandardProjections.Created(Client).WithTimeout(TimeSpan.FromMinutes(2)); - - if (RunStandardProjections) - await Task - .WhenAll(StandardProjections.Names.Select(name => Client.EnableAsync(name, userCredentials: TestCredentials.Root))) - .WithTimeout(TimeSpan.FromMinutes(2)); - } - - public override async Task DisposeAsync() { - await StreamsClient.DisposeAsync(); - await UserManagementClient.DisposeAsync(); - await Client.DisposeAsync(); - await base.DisposeAsync(); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/StandardProjections.cs b/test/EventStore.Client.ProjectionManagement.Tests/StandardProjections.cs deleted file mode 100644 index 4f57a0ae2..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/StandardProjections.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -static class StandardProjections { - public static readonly string[] Names = { - "$streams", - "$stream_by_category", - "$by_category", - "$by_event_type", - "$by_correlation_id" - }; - - public static Task Created(EventStoreProjectionManagementClient client) { - var systemProjectionsReady = Names.Select( - async name => { - var ready = false; - - while (!ready) { - var result = await client.GetStatusAsync(name, userCredentials: TestCredentials.Root); - - if (result?.Status.Contains("Running") ?? false) - ready = true; - else - await Task.Delay(100); - } - } - ); - - return Task.WhenAll(systemProjectionsReady); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/abort.cs b/test/EventStore.Client.ProjectionManagement.Tests/abort.cs deleted file mode 100644 index 1983a79b6..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/abort.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class @abort : IClassFixture { - readonly Fixture _fixture; - - public abort(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task status_is_aborted() { - var name = StandardProjections.Names.First(); - await _fixture.Client.AbortAsync(name, userCredentials: TestCredentials.Root); - var result = await _fixture.Client.GetStatusAsync(name, userCredentials: TestCredentials.Root); - Assert.NotNull(result); - Assert.Contains(new[] { "Aborted/Stopped", "Stopped" }, x => x == result!.Status); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/create.cs b/test/EventStore.Client.ProjectionManagement.Tests/create.cs deleted file mode 100644 index e8f9c21d2..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/create.cs +++ /dev/null @@ -1,35 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class @create : IClassFixture { - readonly Fixture _fixture; - - public create(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task one_time() => - await _fixture.Client.CreateOneTimeAsync("fromAll().when({$init: function (state, ev) {return {};}});", userCredentials: TestCredentials.Root); - - [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task continuous(bool trackEmittedStreams) => - await _fixture.Client.CreateContinuousAsync( - $"{nameof(continuous)}_{trackEmittedStreams}", - "fromAll().when({$init: function (state, ev) {return {};}});", - trackEmittedStreams, - userCredentials: TestCredentials.Root - ); - - [Fact] - public async Task transient() => - await _fixture.Client.CreateTransientAsync( - nameof(transient), - "fromAll().when({$init: function (state, ev) {return {};}});", - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/disable.cs b/test/EventStore.Client.ProjectionManagement.Tests/disable.cs deleted file mode 100644 index bd03a2847..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/disable.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class @disable : IClassFixture { - readonly Fixture _fixture; - - public disable(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task status_is_stopped() { - var name = StandardProjections.Names.First(); - await _fixture.Client.DisableAsync(name, userCredentials: TestCredentials.Root); - var result = await _fixture.Client.GetStatusAsync(name, userCredentials: TestCredentials.Root); - Assert.NotNull(result); - Assert.Contains(new[] { "Aborted/Stopped", "Stopped" }, x => x == result!.Status); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/enable.cs b/test/EventStore.Client.ProjectionManagement.Tests/enable.cs deleted file mode 100644 index 0afecaaa7..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/enable.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class @enable : IClassFixture { - readonly Fixture _fixture; - - public enable(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task status_is_running() { - var name = StandardProjections.Names.First(); - await _fixture.Client.EnableAsync(name, userCredentials: TestCredentials.Root); - var result = await _fixture.Client.GetStatusAsync(name, userCredentials: TestCredentials.Root); - Assert.NotNull(result); - Assert.Equal("Running", result!.Status); - } - - public class Fixture : EventStoreClientFixture { - protected override bool RunStandardProjections => false; - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/get_result.cs b/test/EventStore.Client.ProjectionManagement.Tests/get_result.cs deleted file mode 100644 index d664862b5..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/get_result.cs +++ /dev/null @@ -1,51 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class get_result : IClassFixture { - readonly Fixture _fixture; - - public get_result(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task returns_expected_result() { - Result? result = null; - - await AssertEx.IsOrBecomesTrue( - async () => { - result = await _fixture.Client - .GetResultAsync(nameof(get_result), userCredentials: TestCredentials.TestUser1); - - return result.Count > 0; - } - ); - - Assert.NotNull(result); - Assert.Equal(1, result!.Count); - } - - class Result { - public int Count { get; set; } - } - - public class Fixture : EventStoreClientFixture { - static readonly string Projection = $@" -fromStream('{nameof(get_result)}').when({{ - ""$init"": function() {{ return {{ Count: 0 }}; }}, - ""$any"": function(s, e) {{ s.Count++; return s; }} -}}); -"; - - protected override Task Given() => - Client.CreateContinuousAsync( - nameof(get_result), - Projection, - userCredentials: TestCredentials.Root - ); - - protected override async Task When() => - await StreamsClient.AppendToStreamAsync( - nameof(get_result), - StreamState.NoStream, - CreateTestEvents() - ); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/get_state.cs b/test/EventStore.Client.ProjectionManagement.Tests/get_state.cs deleted file mode 100644 index 2295ed722..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/get_state.cs +++ /dev/null @@ -1,51 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class get_state : IClassFixture { - readonly Fixture _fixture; - - public get_state(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task returns_expected_result() { - Result? result = null; - - await AssertEx.IsOrBecomesTrue( - async () => { - result = await _fixture.Client - .GetStateAsync(nameof(get_state), userCredentials: TestCredentials.TestUser1); - - return result.Count > 0; - } - ); - - Assert.NotNull(result); - Assert.Equal(1, result!.Count); - } - - class Result { - public int Count { get; set; } - } - - public class Fixture : EventStoreClientFixture { - static readonly string Projection = $@" -fromStream('{nameof(get_state)}').when({{ - ""$init"": function() {{ return {{ Count: 0 }}; }}, - ""$any"": function(s, e) {{ s.Count++; return s; }} -}}); -"; - - protected override Task Given() => - Client.CreateContinuousAsync( - nameof(get_state), - Projection, - userCredentials: TestCredentials.Root - ); - - protected override Task When() => - StreamsClient.AppendToStreamAsync( - nameof(get_state), - StreamState.NoStream, - CreateTestEvents() - ); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/get_status.cs b/test/EventStore.Client.ProjectionManagement.Tests/get_status.cs deleted file mode 100644 index 7382a758b..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/get_status.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class get_status : IClassFixture { - readonly Fixture _fixture; - - public get_status(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task returns_expected_result() { - var name = StandardProjections.Names.First(); - var result = await _fixture.Client.GetStatusAsync(name, userCredentials: TestCredentials.TestUser1); - - Assert.NotNull(result); - Assert.Equal(name, result!.Name); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/list_all_projections.cs b/test/EventStore.Client.ProjectionManagement.Tests/list_all_projections.cs deleted file mode 100644 index cac2e85da..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/list_all_projections.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class list_all_projections : IClassFixture { - readonly Fixture _fixture; - - public list_all_projections(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task returns_expected_result() { - var result = await _fixture.Client.ListAllAsync(userCredentials: TestCredentials.Root) - .ToArrayAsync(); - - Assert.Equal(result.Select(x => x.Name).OrderBy(x => x), StandardProjections.Names.OrderBy(x => x)); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/list_continuous_projections.cs b/test/EventStore.Client.ProjectionManagement.Tests/list_continuous_projections.cs deleted file mode 100644 index c96ed825f..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/list_continuous_projections.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class list_continuous_projections : IClassFixture { - readonly Fixture _fixture; - - public list_continuous_projections(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task returns_expected_result() { - var result = await _fixture.Client.ListContinuousAsync(userCredentials: TestCredentials.Root) - .ToArrayAsync(); - - Assert.Equal( - result.Select(x => x.Name).OrderBy(x => x), - StandardProjections.Names.Concat(new[] { nameof(list_continuous_projections) }).OrderBy(x => x) - ); - - Assert.True(result.All(x => x.Mode == "Continuous")); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => - Client.CreateContinuousAsync( - nameof(list_continuous_projections), - "fromAll().when({$init: function (state, ev) {return {};}});", - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/list_one_time_projections.cs b/test/EventStore.Client.ProjectionManagement.Tests/list_one_time_projections.cs deleted file mode 100644 index d88d68b5c..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/list_one_time_projections.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class list_one_time_projections : IClassFixture { - readonly Fixture _fixture; - - public list_one_time_projections(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task returns_expected_result() { - var result = await _fixture.Client.ListOneTimeAsync(userCredentials: TestCredentials.Root) - .ToArrayAsync(); - - var details = Assert.Single(result); - Assert.Equal("OneTime", details.Mode); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => - Client.CreateOneTimeAsync("fromAll().when({$init: function (state, ev) {return {};}});", userCredentials: TestCredentials.Root); - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/reset.cs b/test/EventStore.Client.ProjectionManagement.Tests/reset.cs deleted file mode 100644 index 3dbfc15a5..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/reset.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class @reset : IClassFixture { - readonly Fixture _fixture; - - public reset(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task status_is_running() { - var name = StandardProjections.Names.First(); - await _fixture.Client.ResetAsync(name, userCredentials: TestCredentials.Root); - var result = await _fixture.Client.GetStatusAsync(name, userCredentials: TestCredentials.Root); - - Assert.NotNull(result); - Assert.Equal("Running", result!.Status); - } - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/restart_subsystem.cs b/test/EventStore.Client.ProjectionManagement.Tests/restart_subsystem.cs deleted file mode 100644 index d10ba1545..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/restart_subsystem.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class restart_subsystem : IClassFixture { - readonly Fixture _fixture; - - public restart_subsystem(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task does_not_throw() => await _fixture.Client.RestartSubsystemAsync(userCredentials: TestCredentials.Root); - - [Fact] - public async Task throws_when_given_no_credentials() => await Assert.ThrowsAsync(() => _fixture.Client.RestartSubsystemAsync()); - - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => Task.CompletedTask; - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.ProjectionManagement.Tests/update.cs b/test/EventStore.Client.ProjectionManagement.Tests/update.cs deleted file mode 100644 index ba8b682ad..000000000 --- a/test/EventStore.Client.ProjectionManagement.Tests/update.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace EventStore.Client.ProjectionManagement.Tests; - -public class @update : IClassFixture { - readonly Fixture _fixture; - - public update(Fixture fixture) => _fixture = fixture; - - [Theory] - [InlineData(true)] - [InlineData(false)] - [InlineData(null)] - public async Task returns_expected_result(bool? emitEnabled) => - await _fixture.Client.UpdateAsync( - nameof(update), - "fromAll().when({$init: function (s, e) {return {};}});", - emitEnabled, - userCredentials: TestCredentials.Root - ); - - public class Fixture : EventStoreClientFixture { - protected override Task Given() => - Client.CreateContinuousAsync( - nameof(update), - "fromAll().when({$init: function (state, ev) {return {};}});", - userCredentials: TestCredentials.Root - ); - - protected override Task When() => Task.CompletedTask; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Append/ShouldThrowAsyncExtensions.cs b/test/EventStore.Client.Streams.Tests/Append/ShouldThrowAsyncExtensions.cs deleted file mode 100644 index 80f983ce0..000000000 --- a/test/EventStore.Client.Streams.Tests/Append/ShouldThrowAsyncExtensions.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Append; - -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/Append/append_to_stream_limits.cs b/test/EventStore.Client.Streams.Tests/Append/append_to_stream_limits.cs deleted file mode 100644 index 6bdd3fbb8..000000000 --- a/test/EventStore.Client.Streams.Tests/Append/append_to_stream_limits.cs +++ /dev/null @@ -1,54 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Append; - -[Trait("Category", "Target:Stream")] -[Trait("Category", "Operation:Append")] -public class append_to_stream_limits(ITestOutputHelper output, StreamLimitsFixture fixture) : EventStoreTests(output, fixture) { - [Fact] - public async Task succeeds_when_size_is_less_than_max_append_size() { - var stream = Fixture.GetStreamName(); - - var (events, size) = Fixture.CreateTestEventsUpToMaxSize(StreamLimitsFixture.MaxAppendSize - 1); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - } - - [Fact] - public async Task fails_when_size_exceeds_max_append_size() { - var stream = Fixture.GetStreamName(); - - var eventsAppendSize = StreamLimitsFixture.MaxAppendSize * 2; - - // beware of the size of the events... - var (events, size) = Fixture.CreateTestEventsUpToMaxSize(eventsAppendSize); - - size.ShouldBeGreaterThan(StreamLimitsFixture.MaxAppendSize); - - var ex = await Fixture.Streams - .AppendToStreamAsync(stream, StreamState.NoStream, events) - .ShouldThrowAsync(); - - ex.MaxAppendSize.ShouldBe(StreamLimitsFixture.MaxAppendSize); - } -} - -public class StreamLimitsFixture() : EventStoreFixture(x => x.WithMaxAppendSize(MaxAppendSize)) { - public const uint MaxAppendSize = 64; - - public (IEnumerable Events, uint size) CreateTestEventsUpToMaxSize(uint maxSize) { - var size = 0; - var events = new List(); - - foreach (var evt in CreateTestEvents(int.MaxValue)) { - size += evt.Data.Length; - - if (size >= maxSize) { - size -= evt.Data.Length; - break; - } - - events.Add(evt); - } - - return (events, (uint)size); - } -} diff --git a/test/EventStore.Client.Streams.Tests/Append/append_to_stream_retry.cs b/test/EventStore.Client.Streams.Tests/Append/append_to_stream_retry.cs deleted file mode 100644 index d67240c49..000000000 --- a/test/EventStore.Client.Streams.Tests/Append/append_to_stream_retry.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Polly; -using Polly.Contrib.WaitAndRetry; - -namespace EventStore.Client.Streams.Tests.Append; - -[Trait("Category", "Target:Stream")] -[Trait("Category", "Operation:Append")] -public class append_to_stream_retry(ITestOutputHelper output, StreamRetryFixture fixture) : EventStoreTests(output, fixture) { - [Fact] - public async Task can_retry() { - var stream = Fixture.GetStreamName(); - - // can definitely write without throwing - var result = await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); - - result.NextExpectedStreamRevision.ShouldBe(new(0)); - - await Fixture.Service.Restart(); - - // write can be retried - var writeResult = await Policy - .Handle() - .WaitAndRetryAsync( - Backoff.LinearBackoff(TimeSpan.FromMilliseconds(250), 10), - (ex, ts) => Fixture.Log.Debug("Error writing events to stream. Retrying. Reason: {Message}.", ex.Message) - ) - .ExecuteAsync(() => Fixture.Streams.AppendToStreamAsync(stream, result.NextExpectedStreamRevision, Fixture.CreateTestEvents())); - - Fixture.Log.Information("Successfully wrote events to stream {Stream}.", stream); - - writeResult.NextExpectedStreamRevision.ShouldBe(new(1)); - } -} - -public class StreamRetryFixture() : EventStoreFixture( - x => x.RunInMemory(false).With(o => o.ClientSettings.ConnectivitySettings.MaxDiscoverAttempts = 2) -); \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Append/append_to_stream_with_tls_ca_file.cs b/test/EventStore.Client.Streams.Tests/Append/append_to_stream_with_tls_ca_file.cs deleted file mode 100644 index 2fdc983ba..000000000 --- a/test/EventStore.Client.Streams.Tests/Append/append_to_stream_with_tls_ca_file.cs +++ /dev/null @@ -1,35 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Append; - -[Trait("Category", "Target:Stream")] -[Trait("Category", "Operation:Append")] -public class append_to_stream_with_tls_ca_file(ITestOutputHelper output, EventStoreFixture fixture) - : EventStoreTests(output, fixture) { - public static IEnumerable CertPaths => - new List { - new object[] { Path.Combine("certs", "ca", "ca.crt") }, - new object[] { Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "certs", "ca", "ca.crt") }, - }; - - [Theory] - [MemberData(nameof(CertPaths))] - private async Task TestAppendWithCaFile(string certificateFilePath) { - Fixture.Log.Information($"Using certificate: {certificateFilePath}"); - - var connectionString = - $"esdb://admin:changeit@localhost:2113/?tls=true&tlsVerifyCert=true&tlsCAFile={certificateFilePath}"; - - var settings = EventStoreClientSettings.Create(connectionString); - - var client = new EventStoreClient(settings); - - var appendResult = await client.AppendToStreamAsync( - "some-stream", - StreamState.Any, - new[] { new EventData(Uuid.NewUuid(), "some-event", default) } - ); - - appendResult.ShouldNotBeNull(); - - await client.DisposeAsync(); - } -} diff --git a/test/EventStore.Client.Streams.Tests/Append/appending_to_implicitly_created_stream.cs b/test/EventStore.Client.Streams.Tests/Append/appending_to_implicitly_created_stream.cs deleted file mode 100644 index 59ab89df0..000000000 --- a/test/EventStore.Client.Streams.Tests/Append/appending_to_implicitly_created_stream.cs +++ /dev/null @@ -1,266 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Append; - -[Trait("Category", "Target:Stream")] -[Trait("Category", "Operation:Append")] -public class appending_to_implicitly_created_stream(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { - [Fact] - public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0em1_idempotent() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(6).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(1)); - - var count = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); - - Assert.Equal(events.Length, count); - } - - [Fact] - public async Task sequence_0em1_1e0_2e1_3e2_4e3_4e4_0any_idempotent() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(6).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Take(1)); - - var count = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); - - Assert.Equal(events.Length, count); - } - - [Fact] - public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e5_non_idempotent() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(6).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(5), events.Take(1)); - - var count = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 2).CountAsync(); - - Assert.Equal(events.Length + 1, count); - } - - [Fact] - public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e6_throws_wev() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(6).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - - await Assert.ThrowsAsync(() => Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(6), events.Take(1))); - } - - [Fact] - public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e6_returns_wev() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(6).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - - var writeResult = await Fixture.Streams.AppendToStreamAsync( - stream, - new StreamRevision(6), - events.Take(1), - options => options.ThrowOnAppendFailure = false - ); - - Assert.IsType(writeResult); - } - - [Fact] - public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e4_throws_wev() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(6).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - - await Assert.ThrowsAsync(() => Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(4), events.Take(1))); - } - - [Fact] - public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e4_returns_wev() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(6).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - - var writeResult = await Fixture.Streams.AppendToStreamAsync( - stream, - new StreamRevision(4), - events.Take(1), - options => options.ThrowOnAppendFailure = false - ); - - Assert.IsType(writeResult); - } - - [Fact] - public async Task sequence_0em1_0e0_non_idempotent() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents().ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(0), events.Take(1)); - - var count = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 2).CountAsync(); - - Assert.Equal(events.Length + 1, count); - } - - [Fact] - public async Task sequence_0em1_0any_idempotent() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents().ToArray(); - - await Task.Delay(TimeSpan.FromSeconds(30)); - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Take(1)); - - var count = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); - - Assert.Equal(events.Length, count); - } - - [Fact] - public async Task sequence_0em1_0em1_idempotent() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents().ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(1)); - - var count = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); - - Assert.Equal(events.Length, count); - } - - [Fact] - public async Task sequence_0em1_1e0_2e1_1any_1any_idempotent() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(3).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Skip(1).Take(1)); - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Skip(1).Take(1)); - - var count = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); - - Assert.Equal(events.Length, count); - } - - [Fact] - public async Task sequence_S_0em1_1em1_E_S_0em1_E_idempotent() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(2).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(1)); - - var count = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); - - Assert.Equal(events.Length, count); - } - - [Fact] - public async Task sequence_S_0em1_1em1_E_S_0any_E_idempotent() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(2).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Take(1)); - - var count = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); - - Assert.Equal(events.Length, count); - } - - [Fact] - public async Task sequence_S_0em1_1em1_E_S_1e0_E_idempotent() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(2).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - - await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(0), events.Skip(1)); - - var count = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); - - Assert.Equal(events.Length, count); - } - - [Fact] - public async Task sequence_S_0em1_1em1_E_S_1any_E_idempotent() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(2).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Skip(1).Take(1)); - - var count = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); - - Assert.Equal(events.Length, count); - } - - [Fact] - public async Task sequence_S_0em1_1em1_E_S_0em1_1em1_2em1_E_idempotancy_fail_throws() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(3).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(2)); - - await Assert.ThrowsAsync( - () => Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - events - ) - ); - } - - [Fact] - public async Task sequence_S_0em1_1em1_E_S_0em1_1em1_2em1_E_idempotancy_fail_returns() { - var stream = Fixture.GetStreamName(); - - var events = Fixture.CreateTestEvents(3).ToArray(); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(2)); - - var writeResult = await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - events, - options => options.ThrowOnAppendFailure = false - ); - - Assert.IsType(writeResult); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Append/sending_and_receiving_large_messages.cs b/test/EventStore.Client.Streams.Tests/Append/sending_and_receiving_large_messages.cs deleted file mode 100644 index 099ece45c..000000000 --- a/test/EventStore.Client.Streams.Tests/Append/sending_and_receiving_large_messages.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Grpc.Core; - -namespace EventStore.Client.Streams.Tests.Append; - -[Trait("Category", "Target:Stream")] -[Trait("Category", "Operation:Append")] -public class sending_and_receiving_large_messages(ITestOutputHelper output, sending_and_receiving_large_messages.CustomFixture fixture) - : EventStoreTests(output, fixture) { - [Fact] - public async Task over_the_hard_limit() { - var streamName = Fixture.GetStreamName(); - var largeEvent = Fixture.CreateTestEvents() - .Select(e => new EventData(e.EventId, "-", new byte[CustomFixture.MaximumSize + 1])); - - var ex = await Assert.ThrowsAsync( - () => Fixture.Streams.AppendToStreamAsync( - streamName, - StreamState.NoStream, - largeEvent - ) - ); - - Assert.Equal(StatusCode.ResourceExhausted, ex.StatusCode); - } - - public class CustomFixture() : EventStoreFixture(x => x.WithMaxAppendSize(MaximumSize)) { - public const int MaximumSize = 16 * 1024 * 1024 - 10000; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/AssemblyInfo.cs b/test/EventStore.Client.Streams.Tests/AssemblyInfo.cs deleted file mode 100644 index b0b47aa73..000000000 --- a/test/EventStore.Client.Streams.Tests/AssemblyInfo.cs +++ /dev/null @@ -1 +0,0 @@ -[assembly: CollectionBehavior(DisableTestParallelization = true)] \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/DependencyInjectionTests.cs b/test/EventStore.Client.Streams.Tests/DependencyInjectionTests.cs deleted file mode 100644 index 96512557b..000000000 --- a/test/EventStore.Client.Streams.Tests/DependencyInjectionTests.cs +++ /dev/null @@ -1,75 +0,0 @@ -using Grpc.Core.Interceptors; -using Microsoft.Extensions.DependencyInjection; - -namespace EventStore.Client.Streams.Tests; - -[Trait("Category", "UnitTest")] -public class DependencyInjectionTests { - [Fact] - public void Register() => - new ServiceCollection() - .AddEventStoreClient() - .BuildServiceProvider() - .GetRequiredService(); - - [Fact] - public void RegisterWithConnectionString() => - new ServiceCollection() - .AddEventStoreClient("esdb://localhost:2113?tls=false") - .BuildServiceProvider() - .GetRequiredService(); - - [Fact] - public void RegisterWithConnectionStringFactory() => - new ServiceCollection() - .AddEventStoreClient(provider => "esdb://localhost:2113?tls=false") - .BuildServiceProvider() - .GetRequiredService(); - - [Fact] - public void RegisterWithUri() => - new ServiceCollection() - .AddEventStoreClient(new Uri("https://localhost:1234")) - .BuildServiceProvider() - .GetRequiredService(); - - [Fact] - public void RegisterWithUriFactory() => - new ServiceCollection() - .AddEventStoreClient(provider => new Uri("https://localhost:1234")) - .BuildServiceProvider() - .GetRequiredService(); - - [Fact] - public void RegisterWithSettings() => - new ServiceCollection() - .AddEventStoreClient(settings => { }) - .BuildServiceProvider() - .GetRequiredService(); - - [Fact] - public void RegisterWithSettingsFactory() => - new ServiceCollection() - .AddEventStoreClient(provider => settings => { }) - .BuildServiceProvider() - .GetRequiredService(); - - [Fact] - public void RegisterInterceptors() { - var interceptorResolved = false; - new ServiceCollection() - .AddEventStoreClient() - .AddSingleton(() => interceptorResolved = true) - .AddSingleton() - .BuildServiceProvider() - .GetRequiredService(); - - Assert.True(interceptorResolved); - } - - delegate void ConstructorInvoked(); - - class TestInterceptor : Interceptor { - public TestInterceptor(ConstructorInvoked invoked) => invoked.Invoke(); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Diagnostics/StreamsTracingInstrumentationTests.cs b/test/EventStore.Client.Streams.Tests/Diagnostics/StreamsTracingInstrumentationTests.cs deleted file mode 100644 index 5a19c6b0d..000000000 --- a/test/EventStore.Client.Streams.Tests/Diagnostics/StreamsTracingInstrumentationTests.cs +++ /dev/null @@ -1,221 +0,0 @@ -// ReSharper disable ConditionalAccessQualifierIsNonNullableAccordingToAPIContract - -using EventStore.Client.Diagnostics; -using EventStore.Diagnostics.Tracing; - -namespace EventStore.Client.Streams.Tests.Diagnostics; - -[Trait("Category", "Diagnostics:Tracing")] -public class StreamsTracingInstrumentationTests(ITestOutputHelper output, DiagnosticsFixture fixture) - : EventStoreTests(output, fixture) { - [Fact] - public async Task AppendIsInstrumentedWithTracingAsExpected() { - var stream = Fixture.GetStreamName(); - - await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - Fixture.CreateTestEvents() - ); - - var activity = Fixture - .GetActivitiesForOperation(TracingConstants.Operations.Append, stream) - .SingleOrDefault() - .ShouldNotBeNull(); - - Fixture.AssertAppendActivityHasExpectedTags(activity, stream); - } - - [Fact] - public async Task AppendTraceIsTaggedWithErrorStatusOnException() { - var stream = Fixture.GetStreamName(); - - var actualException = await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - Fixture.CreateTestEventsThatThrowsException() - ).ShouldThrowAsync(); - - var activity = Fixture - .GetActivitiesForOperation(TracingConstants.Operations.Append, stream) - .SingleOrDefault() - .ShouldNotBeNull(); - - Fixture.AssertErroneousAppendActivityHasExpectedTags(activity, actualException); - } - - [Fact] - public async Task TracingContextIsInjectedWhenUserMetadataIsValidJsonObject() { - var stream = Fixture.GetStreamName(); - - await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - Fixture.CreateTestEvents(1, metadata: Fixture.CreateTestJsonMetadata()) - ); - - var activity = Fixture - .GetActivitiesForOperation(TracingConstants.Operations.Append, stream) - .SingleOrDefault() - .ShouldNotBeNull(); - - var readResult = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start) - .ToListAsync(); - - var tracingMetadata = readResult[0].OriginalEvent.Metadata.ExtractTracingMetadata(); - - tracingMetadata.ShouldNotBe(TracingMetadata.None); - tracingMetadata.TraceId.ShouldBe(activity.TraceId.ToString()); - tracingMetadata.SpanId.ShouldBe(activity.SpanId.ToString()); - } - - [Fact] - public async Task TracingContextIsNotInjectedWhenUserMetadataIsNotValidJsonObject() { - var stream = Fixture.GetStreamName(); - - var inputMetadata = "clearlynotavalidjsonobject"u8.ToArray(); - await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - Fixture.CreateTestEvents(1, metadata: inputMetadata) - ); - - var readResult = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start) - .ToListAsync(); - - var outputMetadata = readResult[0].OriginalEvent.Metadata.ToArray(); - outputMetadata.ShouldBe(inputMetadata); - } - - [Fact] - public async Task TracingContextIsInjectedWhenEventIsNotJsonButHasJsonMetadata() { - var stream = Fixture.GetStreamName(); - - var inputMetadata = Fixture.CreateTestJsonMetadata().ToArray(); - await Fixture.Streams.AppendToStreamAsync( - stream, - StreamState.NoStream, - Fixture.CreateTestEvents( - metadata: inputMetadata, - contentType: Constants.Metadata.ContentTypes.ApplicationOctetStream - ) - ); - - var readResult = await Fixture.Streams - .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start) - .ToListAsync(); - - var outputMetadata = readResult[0].OriginalEvent.Metadata.ToArray(); - outputMetadata.ShouldNotBe(inputMetadata); - - var appendActivities = Fixture.GetActivitiesForOperation(TracingConstants.Operations.Append, stream); - - appendActivities.ShouldNotBeEmpty(); - } - - [Fact] - public async Task json_metadata_event_is_traced_and_non_json_metadata_event_is_not_traced() { - var streamName = Fixture.GetStreamName(); - - var seedEvents = new[] { - Fixture.CreateTestEvent(metadata: Fixture.CreateTestJsonMetadata()), - Fixture.CreateTestEvent(metadata: Fixture.CreateTestNonJsonMetadata()) - }; - - var availableEvents = new HashSet(seedEvents.Select(x => x.EventId)); - - await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, seedEvents); - - await using var subscription = Fixture.Streams.SubscribeToStream(streamName, FromStream.Start); - await using var enumerator = subscription.Messages.GetAsyncEnumerator(); - - var appendActivities = Fixture - .GetActivitiesForOperation(TracingConstants.Operations.Append, streamName) - .ShouldNotBeNull(); - - Assert.True(await enumerator.MoveNextAsync()); - - Assert.IsType(enumerator.Current); - - await Subscribe(enumerator).WithTimeout(); - - var subscribeActivities = Fixture - .GetActivitiesForOperation(TracingConstants.Operations.Subscribe, streamName) - .ToArray(); - - appendActivities.ShouldHaveSingleItem(); - - subscribeActivities.ShouldHaveSingleItem(); - - subscribeActivities.First().ParentId.ShouldBe(appendActivities.First().Id); - - var jsonMetadataEvent = seedEvents.First(); - - Fixture.AssertSubscriptionActivityHasExpectedTags( - subscribeActivities.First(), - streamName, - jsonMetadataEvent.EventId.ToString() - ); - - return; - - async Task Subscribe(IAsyncEnumerator internalEnumerator) { - while (await internalEnumerator.MoveNextAsync()) { - if (internalEnumerator.Current is not StreamMessage.Event(var resolvedEvent)) - continue; - - availableEvents.Remove(resolvedEvent.Event.EventId); - - if (availableEvents.Count == 0) - return; - } - } - } - - [Fact] - [Trait("Category", "Special cases")] - public async Task should_not_trace_when_event_is_null() { - var category = Guid.NewGuid().ToString("N"); - var streamName = category + "-123"; - - var seedEvents = Fixture.CreateTestEvents(type: $"{category}-{Fixture.GetStreamName()}").ToArray(); - await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, seedEvents); - - await Fixture.Streams.DeleteAsync(streamName, StreamState.StreamExists); - - await using var subscription = Fixture.Streams.SubscribeToStream("$ce-" + category, FromStream.Start, resolveLinkTos: true); - - await using var enumerator = subscription.Messages.GetAsyncEnumerator(); - - Assert.True(await enumerator.MoveNextAsync()); - - Assert.IsType(enumerator.Current); - - await Subscribe().WithTimeout(); - - var appendActivities = Fixture - .GetActivitiesForOperation(TracingConstants.Operations.Append, streamName) - .ShouldNotBeNull(); - - var subscribeActivities = Fixture - .GetActivitiesForOperation(TracingConstants.Operations.Subscribe, "$ce-" + category) - .ToArray(); - - appendActivities.ShouldHaveSingleItem(); - subscribeActivities.ShouldBeEmpty(); - - return; - - async Task Subscribe() { - while (await enumerator.MoveNextAsync()) { - if (enumerator.Current is not StreamMessage.Event(var resolvedEvent)) - continue; - - if (resolvedEvent.Event?.EventType is "$metadata") - return; - } - } - } -} diff --git a/test/EventStore.Client.Streams.Tests/EventDataTests.cs b/test/EventStore.Client.Streams.Tests/EventDataTests.cs deleted file mode 100644 index 87ed00191..000000000 --- a/test/EventStore.Client.Streams.Tests/EventDataTests.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace EventStore.Client.Streams.Tests; - -[Trait("Category", "UnitTest")] -public class EventDataTests { - [Fact] - public void EmptyEventIdThrows() { - var ex = Assert.Throws( - () => new EventData(Uuid.Empty, "-", Array.Empty()) - ); - - Assert.Equal("eventId", ex.ParamName); - } - - [Fact] - public void MalformedContentTypeThrows() => - Assert.Throws(() => new EventData(Uuid.NewUuid(), "-", Array.Empty(), contentType: "application")); - - [Fact] - public void InvalidContentTypeThrows() { - var ex = Assert.Throws(() => new EventData(Uuid.NewUuid(), "-", Array.Empty(), contentType: "application/xml")); - Assert.Equal("contentType", ex.ParamName); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj b/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj deleted file mode 100644 index e0cf4e59d..000000000 --- a/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj +++ /dev/null @@ -1,9 +0,0 @@ - - - - CS0612;xUnit1031 - - - - - diff --git a/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj.DotSettings b/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj.DotSettings deleted file mode 100644 index 9176e378d..000000000 --- a/test/EventStore.Client.Streams.Tests/EventStore.Client.Streams.Tests.csproj.DotSettings +++ /dev/null @@ -1,12 +0,0 @@ - - False - True - False - False - True - False - True - True - True - True - False \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Security/Obsolete/SecurityFixture_obsolete.cs b/test/EventStore.Client.Streams.Tests/Security/Obsolete/SecurityFixture_obsolete.cs deleted file mode 100644 index 18b52be82..000000000 --- a/test/EventStore.Client.Streams.Tests/Security/Obsolete/SecurityFixture_obsolete.cs +++ /dev/null @@ -1,321 +0,0 @@ -using System.Runtime.CompilerServices; - -namespace EventStore.Client.Streams.Tests.Obsolete; - -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class SecurityFixture_obsolete : EventStoreFixture { - public const string NoAclStream = nameof(NoAclStream); - public const string ReadStream = nameof(ReadStream); - public const string WriteStream = nameof(WriteStream); - public const string MetaReadStream = nameof(MetaReadStream); - public const string MetaWriteStream = nameof(MetaWriteStream); - public const string AllStream = SystemStreams.AllStream; - public const string NormalAllStream = nameof(NormalAllStream); - public const string SystemAllStream = $"${nameof(SystemAllStream)}"; - public const string SystemAdminStream = $"${nameof(SystemAdminStream)}"; - public const string SystemAclStream = $"${nameof(SystemAclStream)}"; - - const int TimeoutMs = 1000; - - public SecurityFixture_obsolete() : base(x => x.WithoutDefaultCredentials()) { - OnSetup = async () => { - await Users.CreateUserWithRetry( - TestCredentials.TestUser1.Username!, - nameof(TestCredentials.TestUser1), - Array.Empty(), - TestCredentials.TestUser1.Password!, - TestCredentials.Root - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await Users.CreateUserWithRetry( - TestCredentials.TestUser2.Username!, - nameof(TestCredentials.TestUser2), - Array.Empty(), - TestCredentials.TestUser2.Password!, - TestCredentials.Root - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await Users.CreateUserWithRetry( - TestCredentials.TestAdmin.Username!, - nameof(TestCredentials.TestAdmin), - new[] { SystemRoles.Admins }, - TestCredentials.TestAdmin.Password!, - TestCredentials.Root - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await Given(); - await When(); - }; - } - - protected virtual async Task Given() { - await Streams.SetStreamMetadataAsync( - NoAclStream, - StreamState.NoStream, - new(), - userCredentials: TestCredentials.TestAdmin - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await Streams.SetStreamMetadataAsync( - ReadStream, - StreamState.NoStream, - new(acl: new(TestCredentials.TestUser1.Username)), - userCredentials: TestCredentials.TestAdmin - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await Streams.SetStreamMetadataAsync( - WriteStream, - StreamState.NoStream, - new(acl: new(writeRole: TestCredentials.TestUser1.Username)), - userCredentials: TestCredentials.TestAdmin - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await Streams.SetStreamMetadataAsync( - MetaReadStream, - StreamState.NoStream, - new(acl: new(metaReadRole: TestCredentials.TestUser1.Username)), - userCredentials: TestCredentials.TestAdmin - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await Streams.SetStreamMetadataAsync( - MetaWriteStream, - StreamState.NoStream, - new(acl: new(metaWriteRole: TestCredentials.TestUser1.Username)), - userCredentials: TestCredentials.TestAdmin - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await Streams.SetStreamMetadataAsync( - AllStream, - StreamState.Any, - new(acl: new(TestCredentials.TestUser1.Username)), - userCredentials: TestCredentials.TestAdmin - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await Streams.SetStreamMetadataAsync( - SystemAclStream, - StreamState.NoStream, - new( - acl: new( - writeRole: TestCredentials.TestUser1.Username, - readRole: TestCredentials.TestUser1.Username, - metaWriteRole: TestCredentials.TestUser1.Username, - metaReadRole: TestCredentials.TestUser1.Username - ) - ), - userCredentials: TestCredentials.TestAdmin - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await Streams.SetStreamMetadataAsync( - SystemAdminStream, - StreamState.NoStream, - new( - acl: new( - writeRole: SystemRoles.Admins, - readRole: SystemRoles.Admins, - metaWriteRole: SystemRoles.Admins, - metaReadRole: SystemRoles.Admins - ) - ), - userCredentials: TestCredentials.TestAdmin - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await Streams.SetStreamMetadataAsync( - NormalAllStream, - StreamState.NoStream, - new( - acl: new( - writeRole: SystemRoles.All, - readRole: SystemRoles.All, - metaWriteRole: SystemRoles.All, - metaReadRole: SystemRoles.All - ) - ), - userCredentials: TestCredentials.TestAdmin - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - await Streams.SetStreamMetadataAsync( - SystemAllStream, - StreamState.NoStream, - new( - acl: new( - writeRole: SystemRoles.All, - readRole: SystemRoles.All, - metaWriteRole: SystemRoles.All, - metaReadRole: SystemRoles.All - ) - ), - userCredentials: TestCredentials.TestAdmin - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - } - - protected virtual Task When() => Task.CompletedTask; - - public Task ReadEvent(string streamId, UserCredentials? userCredentials = default) => - Streams.ReadStreamAsync( - Direction.Forwards, - streamId, - StreamPosition.Start, - 1, - false, - userCredentials: userCredentials - ) - .ToArrayAsync() - .AsTask() - .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - public Task ReadStreamForward(string streamId, UserCredentials? userCredentials = default) => - Streams.ReadStreamAsync( - Direction.Forwards, - streamId, - StreamPosition.Start, - 1, - false, - userCredentials: userCredentials - ) - .ToArrayAsync() - .AsTask() - .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - public Task ReadStreamBackward(string streamId, UserCredentials? userCredentials = default) => - Streams.ReadStreamAsync( - Direction.Backwards, - streamId, - StreamPosition.Start, - 1, - false, - userCredentials: userCredentials - ) - .ToArrayAsync() - .AsTask() - .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - public Task AppendStream(string streamId, UserCredentials? userCredentials = default) => - Streams.AppendToStreamAsync( - streamId, - StreamState.Any, - CreateTestEvents(3), - userCredentials: userCredentials - ) - .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - public Task ReadAllForward(UserCredentials? userCredentials = default) => - Streams.ReadAllAsync( - Direction.Forwards, - Position.Start, - 1, - false, - userCredentials: userCredentials - ) - .ToArrayAsync() - .AsTask() - .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - public Task ReadAllBackward(UserCredentials? userCredentials = default) => - Streams - .ReadAllAsync( - Direction.Backwards, - Position.End, - 1, - false, - userCredentials: userCredentials - ) - .ToArrayAsync() - .AsTask() - .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - public Task ReadMeta(string streamId, UserCredentials? userCredentials = default) => - Streams.GetStreamMetadataAsync(streamId, userCredentials: userCredentials) - .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - public Task WriteMeta(string streamId, UserCredentials? userCredentials = default, string? role = default) => - Streams.SetStreamMetadataAsync( - streamId, - StreamState.Any, - new( - acl: new( - writeRole: role, - readRole: role, - metaWriteRole: role, - metaReadRole: role - ) - ), - userCredentials: userCredentials - ) - .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - [Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client", false)] - public async Task SubscribeToStreamObsolete(string streamId, UserCredentials? userCredentials = default) { - var source = new TaskCompletionSource(); - using (await Streams.SubscribeToStreamAsync( - streamId, - FromStream.Start, - (_, _, _) => { - source.TrySetResult(true); - return Task.CompletedTask; - }, - subscriptionDropped: (_, _, ex) => { - if (ex == null) - source.TrySetResult(true); - else - source.TrySetException(ex); - }, - userCredentials: userCredentials - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs))) { - await source.Task.WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - } - } - - public async Task SubscribeToStream(string streamId, UserCredentials? userCredentials = default) { - await using var subscription = - Streams.SubscribeToStream(streamId, FromStream.Start, userCredentials: userCredentials); - await subscription - .Messages.OfType().AnyAsync().AsTask() - .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - } - - [Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client", false)] - public async Task SubscribeToAllObsolete(UserCredentials? userCredentials = default) { - var source = new TaskCompletionSource(); - using (await Streams.SubscribeToAllAsync( - FromAll.Start, - (_, _, _) => { - source.TrySetResult(true); - return Task.CompletedTask; - }, - false, - (_, _, ex) => { - if (ex == null) - source.TrySetResult(true); - else - source.TrySetException(ex); - }, - userCredentials: userCredentials - ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs))) { - await source.Task.WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - } - } - - public async Task SubscribeToAll(UserCredentials? userCredentials = default) { - await using var subscription = - Streams.SubscribeToAll(FromAll.Start, userCredentials: userCredentials); - await subscription - .Messages.OfType().AnyAsync().AsTask() - .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - } - - public async Task CreateStreamWithMeta(StreamMetadata metadata, [CallerMemberName] string streamId = "") { - await Streams.SetStreamMetadataAsync( - streamId, - StreamState.NoStream, - metadata, - userCredentials: TestCredentials.TestAdmin - ) - .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - - return streamId; - } - - public Task DeleteStream(string streamId, UserCredentials? userCredentials = default) => - Streams.TombstoneAsync(streamId, StreamState.Any, userCredentials: userCredentials) - .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); -} diff --git a/test/EventStore.Client.Streams.Tests/Security/Obsolete/all_stream_with_no_acl_security_obsolete.cs b/test/EventStore.Client.Streams.Tests/Security/Obsolete/all_stream_with_no_acl_security_obsolete.cs deleted file mode 100644 index 40cdd81ef..000000000 --- a/test/EventStore.Client.Streams.Tests/Security/Obsolete/all_stream_with_no_acl_security_obsolete.cs +++ /dev/null @@ -1,37 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Obsolete; - -[Trait("Category", "Security")] -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class all_stream_with_no_acl_security_obsolete(ITestOutputHelper output, all_stream_with_no_acl_security_obsolete.CustomFixture fixture) : EventStoreTests(output, fixture) { - [Fact] - public async Task reading_and_subscribing_is_not_allowed_when_no_credentials_are_passed() { - await Assert.ThrowsAsync(() => Fixture.ReadAllForward()); - await Assert.ThrowsAsync(() => Fixture.ReadAllBackward()); - await Assert.ThrowsAsync(() => Fixture.ReadMeta(SecurityFixture_obsolete.AllStream)); - await Assert.ThrowsAsync(() => Fixture.SubscribeToAllObsolete()); - } - - [Fact] - public async Task reading_and_subscribing_is_not_allowed_for_usual_user() { - await Assert.ThrowsAsync(() => Fixture.ReadAllForward(TestCredentials.TestUser1)); - await Assert.ThrowsAsync(() => Fixture.ReadAllBackward(TestCredentials.TestUser1)); - await Assert.ThrowsAsync(() => Fixture.ReadMeta(SecurityFixture_obsolete.AllStream, TestCredentials.TestUser1)); - await Assert.ThrowsAsync(() => Fixture.SubscribeToAllObsolete(TestCredentials.TestUser1)); - } - - [Fact] - public async Task reading_and_subscribing_is_allowed_for_admin_user() { - await Fixture.ReadAllForward(TestCredentials.TestAdmin); - await Fixture.ReadAllBackward(TestCredentials.TestAdmin); - await Fixture.ReadMeta(SecurityFixture_obsolete.AllStream, TestCredentials.TestAdmin); - await Fixture.SubscribeToAllObsolete(TestCredentials.TestAdmin); - } - - public class CustomFixture : SecurityFixture_obsolete { - protected override async Task Given() { - await base.Given(); - - await Streams.SetStreamMetadataAsync(AllStream, StreamState.Any, new(), userCredentials: TestCredentials.Root); - } - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Security/Obsolete/overriden_system_stream_security_for_all_obsolete.cs b/test/EventStore.Client.Streams.Tests/Security/Obsolete/overriden_system_stream_security_for_all_obsolete.cs deleted file mode 100644 index 4593e39e0..000000000 --- a/test/EventStore.Client.Streams.Tests/Security/Obsolete/overriden_system_stream_security_for_all_obsolete.cs +++ /dev/null @@ -1,70 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Obsolete; - -[Trait("Category", "Security")] -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class overriden_system_stream_security_for_all_obsolete(ITestOutputHelper output, overriden_system_stream_security_for_all_obsolete.CustomFixture fixture) : EventStoreTests(output, fixture) { - [Fact] - public async Task operations_on_system_stream_succeeds_for_user() { - var stream = $"${Fixture.GetStreamName()}"; - await Fixture.AppendStream(stream, TestCredentials.TestUser1); - await Fixture.ReadEvent(stream, TestCredentials.TestUser1); - await Fixture.ReadStreamForward(stream, TestCredentials.TestUser1); - await Fixture.ReadStreamBackward(stream, TestCredentials.TestUser1); - - await Fixture.ReadMeta(stream, TestCredentials.TestUser1); - await Fixture.WriteMeta(stream, TestCredentials.TestUser1); - - await Fixture.SubscribeToStreamObsolete(stream, TestCredentials.TestUser1); - - await Fixture.DeleteStream(stream, TestCredentials.TestUser1); - } - - [AnonymousAccess.Fact] - public async Task operations_on_system_stream_fail_for_anonymous_user() { - var stream = $"${Fixture.GetStreamName()}"; - await Fixture.AppendStream(stream); - await Fixture.ReadEvent(stream); - await Fixture.ReadStreamForward(stream); - await Fixture.ReadStreamBackward(stream); - - await Fixture.ReadMeta(stream); - await Fixture.WriteMeta(stream); - - await Fixture.SubscribeToStreamObsolete(stream); - - await Fixture.DeleteStream(stream); - } - - [Fact] - public async Task operations_on_system_stream_succeed_for_admin() { - var stream = $"${Fixture.GetStreamName()}"; - await Fixture.AppendStream(stream, TestCredentials.TestAdmin); - - await Fixture.ReadEvent(stream, TestCredentials.TestAdmin); - await Fixture.ReadStreamForward(stream, TestCredentials.TestAdmin); - await Fixture.ReadStreamBackward(stream, TestCredentials.TestAdmin); - - await Fixture.ReadMeta(stream, TestCredentials.TestAdmin); - await Fixture.WriteMeta(stream, TestCredentials.TestAdmin); - - await Fixture.SubscribeToStreamObsolete(stream, TestCredentials.TestAdmin); - - await Fixture.DeleteStream(stream, TestCredentials.TestAdmin); - } - - public class CustomFixture : SecurityFixture_obsolete { - protected override Task When() { - var settings = new SystemSettings( - systemStreamAcl: new( - SystemRoles.All, - SystemRoles.All, - SystemRoles.All, - SystemRoles.All, - SystemRoles.All - ) - ); - - return Streams.SetSystemSettingsAsync(settings, userCredentials: TestCredentials.TestAdmin); - } - } -} diff --git a/test/EventStore.Client.Streams.Tests/Security/Obsolete/overriden_system_stream_security_obsolete.cs b/test/EventStore.Client.Streams.Tests/Security/Obsolete/overriden_system_stream_security_obsolete.cs deleted file mode 100644 index f36646be1..000000000 --- a/test/EventStore.Client.Streams.Tests/Security/Obsolete/overriden_system_stream_security_obsolete.cs +++ /dev/null @@ -1,87 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Obsolete; - -[Trait("Category", "Security")] -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class overriden_system_stream_security_obsolete(ITestOutputHelper output, overriden_system_stream_security_obsolete.CustomFixture fixture) : EventStoreTests(output, fixture) { - [Fact] - public async Task operations_on_system_stream_succeed_for_authorized_user() { - var stream = $"${Fixture.GetStreamName()}"; - await Fixture.AppendStream(stream, TestCredentials.TestUser1); - - await Fixture.ReadEvent(stream, TestCredentials.TestUser1); - await Fixture.ReadStreamForward(stream, TestCredentials.TestUser1); - await Fixture.ReadStreamBackward(stream, TestCredentials.TestUser1); - - await Fixture.ReadMeta(stream, TestCredentials.TestUser1); - await Fixture.WriteMeta(stream, TestCredentials.TestUser1); - - await Fixture.SubscribeToStreamObsolete(stream, TestCredentials.TestUser1); - - await Fixture.DeleteStream(stream, TestCredentials.TestUser1); - } - - [Fact] - public async Task operations_on_system_stream_fail_for_not_authorized_user() { - var stream = $"${Fixture.GetStreamName()}"; - await Assert.ThrowsAsync(() => Fixture.ReadEvent(stream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => Fixture.ReadStreamForward(stream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync( - () => - Fixture.ReadStreamBackward(stream, TestCredentials.TestUser2) - ); - - await Assert.ThrowsAsync(() => Fixture.AppendStream(stream, TestCredentials.TestUser2)); - - await Assert.ThrowsAsync(() => Fixture.ReadMeta(stream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => Fixture.WriteMeta(stream, TestCredentials.TestUser2)); - - await Assert.ThrowsAsync(() => Fixture.SubscribeToStreamObsolete(stream, TestCredentials.TestUser2)); - - await Assert.ThrowsAsync(() => Fixture.DeleteStream(stream, TestCredentials.TestUser2)); - } - - [Fact] - public async Task operations_on_system_stream_fail_for_anonymous_user() { - var stream = $"${Fixture.GetStreamName()}"; - await Assert.ThrowsAsync(() => Fixture.ReadEvent(stream)); - await Assert.ThrowsAsync(() => Fixture.ReadStreamForward(stream)); - await Assert.ThrowsAsync(() => Fixture.ReadStreamBackward(stream)); - - await Assert.ThrowsAsync(() => Fixture.AppendStream(stream)); - - await Assert.ThrowsAsync(() => Fixture.ReadMeta(stream)); - await Assert.ThrowsAsync(() => Fixture.WriteMeta(stream)); - - await Assert.ThrowsAsync(() => Fixture.SubscribeToStreamObsolete(stream)); - - await Assert.ThrowsAsync(() => Fixture.DeleteStream(stream)); - } - - [Fact] - public async Task operations_on_system_stream_succeed_for_admin() { - var stream = $"${Fixture.GetStreamName()}"; - await Fixture.AppendStream(stream, TestCredentials.TestAdmin); - - await Fixture.ReadEvent(stream, TestCredentials.TestAdmin); - await Fixture.ReadStreamForward(stream, TestCredentials.TestAdmin); - await Fixture.ReadStreamBackward(stream, TestCredentials.TestAdmin); - - await Fixture.ReadMeta(stream, TestCredentials.TestAdmin); - await Fixture.WriteMeta(stream, TestCredentials.TestAdmin); - - await Fixture.SubscribeToStreamObsolete(stream, TestCredentials.TestAdmin); - - await Fixture.DeleteStream(stream, TestCredentials.TestAdmin); - } - - public class CustomFixture : SecurityFixture_obsolete { - protected override Task When() { - var settings = new SystemSettings( - systemStreamAcl: new("user1", "user1", "user1", "user1", "user1"), - userStreamAcl: default - ); - - return Streams.SetSystemSettingsAsync(settings, userCredentials: TestCredentials.TestAdmin); - } - } -} diff --git a/test/EventStore.Client.Streams.Tests/Security/Obsolete/overriden_user_stream_security_obsolete.cs b/test/EventStore.Client.Streams.Tests/Security/Obsolete/overriden_user_stream_security_obsolete.cs deleted file mode 100644 index dcbd88fa1..000000000 --- a/test/EventStore.Client.Streams.Tests/Security/Obsolete/overriden_user_stream_security_obsolete.cs +++ /dev/null @@ -1,78 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Obsolete; - -[Trait("Category", "Security")] -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class overriden_user_stream_security_obsolete(ITestOutputHelper output, overriden_user_stream_security_obsolete.CustomFixture fixture) : EventStoreTests(output, fixture) { - [Fact] - public async Task operations_on_user_stream_succeeds_for_authorized_user() { - var stream = Fixture.GetStreamName(); - await Fixture.AppendStream(stream, TestCredentials.TestUser1); - - await Fixture.ReadEvent(stream, TestCredentials.TestUser1); - await Fixture.ReadStreamForward(stream, TestCredentials.TestUser1); - await Fixture.ReadStreamBackward(stream, TestCredentials.TestUser1); - - await Fixture.ReadMeta(stream, TestCredentials.TestUser1); - await Fixture.WriteMeta(stream, TestCredentials.TestUser1); - - await Fixture.SubscribeToStreamObsolete(stream, TestCredentials.TestUser1); - - await Fixture.DeleteStream(stream, TestCredentials.TestUser1); - } - - [Fact] - public async Task operations_on_user_stream_fail_for_not_authorized_user() { - var stream = Fixture.GetStreamName(); - await Assert.ThrowsAsync(() => Fixture.ReadEvent(stream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => Fixture.ReadStreamForward(stream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => Fixture.ReadStreamBackward(stream, TestCredentials.TestUser2)); - - await Assert.ThrowsAsync(() => Fixture.AppendStream(stream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => Fixture.ReadMeta(stream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => Fixture.WriteMeta(stream, TestCredentials.TestUser2)); - - await Assert.ThrowsAsync(() => Fixture.SubscribeToStreamObsolete(stream, TestCredentials.TestUser2)); - - await Assert.ThrowsAsync(() => Fixture.DeleteStream(stream, TestCredentials.TestUser2)); - } - - [Fact] - public async Task operations_on_user_stream_fail_for_anonymous_user() { - var stream = Fixture.GetStreamName(); - await Assert.ThrowsAsync(() => Fixture.ReadEvent(stream)); - await Assert.ThrowsAsync(() => Fixture.ReadStreamForward(stream)); - await Assert.ThrowsAsync(() => Fixture.ReadStreamBackward(stream)); - - await Assert.ThrowsAsync(() => Fixture.AppendStream(stream)); - await Assert.ThrowsAsync(() => Fixture.ReadMeta(stream)); - await Assert.ThrowsAsync(() => Fixture.WriteMeta(stream)); - - await Assert.ThrowsAsync(() => Fixture.SubscribeToStreamObsolete(stream)); - - await Assert.ThrowsAsync(() => Fixture.DeleteStream(stream)); - } - - [Fact] - public async Task operations_on_user_stream_succeed_for_admin() { - var stream = Fixture.GetStreamName(); - await Fixture.AppendStream(stream, TestCredentials.TestAdmin); - - await Fixture.ReadEvent(stream, TestCredentials.TestAdmin); - await Fixture.ReadStreamForward(stream, TestCredentials.TestAdmin); - await Fixture.ReadStreamBackward(stream, TestCredentials.TestAdmin); - - await Fixture.ReadMeta(stream, TestCredentials.TestAdmin); - await Fixture.WriteMeta(stream, TestCredentials.TestAdmin); - - await Fixture.SubscribeToStreamObsolete(stream, TestCredentials.TestAdmin); - - await Fixture.DeleteStream(stream, TestCredentials.TestAdmin); - } - - public class CustomFixture : SecurityFixture_obsolete { - protected override Task When() { - var settings = new SystemSettings(new("user1", "user1", "user1", "user1", "user1")); - return Streams.SetSystemSettingsAsync(settings, userCredentials: TestCredentials.TestAdmin); - } - } -} diff --git a/test/EventStore.Client.Streams.Tests/Security/Obsolete/subscribe_to_all_security_obsolete.cs b/test/EventStore.Client.Streams.Tests/Security/Obsolete/subscribe_to_all_security_obsolete.cs deleted file mode 100644 index b21cf66c6..000000000 --- a/test/EventStore.Client.Streams.Tests/Security/Obsolete/subscribe_to_all_security_obsolete.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Obsolete; - -[Trait("Category", "Security")] -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class subscribe_to_all_security_obsolete(ITestOutputHelper output, SecurityFixture_obsolete fixture) : EventStoreTests(output, fixture) { - [Fact] - public async Task subscribing_to_all_with_not_existing_credentials_is_not_authenticated() => - await Assert.ThrowsAsync(() => Fixture.SubscribeToAllObsolete(TestCredentials.TestBadUser)); - - [Fact] - public async Task subscribing_to_all_with_no_credentials_is_denied() => await Assert.ThrowsAsync(() => Fixture.SubscribeToAllObsolete()); - - [Fact] - public async Task subscribing_to_all_with_not_authorized_user_credentials_is_denied() => - await Assert.ThrowsAsync(() => Fixture.SubscribeToAllObsolete(TestCredentials.TestUser2)); - - [Fact] - public async Task subscribing_to_all_with_authorized_user_credentials_succeeds() => await Fixture.SubscribeToAllObsolete(TestCredentials.TestUser1); - - [Fact] - public async Task subscribing_to_all_with_admin_user_credentials_succeeds() => await Fixture.SubscribeToAllObsolete(TestCredentials.TestAdmin); -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Security/Obsolete/subscribe_to_stream_security_obsolete.cs b/test/EventStore.Client.Streams.Tests/Security/Obsolete/subscribe_to_stream_security_obsolete.cs deleted file mode 100644 index 409256650..000000000 --- a/test/EventStore.Client.Streams.Tests/Security/Obsolete/subscribe_to_stream_security_obsolete.cs +++ /dev/null @@ -1,75 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Obsolete; - -[Trait("Category", "Security")] -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class subscribe_to_stream_security_obsolete(ITestOutputHelper output, SecurityFixture_obsolete fixture) : EventStoreTests(output, fixture) { - [Fact] - public async Task subscribing_to_stream_with_not_existing_credentials_is_not_authenticated() => - await Assert.ThrowsAsync(() => Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.ReadStream, TestCredentials.TestBadUser)); - - [Fact] - public async Task subscribing_to_stream_with_no_credentials_is_denied() => - await Assert.ThrowsAsync(() => Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.ReadStream)); - - [Fact] - public async Task subscribing_to_stream_with_not_authorized_user_credentials_is_denied() => - await Assert.ThrowsAsync(() => Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.ReadStream, TestCredentials.TestUser2)); - - [Fact] - public async Task reading_stream_with_authorized_user_credentials_succeeds() { - await Fixture.AppendStream(SecurityFixture_obsolete.ReadStream, TestCredentials.TestUser1); - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.ReadStream, TestCredentials.TestUser1); - } - - [Fact] - public async Task reading_stream_with_admin_user_credentials_succeeds() { - await Fixture.AppendStream(SecurityFixture_obsolete.ReadStream, TestCredentials.TestAdmin); - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.ReadStream, TestCredentials.TestAdmin); - } - - [AnonymousAccess.Fact] - public async Task subscribing_to_no_acl_stream_succeeds_when_no_credentials_are_passed() { - await Fixture.AppendStream(SecurityFixture_obsolete.NoAclStream); - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.NoAclStream); - } - - [Fact] - public async Task subscribing_to_no_acl_stream_is_not_authenticated_when_not_existing_credentials_are_passed() => - await Assert.ThrowsAsync(() => Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.NoAclStream, TestCredentials.TestBadUser)); - - [Fact] - public async Task subscribing_to_no_acl_stream_succeeds_when_any_existing_user_credentials_are_passed() { - await Fixture.AppendStream(SecurityFixture_obsolete.NoAclStream, TestCredentials.TestUser1); - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.NoAclStream, TestCredentials.TestUser1); - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.NoAclStream, TestCredentials.TestUser2); - } - - [Fact] - public async Task subscribing_to_no_acl_stream_succeeds_when_admin_user_credentials_are_passed() { - await Fixture.AppendStream(SecurityFixture_obsolete.NoAclStream, TestCredentials.TestAdmin); - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.NoAclStream, TestCredentials.TestAdmin); - } - - [AnonymousAccess.Fact] - public async Task subscribing_to_all_access_normal_stream_succeeds_when_no_credentials_are_passed() { - await Fixture.AppendStream(SecurityFixture_obsolete.NormalAllStream); - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.NormalAllStream); - } - - [Fact] - public async Task subscribing_to_all_access_normal_stream_is_not_authenticated_when_not_existing_credentials_are_passed() => - await Assert.ThrowsAsync(() => Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.NormalAllStream, TestCredentials.TestBadUser)); - - [Fact] - public async Task subscribing_to_all_access_normal_stream_succeeds_when_any_existing_user_credentials_are_passed() { - await Fixture.AppendStream(SecurityFixture_obsolete.NormalAllStream, TestCredentials.TestUser1); - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.NormalAllStream, TestCredentials.TestUser1); - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.NormalAllStream, TestCredentials.TestUser2); - } - - [Fact] - public async Task subscribing_to_all_access_normal_streamm_succeeds_when_admin_user_credentials_are_passed() { - await Fixture.AppendStream(SecurityFixture_obsolete.NormalAllStream, TestCredentials.TestAdmin); - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.NormalAllStream, TestCredentials.TestAdmin); - } -} diff --git a/test/EventStore.Client.Streams.Tests/Security/Obsolete/system_stream_security_obsolete.cs b/test/EventStore.Client.Streams.Tests/Security/Obsolete/system_stream_security_obsolete.cs deleted file mode 100644 index 462696ff2..000000000 --- a/test/EventStore.Client.Streams.Tests/Security/Obsolete/system_stream_security_obsolete.cs +++ /dev/null @@ -1,146 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Obsolete; - -[Trait("Category", "Security")] -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class system_stream_security_obsolete(ITestOutputHelper output, SecurityFixture_obsolete fixture) : EventStoreTests(output, fixture) { - [Fact] - public async Task operations_on_system_stream_with_no_acl_set_fail_for_non_admin() { - await Assert.ThrowsAsync(() => Fixture.ReadEvent("$system-no-acl", TestCredentials.TestUser1)); - await Assert.ThrowsAsync(() => Fixture.ReadStreamForward("$system-no-acl", TestCredentials.TestUser1)); - - await Assert.ThrowsAsync(() => Fixture.ReadStreamBackward("$system-no-acl", TestCredentials.TestUser1)); - - await Assert.ThrowsAsync(() => Fixture.AppendStream("$system-no-acl", TestCredentials.TestUser1)); - - await Assert.ThrowsAsync(() => Fixture.ReadMeta("$system-no-acl", TestCredentials.TestUser1)); - await Assert.ThrowsAsync(() => Fixture.WriteMeta("$system-no-acl", TestCredentials.TestUser1)); - - await Assert.ThrowsAsync(() => Fixture.SubscribeToStreamObsolete("$system-no-acl", TestCredentials.TestUser1)); - } - - [Fact] - public async Task operations_on_system_stream_with_no_acl_set_succeed_for_admin() { - await Fixture.AppendStream("$system-no-acl", TestCredentials.TestAdmin); - - await Fixture.ReadEvent("$system-no-acl", TestCredentials.TestAdmin); - await Fixture.ReadStreamForward("$system-no-acl", TestCredentials.TestAdmin); - await Fixture.ReadStreamBackward("$system-no-acl", TestCredentials.TestAdmin); - - await Fixture.ReadMeta("$system-no-acl", TestCredentials.TestAdmin); - await Fixture.WriteMeta("$system-no-acl", TestCredentials.TestAdmin); - - await Fixture.SubscribeToStreamObsolete("$system-no-acl", TestCredentials.TestAdmin); - } - - [Fact] - public async Task operations_on_system_stream_with_acl_set_to_usual_user_fail_for_not_authorized_user() { - await Assert.ThrowsAsync(() => Fixture.ReadEvent(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => Fixture.ReadStreamForward(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => Fixture.ReadStreamBackward(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser2)); - - await Assert.ThrowsAsync(() => Fixture.AppendStream(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser2)); - - await Assert.ThrowsAsync(() => Fixture.ReadMeta(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => Fixture.WriteMeta(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser2, TestCredentials.TestUser1.Username)); - - await Assert.ThrowsAsync(() => Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser2)); - } - - [Fact] - public async Task operations_on_system_stream_with_acl_set_to_usual_user_succeed_for_that_user() { - await Fixture.AppendStream(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser1); - await Fixture.ReadEvent(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser1); - await Fixture.ReadStreamForward(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser1); - await Fixture.ReadStreamBackward(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser1); - - await Fixture.ReadMeta(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser1); - await Fixture.WriteMeta(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser1, TestCredentials.TestUser1.Username); - - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestUser1); - } - - [Fact] - public async Task operations_on_system_stream_with_acl_set_to_usual_user_succeed_for_admin() { - await Fixture.AppendStream(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestAdmin); - await Fixture.ReadEvent(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestAdmin); - await Fixture.ReadStreamForward(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestAdmin); - await Fixture.ReadStreamBackward(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestAdmin); - - await Fixture.ReadMeta(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestAdmin); - await Fixture.WriteMeta(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestAdmin, TestCredentials.TestUser1.Username); - - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.SystemAclStream, TestCredentials.TestAdmin); - } - - [Fact] - public async Task operations_on_system_stream_with_acl_set_to_admins_fail_for_usual_user() { - await Assert.ThrowsAsync(() => Fixture.ReadEvent(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestUser1)); - await Assert.ThrowsAsync(() => Fixture.ReadStreamForward(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestUser1)); - await Assert.ThrowsAsync( - () => - Fixture.ReadStreamBackward(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestUser1) - ); - - await Assert.ThrowsAsync(() => Fixture.AppendStream(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestUser1)); - - await Assert.ThrowsAsync(() => Fixture.ReadMeta(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestUser1)); - await Assert.ThrowsAsync( - () => - Fixture.WriteMeta(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestUser1, SystemRoles.Admins) - ); - - await Assert.ThrowsAsync(() => Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestUser1)); - } - - [Fact] - public async Task operations_on_system_stream_with_acl_set_to_admins_succeed_for_admin() { - await Fixture.AppendStream(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestAdmin); - await Fixture.ReadEvent(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestAdmin); - await Fixture.ReadStreamForward(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestAdmin); - await Fixture.ReadStreamBackward(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestAdmin); - - await Fixture.ReadMeta(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestAdmin); - await Fixture.WriteMeta(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestAdmin, SystemRoles.Admins); - - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.SystemAdminStream, TestCredentials.TestAdmin); - } - - [AnonymousAccess.Fact] - public async Task operations_on_system_stream_with_acl_set_to_all_succeed_for_not_authenticated_user() { - await Fixture.AppendStream(SecurityFixture_obsolete.SystemAllStream); - await Fixture.ReadEvent(SecurityFixture_obsolete.SystemAllStream); - await Fixture.ReadStreamForward(SecurityFixture_obsolete.SystemAllStream); - await Fixture.ReadStreamBackward(SecurityFixture_obsolete.SystemAllStream); - - await Fixture.ReadMeta(SecurityFixture_obsolete.SystemAllStream); - await Fixture.WriteMeta(SecurityFixture_obsolete.SystemAllStream, role: SystemRoles.All); - - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.SystemAllStream); - } - - [Fact] - public async Task operations_on_system_stream_with_acl_set_to_all_succeed_for_usual_user() { - await Fixture.AppendStream(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestUser1); - await Fixture.ReadEvent(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestUser1); - await Fixture.ReadStreamForward(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestUser1); - await Fixture.ReadStreamBackward(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestUser1); - - await Fixture.ReadMeta(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestUser1); - await Fixture.WriteMeta(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestUser1, SystemRoles.All); - - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestUser1); - } - - [Fact] - public async Task operations_on_system_stream_with_acl_set_to_all_succeed_for_admin() { - await Fixture.AppendStream(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestAdmin); - await Fixture.ReadEvent(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestAdmin); - await Fixture.ReadStreamForward(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestAdmin); - await Fixture.ReadStreamBackward(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestAdmin); - - await Fixture.ReadMeta(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestAdmin); - await Fixture.WriteMeta(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestAdmin, SystemRoles.All); - - await Fixture.SubscribeToStreamObsolete(SecurityFixture_obsolete.SystemAllStream, TestCredentials.TestAdmin); - } -} diff --git a/test/EventStore.Client.Streams.Tests/Serialization/is_json.cs b/test/EventStore.Client.Streams.Tests/Serialization/is_json.cs deleted file mode 100644 index d2b44a918..000000000 --- a/test/EventStore.Client.Streams.Tests/Serialization/is_json.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System.Runtime.CompilerServices; -using System.Text; - -namespace EventStore.Client.Streams.Tests.Serialization; - -[Trait("Category", "Serialization")] -public class is_json(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { - public static IEnumerable TestCases() { - var json = @"{""some"":""json""}"; - - yield return new object?[] { true, json, string.Empty }; - yield return new object?[] { true, string.Empty, json }; - yield return new object?[] { true, json, json }; - yield return new object?[] { false, json, string.Empty }; - yield return new object?[] { false, string.Empty, json }; - yield return new object?[] { false, json, json }; - } - - [Theory] - [MemberData(nameof(TestCases))] - public async Task is_preserved(bool isJson, string data, string metadata) { - var stream = GetStreamName(isJson, data, metadata); - var encoding = Encoding.UTF8; - var eventData = new EventData( - Uuid.NewUuid(), - "-", - encoding.GetBytes(data), - encoding.GetBytes(metadata), - isJson - ? Constants.Metadata.ContentTypes.ApplicationJson - : Constants.Metadata.ContentTypes.ApplicationOctetStream - ); - - await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, new[] { eventData }); - - var @event = await Fixture.Streams - .ReadStreamAsync( - Direction.Forwards, - stream, - StreamPosition.Start, - 1, - true - ) - .FirstOrDefaultAsync(); - - Assert.Equal( - isJson - ? Constants.Metadata.ContentTypes.ApplicationJson - : Constants.Metadata.ContentTypes.ApplicationOctetStream, - @event.Event.ContentType - ); - - Assert.Equal(data, encoding.GetString(@event.Event.Data.ToArray())); - Assert.Equal(metadata, encoding.GetString(@event.Event.Metadata.ToArray())); - } - - string GetStreamName(bool isJson, string data, string metadata, [CallerMemberName] string? testMethod = default) => - $"{Fixture.GetStreamName(testMethod)}_{isJson}_{(data == string.Empty ? "no_data" : "data")}_{(metadata == string.Empty ? "no_metadata" : "metadata")}"; -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionsFixture.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionsFixture.cs deleted file mode 100644 index 582344f98..000000000 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionsFixture.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace EventStore.Client.Streams.Tests.Subscriptions; - - -[Trait("Category", "Subscriptions")] -public class SubscriptionsFixture : EventStoreFixture { - public SubscriptionsFixture(): base(x => x.RunProjections()) { - OnSetup = async () => { - await Streams.SetStreamMetadataAsync( - SystemStreams.AllStream, - StreamState.NoStream, - new(acl: new(SystemRoles.All)), - userCredentials: TestCredentials.Root - ); - - await Streams.AppendToStreamAsync($"SubscriptionsFixture-Noise-{Guid.NewGuid():N}", StreamState.NoStream, CreateTestEvents(10)); - }; - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/reconnection.cs b/test/EventStore.Client.Streams.Tests/Subscriptions/reconnection.cs deleted file mode 100644 index 2dc9912e5..000000000 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/reconnection.cs +++ /dev/null @@ -1,178 +0,0 @@ -using Grpc.Core; -using static System.TimeSpan; - -namespace EventStore.Client.Streams.Tests.Subscriptions; - -[Trait("Category", "Subscriptions")] -[Obsolete] -public class @reconnection(ITestOutputHelper output, ReconnectionFixture fixture) : EventStoreTests(output, fixture) { - [Theory] - [InlineData(4, 5000, 0, 30000)] - public async Task when_the_connection_is_lost(int expectedNumberOfEvents, int reconnectDelayMs, int serviceRestartDelayMs, int testTimeoutMs) { - using var cancellator = new CancellationTokenSource().With(x => x.CancelAfter(testTimeoutMs)); - - var streamName = Fixture.GetStreamName(); - - // create backpressure by producing half of the events - await Fixture.ProduceEvents(streamName, expectedNumberOfEvents / 2, cancellationToken: cancellator.Token); - - // create subscription that will actually receive the first event and - // then wait for the service to be restarted - // but we are evil and will force the drop of the subscription muah ah ah - var consumeEvents = Fixture.ConsumeEvents( - streamName, - expectedNumberOfEvents, - FromMilliseconds(reconnectDelayMs), - cancellator.Token - ); - - // create chaos by pausing the service - await Fixture.RestartService(FromMilliseconds(serviceRestartDelayMs)); - - // produce the rest of the events to make it more interesting - await Fixture.ProduceEvents(streamName, expectedNumberOfEvents / 2, cancellationToken: cancellator.Token); - - // wait for the subscription to receive all events or timeout - await consumeEvents.ShouldNotThrowAsync(); - } -} - -public class ReconnectionFixture() - : EventStoreFixture( - x => x.RunInMemory(false) - .With(o => o.ClientSettings.ConnectivitySettings.DiscoveryInterval = FromMilliseconds(100)) - .With(o => o.ClientSettings.ConnectivitySettings.GossipTimeout = FromMilliseconds(100)) - ) -{ - public async Task ProduceEvents(string streamName, int numberOfEvents, StreamState? streamState = null, CancellationToken cancellationToken = default) { - while (!cancellationToken.IsCancellationRequested) { - try { - var result = await Streams.AppendToStreamAsync( - streamName, - streamState.GetValueOrDefault(StreamState.Any), - CreateTestEvents(numberOfEvents), - cancellationToken: cancellationToken - ); - - if (result is SuccessResult success) { - Log.Information( - "{NumberOfEvents} events produced to {StreamName}.", numberOfEvents, streamName - ); - - return; - } - - Log.Error( - "Failed to produce {NumberOfEvents} events to {StreamName}.", numberOfEvents, streamName - ); - - await Task.Delay(250); - } - catch (Exception ex) when ( ex is not OperationCanceledException) { - Log.Error( - ex, "Failed to produce {NumberOfEvents} events to {StreamName}.", numberOfEvents, streamName - ); - - await Task.Delay(250); - } - } - } - - public Task ConsumeEvents( - string streamName, - int expectedNumberOfEvents, - TimeSpan reconnectDelay, - CancellationToken cancellationToken - ) { - var receivedAllEvents = new TaskCompletionSource(); - - var receivedEventsCount = 0; - - _ = SubscribeToStream( - streamName, - checkpoint: null, - OnReceive(), - OnDrop(), - cancellationToken - ); - - return receivedAllEvents.Task; - - Func OnReceive() { - return re => { - receivedEventsCount++; - Log.Debug("{ReceivedEventsCount}/{ExpectedNumberOfEvents} events received.", receivedEventsCount, expectedNumberOfEvents); - - if (receivedEventsCount == expectedNumberOfEvents) { - Log.Information("Test complete. {ReceivedEventsCount}/{ExpectedNumberOfEvents} events received.", receivedEventsCount, expectedNumberOfEvents); - receivedAllEvents.TrySetResult(); - } - - return Task.CompletedTask; - }; - } - - Func> OnDrop() { - return async (reason, ex) => { - if (ex is RpcException { StatusCode: StatusCode.Unavailable or StatusCode.DeadlineExceeded }) { - Log.Warning("Transitive exception detected. Retrying connection in {reconnectDelayMs}ms.", reconnectDelay.TotalMilliseconds); - await Task.Delay(reconnectDelay); - return true; - } - - if (reason == SubscriptionDroppedReason.Disposed || ex is OperationCanceledException || ex is TaskCanceledException || ex is null) { - if (receivedEventsCount != expectedNumberOfEvents) - receivedAllEvents.TrySetException(new TimeoutException($"Test timeout detected. {receivedEventsCount}/{expectedNumberOfEvents} events received.", ex)); - else { - Log.Information("Test cancellation requested. {ReceivedEventsCount}/{ExpectedNumberOfEvents} events received.", receivedEventsCount, expectedNumberOfEvents); - receivedAllEvents.TrySetCanceled(cancellationToken); - } - - return false; - } - - Log.Fatal(ex, "Fatal exception detected. This is the end..."); - receivedAllEvents.SetException(ex); - - return false; - }; - } - } - - [Obsolete] - async Task SubscribeToStream( - string stream, - StreamPosition? checkpoint, - Func onReceive, - Func> onDrop, - CancellationToken cancellationToken - ) { - var start = checkpoint == null ? FromStream.Start : FromStream.After(checkpoint.Value); - - Log.Verbose("Attempting to start from checkpoint: {Checkpoint}.", checkpoint); - - try { - var sub = await Streams.SubscribeToStreamAsync( - streamName: stream, - start: start, - eventAppeared: async (s, re, ct) => { - await onReceive(re); - checkpoint = re.OriginalEventNumber; - Log.Verbose("Checkpoint Set: {Checkpoint}.", checkpoint); - }, - subscriptionDropped: async (s, reason, ex) => { - var resubscribe = await onDrop(reason, ex); - if (resubscribe) _ = SubscribeToStream(stream, checkpoint, onReceive, onDrop, cancellationToken); - }, - cancellationToken: cancellationToken - ); - } catch (Exception ex) { - var reason = ex is OperationCanceledException or TaskCanceledException - ? SubscriptionDroppedReason.Disposed - : SubscriptionDroppedReason.SubscriberError; - - var resubscribe = await onDrop(reason, ex); - if (resubscribe) _ = SubscribeToStream(stream, checkpoint, onReceive, onDrop, cancellationToken); - } - } -} diff --git a/test/EventStore.Client.Tests.Common/EventStore.Client.Tests.Common.csproj b/test/EventStore.Client.Tests.Common/EventStore.Client.Tests.Common.csproj deleted file mode 100644 index f666f3871..000000000 --- a/test/EventStore.Client.Tests.Common/EventStore.Client.Tests.Common.csproj +++ /dev/null @@ -1,72 +0,0 @@ - - - EventStore.Client.Tests - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - certs\%(RecursiveDir)/%(FileName)%(Extension) - Always - - - - - - Always - - - Always - - - Always - - - PreserveNewest - - - Always - - - Always - - - - - - - diff --git a/test/EventStore.Client.Tests.Common/EventStore.Client.Tests.Common.csproj.DotSettings b/test/EventStore.Client.Tests.Common/EventStore.Client.Tests.Common.csproj.DotSettings deleted file mode 100644 index 6ba62e1cd..000000000 --- a/test/EventStore.Client.Tests.Common/EventStore.Client.Tests.Common.csproj.DotSettings +++ /dev/null @@ -1,5 +0,0 @@ - - True - True - True - True \ No newline at end of file diff --git a/test/EventStore.Client.Tests.Common/Facts/SupportsPSToAllFact.cs b/test/EventStore.Client.Tests.Common/Facts/SupportsPSToAllFact.cs deleted file mode 100644 index 3f5d993fe..000000000 --- a/test/EventStore.Client.Tests.Common/Facts/SupportsPSToAllFact.cs +++ /dev/null @@ -1,18 +0,0 @@ -// ReSharper disable InconsistentNaming - -namespace EventStore.Client.Tests; - -[PublicAPI] -public class SupportsPSToAll { - const int SupportedFromMajorVersion = 21; - - static readonly string SkipMessage = $"Persistent Subscriptions to $all are not supported on" - + $" {EventStoreTestServer.Version?.ToString(3) ?? "unknown"}"; - - public static bool No => !Yes; - public static bool Yes => (EventStoreTestServer.Version?.Major ?? int.MaxValue) >= SupportedFromMajorVersion; - - public class FactAttribute() : Regression.FactAttribute(SupportedFromMajorVersion, SkipMessage); - - public class TheoryAttribute() : Regression.TheoryAttribute(SupportedFromMajorVersion, SkipMessage); -} \ No newline at end of file diff --git a/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreClientFixtureBase.cs b/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreClientFixtureBase.cs deleted file mode 100644 index 141a2a8da..000000000 --- a/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreClientFixtureBase.cs +++ /dev/null @@ -1,147 +0,0 @@ -using System.Diagnostics; -using System.Net; -using System.Reactive.Linq; -using System.Reactive.Subjects; -using System.Runtime.CompilerServices; -using System.Text; -using Serilog; -using Serilog.Events; -using Serilog.Extensions.Logging; -using Serilog.Formatting.Display; - -namespace EventStore.Client; - -public abstract class EventStoreClientFixtureBase : IAsyncLifetime { - public const string TestEventType = "-"; - - const string ConnectionStringSingle = "esdb://admin:changeit@localhost:2113/?tls=true&tlsVerifyCert=false"; - const string ConnectionStringCluster = "esdb://admin:changeit@localhost:2113,localhost:2112,localhost:2111?tls=true&tlsVerifyCert=false"; - - static readonly Subject LogEventSubject = new(); - - readonly IList _disposables; - - static EventStoreClientFixtureBase() => ConfigureLogging(); - - protected EventStoreClientFixtureBase( - EventStoreClientSettings? clientSettings, - IDictionary? env = null, bool noDefaultCredentials = false - ) { - _disposables = new List(); - - ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; - - var connectionString = GlobalEnvironment.UseCluster ? ConnectionStringCluster : ConnectionStringSingle; - Settings = clientSettings ?? EventStoreClientSettings.Create(connectionString); - - if (noDefaultCredentials) - Settings.DefaultCredentials = null; - - Settings.DefaultDeadline = Debugger.IsAttached - ? new TimeSpan?() - : TimeSpan.FromSeconds(30); - - var hostCertificatePath = Path.Combine( - Environment.CurrentDirectory, - GlobalEnvironment.UseCluster ? "certs-cluster" : "certs" - ); - - Settings.LoggerFactory ??= new SerilogLoggerFactory(); - - Settings.ConnectivitySettings.MaxDiscoverAttempts = 20; - Settings.ConnectivitySettings.DiscoveryInterval = TimeSpan.FromSeconds(1); - - if (GlobalEnvironment.UseExternalServer) - TestServer = new EventStoreTestServerExternal(); - else - TestServer = GlobalEnvironment.UseCluster - ? new EventStoreTestServerCluster(hostCertificatePath, Settings.ConnectivitySettings.ResolvedAddressOrDefault, env) - : new EventStoreTestServer(hostCertificatePath, Settings.ConnectivitySettings.ResolvedAddressOrDefault, env); - } - - public IEventStoreTestServer TestServer { get; } - protected EventStoreClientSettings Settings { get; } - - public Faker Faker { get; } = new(); - - public virtual async Task InitializeAsync() { - await TestServer.StartAsync().WithTimeout(TimeSpan.FromMinutes(5)); - await OnServerUpAsync().WithTimeout(TimeSpan.FromMinutes(5)); - await Given().WithTimeout(TimeSpan.FromMinutes(5)); - await When().WithTimeout(TimeSpan.FromMinutes(5)); - } - - public virtual Task DisposeAsync() { - foreach (var disposable in _disposables) - disposable.Dispose(); - - return TestServer.DisposeAsync().AsTask().WithTimeout(TimeSpan.FromMinutes(5)); - } - - static void ConfigureLogging() { - var loggerConfiguration = new LoggerConfiguration() - .Enrich.FromLogContext() - .MinimumLevel.Is(LogEventLevel.Verbose) - .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) - .MinimumLevel.Override("Grpc", LogEventLevel.Verbose) - .WriteTo.Observers(observable => observable.Subscribe(LogEventSubject.OnNext)) - .WriteTo.Seq("http://localhost:5341/", period: TimeSpan.FromMilliseconds(1)); - - Log.Logger = loggerConfiguration.CreateLogger(); - AppDomain.CurrentDomain.DomainUnload += (_, e) => Log.CloseAndFlush(); - } - - protected abstract Task OnServerUpAsync(); - protected abstract Task Given(); - protected abstract Task When(); - - public IEnumerable CreateTestEvents(int count = 1, string? type = null, int metadataSize = 1) => - Enumerable.Range(0, count).Select(index => CreateTestEvent(index, type ?? TestEventType, metadataSize)); - - protected static EventData CreateTestEvent(int index) => CreateTestEvent(index, TestEventType, 1); - - protected static EventData CreateTestEvent(int index, string type, int metadataSize) => - new( - Uuid.NewUuid(), - type, - Encoding.UTF8.GetBytes($@"{{""x"":{index}}}"), - Encoding.UTF8.GetBytes("\"" + new string('$', metadataSize) + "\"") - ); - - public string GetStreamName([CallerMemberName] string? testMethod = null) { - var type = GetType(); - - return $"{type.DeclaringType?.Name}.{testMethod ?? "unknown"}"; - } - - public void CaptureLogs(ITestOutputHelper testOutputHelper) { - const string captureCorrelationId = nameof(captureCorrelationId); - - var captureId = Guid.NewGuid(); - - var callContextData = new AsyncLocal<(string, Guid)> { - Value = (captureCorrelationId, captureId) - }; - - bool Filter(LogEvent logEvent) => callContextData.Value.Item2.Equals(captureId); - - var formatter = new MessageTemplateTextFormatter("{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] [{SourceContext}] {Message}"); - - var formatterWithException = - new MessageTemplateTextFormatter("{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] [{SourceContext}] {Message}{NewLine}{Exception}"); - - var subscription = LogEventSubject.Where(Filter).Subscribe( - logEvent => { - using var writer = new StringWriter(); - if (logEvent.Exception != null) - formatterWithException.Format(logEvent, writer); - else - formatter.Format(logEvent, writer); - - testOutputHelper.WriteLine(writer.ToString()); - } - ); - - _disposables.Add(subscription); - } -} diff --git a/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreTestServer.cs b/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreTestServer.cs deleted file mode 100644 index 20c8c0c93..000000000 --- a/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreTestServer.cs +++ /dev/null @@ -1,143 +0,0 @@ -using System.Net; -using System.Net.Http; -using Ductus.FluentDocker.Builders; -using Ductus.FluentDocker.Extensions; -using Ductus.FluentDocker.Model.Builders; -using Ductus.FluentDocker.Services; -using Ductus.FluentDocker.Services.Extensions; -using Polly; - -namespace EventStore.Client.Tests; - -public class EventStoreTestServer : IEventStoreTestServer { - static readonly string ContainerName = "es-client-dotnet-test"; - - static Version? _version; - readonly IContainerService _eventStore; - readonly string _hostCertificatePath; - readonly HttpClient _httpClient; - - public EventStoreTestServer( - string hostCertificatePath, - Uri address, - IDictionary? envOverrides - ) { - _hostCertificatePath = hostCertificatePath; - VerifyCertificatesExist(); - -#if NET - _httpClient = new HttpClient(new SocketsHttpHandler { - SslOptions = {RemoteCertificateValidationCallback = delegate { return true; }} - }) { - BaseAddress = address, - }; -#else - _httpClient = new HttpClient(new WinHttpHandler { - ServerCertificateValidationCallback = delegate { return true; } - }) { - BaseAddress = address, - }; -#endif - - var env = new Dictionary { - ["EVENTSTORE_DB_LOG_FORMAT"] = "V2", - ["EVENTSTORE_MEM_DB"] = "true", - ["EVENTSTORE_CHUNK_SIZE"] = (1024 * 1024 * 1024).ToString(), - ["EVENTSTORE_CERTIFICATE_FILE"] = "/etc/eventstore/certs/node/node.crt", - ["EVENTSTORE_CERTIFICATE_PRIVATE_KEY_FILE"] = "/etc/eventstore/certs/node/node.key", - ["EVENTSTORE_TRUSTED_ROOT_CERTIFICATES_PATH"] = "/etc/eventstore/certs/ca", - ["EVENTSTORE_LOG_LEVEL"] = "Verbose", - ["EVENTSTORE_STREAM_EXISTENCE_FILTER_SIZE"] = "10000", - ["EVENTSTORE_STREAM_INFO_CACHE_CAPACITY"] = "10000", - ["EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP"] = "false", - ["EVENTSTORE_DISABLE_LOG_FILE"] = "true" - }; - - foreach (var val in envOverrides ?? Enumerable.Empty>()) - env[val.Key] = val.Value; - - _eventStore = new Builder() - .UseContainer() - .UseImage(GlobalEnvironment.DockerImage) - .WithEnvironment(env.Select(pair => $"{pair.Key}={pair.Value}").ToArray()) - .WithName(ContainerName) - .MountVolume(_hostCertificatePath, "/etc/eventstore/certs", MountType.ReadOnly) - .ExposePort(2113, 2113) - //.WaitForHealthy(TimeSpan.FromSeconds(120)) - //.KeepContainer() - //.KeepRunning() - .Build(); - } - - public static Version Version => _version ??= GetVersion(); - - public async Task StartAsync(CancellationToken cancellationToken = default) { - _eventStore.Start(); - try { - await Policy.Handle() - .WaitAndRetryAsync(200, retryCount => TimeSpan.FromMilliseconds(100)) - .ExecuteAsync( - async () => { - using var response = await _httpClient.GetAsync("/health/live", cancellationToken); - if (response.StatusCode >= HttpStatusCode.BadRequest) - throw new($"Health check failed with status code: {response.StatusCode}."); - } - ); - } - catch (Exception) { - _eventStore.Dispose(); - throw; - } - } - - public void Stop() => _eventStore.Stop(); - - public ValueTask DisposeAsync() { - _httpClient?.Dispose(); - _eventStore?.Dispose(); - - return new ValueTask(Task.CompletedTask); - } - - static Version GetVersion() { - const string versionPrefix = "EventStoreDB version"; - - using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)); - using var eventstore = new Builder().UseContainer() - .UseImage(GlobalEnvironment.DockerImage) - .Command("--version") - .Build() - .Start(); - - using var log = eventstore.Logs(true, cts.Token); - foreach (var line in log.ReadToEnd()) { - if (line.StartsWith(versionPrefix) && - Version.TryParse(new string(ReadVersion(line[(versionPrefix.Length + 1)..]).ToArray()), out var version)) { - return version; - } - } - - throw new InvalidOperationException("Could not determine server version."); - - IEnumerable ReadVersion(string s) { - foreach (var c in s.TakeWhile(c => c == '.' || char.IsDigit(c))) { - yield return c; - } - } - } - - void VerifyCertificatesExist() { - var certificateFiles = new[] { - Path.Combine("ca", "ca.crt"), - Path.Combine("ca", "ca.key"), - Path.Combine("node", "node.crt"), - Path.Combine("node", "node.key") - }.Select(path => Path.Combine(_hostCertificatePath, path)); - - foreach (var file in certificateFiles) - if (!File.Exists(file)) - throw new InvalidOperationException( - $"Could not locate the certificates file {file} needed to run EventStoreDB. Please run the 'gencert' tool at the root of the repository." - ); - } -} diff --git a/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreTestServerCluster.cs b/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreTestServerCluster.cs deleted file mode 100644 index ceb263e15..000000000 --- a/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreTestServerCluster.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System.Net; -using System.Net.Http; -using Ductus.FluentDocker.Builders; -using Ductus.FluentDocker.Common; -using Ductus.FluentDocker.Services; -using Polly; - -namespace EventStore.Client; - -// [Obsolete("Use EventStoreTestCluster instead.", false)] -public class EventStoreTestServerCluster : IEventStoreTestServer { - readonly ICompositeService _eventStoreCluster; - readonly HttpClient _httpClient; - - public EventStoreTestServerCluster( - string hostCertificatePath, - Uri address, - IDictionary? envOverrides - ) { - envOverrides ??= new Dictionary(); - envOverrides["ES_CERTS_CLUSTER"] = hostCertificatePath; - - _eventStoreCluster = BuildCluster(envOverrides); - -#if NET - _httpClient = new HttpClient(new SocketsHttpHandler { - SslOptions = {RemoteCertificateValidationCallback = delegate { return true; }} - }) { - BaseAddress = address, - }; -#else - _httpClient = new HttpClient(new WinHttpHandler { - ServerCertificateValidationCallback = delegate { return true; } - }) { - BaseAddress = address, - }; -#endif - } - - public async Task StartAsync(CancellationToken cancellationToken = default) { - try { - // don't know why, sometimes the default network (e.g. net50_default) remains - // from previous cluster and prevents docker-compose up from executing successfully - Policy.Handle() - .WaitAndRetry( - 10, - retryCount => TimeSpan.FromSeconds(2), - (ex, _) => { - BuildCluster().Dispose(); - _eventStoreCluster.Start(); - } - ) - .Execute(() => { _eventStoreCluster.Start(); }); - - await Policy.Handle() - .WaitAndRetryAsync(200, retryCount => TimeSpan.FromMilliseconds(100)) - .ExecuteAsync( - async () => { - using var response = await _httpClient.GetAsync("/health/live", cancellationToken); - if (response.StatusCode >= HttpStatusCode.BadRequest) - throw new($"Health check failed with status code: {response.StatusCode}."); - } - ); - } - catch (Exception) { - _eventStoreCluster.Dispose(); - throw; - } - } - - public void Stop() => _eventStoreCluster.Stop(); - - public ValueTask DisposeAsync() { - _eventStoreCluster.Dispose(); - return new(Task.CompletedTask); - } - - ICompositeService BuildCluster(IDictionary? envOverrides = null) { - var env = GlobalEnvironment - .GetEnvironmentVariables(envOverrides) - .Select(pair => $"{pair.Key}={pair.Value}") - .ToArray(); - - return new Builder() - .UseContainer() - .UseCompose() - .WithEnvironment(env) - .FromFile("docker-compose.yml") - .ForceRecreate() - .RemoveOrphans() - .Build(); - } -} diff --git a/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreTestServerExternal.cs b/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreTestServerExternal.cs deleted file mode 100644 index 19b866a63..000000000 --- a/test/EventStore.Client.Tests.Common/Fixtures/Base/EventStoreTestServerExternal.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace EventStore.Client; - -public class EventStoreTestServerExternal : IEventStoreTestServer { - public Task StartAsync(CancellationToken cancellationToken = default) => Task.CompletedTask; - public void Stop() { } - - public ValueTask DisposeAsync() => new ValueTask(Task.CompletedTask); -} diff --git a/test/EventStore.Client.Tests.Common/Fixtures/Base/IEventStoreTestServer.cs b/test/EventStore.Client.Tests.Common/Fixtures/Base/IEventStoreTestServer.cs deleted file mode 100644 index 2d467835d..000000000 --- a/test/EventStore.Client.Tests.Common/Fixtures/Base/IEventStoreTestServer.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace EventStore.Client; - -public interface IEventStoreTestServer : IAsyncDisposable { - Task StartAsync(CancellationToken cancellationToken = default); - void Stop(); -} \ No newline at end of file diff --git a/test/EventStore.Client.Tests.Common/Fixtures/DiagnosticsFixture.cs b/test/EventStore.Client.Tests.Common/Fixtures/DiagnosticsFixture.cs deleted file mode 100644 index 549093654..000000000 --- a/test/EventStore.Client.Tests.Common/Fixtures/DiagnosticsFixture.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System.Collections.Concurrent; -using System.Diagnostics; -using EventStore.Client.Diagnostics; -using EventStore.Diagnostics; -using EventStore.Diagnostics.Telemetry; -using EventStore.Diagnostics.Tracing; - -namespace EventStore.Client.Tests; - -[PublicAPI] -public class DiagnosticsFixture : EventStoreFixture { - readonly ConcurrentDictionary<(string Operation, string Stream), List> _activities = []; - - public DiagnosticsFixture() : base(x => x.RunProjections()) { - var diagnosticActivityListener = new ActivityListener { - ShouldListenTo = source => source.Name == EventStoreClientDiagnostics.InstrumentationName, - Sample = (ref ActivityCreationOptions _) => ActivitySamplingResult.AllDataAndRecorded, - ActivityStopped = activity => { - var operation = (string?)activity.GetTagItem(TelemetryTags.Database.Operation); - var stream = (string?)activity.GetTagItem(TelemetryTags.EventStore.Stream); - - if (operation is null || stream is null) - return; - - _activities.AddOrUpdate( - (operation, stream), - _ => [activity], - (_, activities) => { - activities.Add(activity); - return activities; - } - ); - } - }; - - OnSetup = () => { - ActivitySource.AddActivityListener(diagnosticActivityListener); - return Task.CompletedTask; - }; - - OnTearDown = () => { - diagnosticActivityListener.Dispose(); - return Task.CompletedTask; - }; - } - - public List GetActivitiesForOperation(string operation, string stream) => - _activities.TryGetValue((operation, stream), out var activities) ? activities : []; - - public void AssertAppendActivityHasExpectedTags(Activity activity, string stream) { - var expectedTags = new Dictionary { - { TelemetryTags.Database.System, EventStoreClientDiagnostics.InstrumentationName }, - { TelemetryTags.Database.Operation, TracingConstants.Operations.Append }, - { TelemetryTags.EventStore.Stream, stream }, - { TelemetryTags.Database.User, TestCredentials.Root.Username }, - { TelemetryTags.Otel.StatusCode, ActivityStatusCodeHelper.OkStatusCodeTagValue } - }; - - foreach (var tag in expectedTags) - activity.Tags.ShouldContain(tag); - } - - public void AssertErroneousAppendActivityHasExpectedTags(Activity activity, Exception actualException) { - var expectedTags = new Dictionary { - { TelemetryTags.Otel.StatusCode, ActivityStatusCodeHelper.ErrorStatusCodeTagValue } - }; - - foreach (var tag in expectedTags) - activity.Tags.ShouldContain(tag); - - var actualEvent = activity.Events.ShouldHaveSingleItem(); - - actualEvent.Name.ShouldBe(TelemetryTags.Exception.EventName); - actualEvent.Tags.ShouldContain( - new KeyValuePair(TelemetryTags.Exception.Type, actualException.GetType().FullName) - ); - - actualEvent.Tags.ShouldContain( - new KeyValuePair(TelemetryTags.Exception.Message, actualException.Message) - ); - - actualEvent.Tags.Any(x => x.Key == TelemetryTags.Exception.Stacktrace).ShouldBeTrue(); - } - - public void AssertSubscriptionActivityHasExpectedTags( - Activity activity, - string stream, - string eventId, - string? subscriptionId = null - ) { - var expectedTags = new Dictionary { - { TelemetryTags.Database.System, EventStoreClientDiagnostics.InstrumentationName }, - { TelemetryTags.Database.Operation, TracingConstants.Operations.Subscribe }, - { TelemetryTags.EventStore.Stream, stream }, - { TelemetryTags.EventStore.EventId, eventId }, - { TelemetryTags.EventStore.EventType, TestEventType }, - { TelemetryTags.Database.User, TestCredentials.Root.Username } - }; - - if (subscriptionId != null) - expectedTags[TelemetryTags.EventStore.SubscriptionId] = subscriptionId; - - foreach (var tag in expectedTags) { - activity.Tags.ShouldContain(tag); - } - } -} diff --git a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.cs b/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.cs deleted file mode 100644 index 50faebf7a..000000000 --- a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.cs +++ /dev/null @@ -1,222 +0,0 @@ -using System.Net; -using Ductus.FluentDocker.Builders; -using Ductus.FluentDocker.Extensions; -using Ductus.FluentDocker.Services.Extensions; -using EventStore.Client.Tests.FluentDocker; -using Serilog; -using static System.TimeSpan; - -namespace EventStore.Client.Tests; - -public record EventStoreFixtureOptions( - EventStoreClientSettings ClientSettings, - IDictionary Environment -) { - public EventStoreFixtureOptions RunInMemory(bool runInMemory = true) => - this with { Environment = Environment.With(x => x["EVENTSTORE_MEM_DB"] = runInMemory.ToString()) }; - - public EventStoreFixtureOptions RunProjections(bool runProjections = true) => - this with { - Environment = Environment.With( - x => { - x["EVENTSTORE_START_STANDARD_PROJECTIONS"] = runProjections.ToString(); - x["EVENTSTORE_RUN_PROJECTIONS"] = runProjections ? "All" : "None"; - } - ) - }; - - public EventStoreFixtureOptions WithoutDefaultCredentials() => - this with { ClientSettings = ClientSettings.With(x => x.DefaultCredentials = null) }; - - public EventStoreFixtureOptions WithMaxAppendSize(uint maxAppendSize) => - this with { Environment = Environment.With(x => x["EVENTSTORE_MAX_APPEND_SIZE"] = $"{maxAppendSize}") }; -} - -public delegate EventStoreFixtureOptions ConfigureFixture(EventStoreFixtureOptions options); - -[PublicAPI] -public partial class EventStoreFixture : IAsyncLifetime, IAsyncDisposable { - static readonly ILogger Logger; - - static EventStoreFixture() { - Logging.Initialize(); - Logger = Serilog.Log.ForContext(); - - ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; - } - - public EventStoreFixture() : this(options => options) { } - - protected EventStoreFixture(ConfigureFixture configure) { - // TODO SS: should I verify the certificates exist here? - if (GlobalEnvironment.UseExternalServer) { - Options = new(new(), new Dictionary()); - Service = new TestBypassService(); - } - - if (GlobalEnvironment.UseCluster) { - Options = configure(EventStoreTestCluster.DefaultOptions()); - Service = new EventStoreTestCluster(Options); - } else { - Options = configure(EventStoreTestNode.DefaultOptions()); - Service = new EventStoreTestNode(Options); - } - } - - List TestRuns { get; } = new(); - - public ILogger Log => Logger; - - 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!; - public EventStoreProjectionManagementClient Projections { get; private set; } = null!; - public EventStorePersistentSubscriptionsClient Subscriptions { get; private set; } = null!; - public EventStoreOperationsClient Operations { get; private set; } = null!; - - public Func OnSetup { get; init; } = () => Task.CompletedTask; - public Func OnTearDown { get; init; } = () => Task.CompletedTask; - - /// - /// must test this - /// - public EventStoreClientSettings ClientSettings => - new() { - Interceptors = Options.ClientSettings.Interceptors, - ConnectionName = Options.ClientSettings.ConnectionName, - CreateHttpMessageHandler = Options.ClientSettings.CreateHttpMessageHandler, - LoggerFactory = Options.ClientSettings.LoggerFactory, - ChannelCredentials = Options.ClientSettings.ChannelCredentials, - OperationOptions = Options.ClientSettings.OperationOptions, - ConnectivitySettings = Options.ClientSettings.ConnectivitySettings, - DefaultCredentials = Options.ClientSettings.DefaultCredentials, - DefaultDeadline = Options.ClientSettings.DefaultDeadline - }; - - InterlockedBoolean WarmUpCompleted { get; } = new InterlockedBoolean(); - SemaphoreSlim WarmUpGatekeeper { get; } = new(1, 1); - - public void CaptureTestRun(ITestOutputHelper outputHelper) { - var testRunId = Logging.CaptureLogs(outputHelper); - TestRuns.Add(testRunId); - Logger.Information(">>> Test Run {TestRunId} {Operation} <<<", testRunId, "starting"); - Service.ReportStatus(); - } - - public async Task InitializeAsync() { - await Service.Start(); - - EventStoreVersion = GetEventStoreVersion(); - EventStoreHasLastStreamPosition = (EventStoreVersion?.Major ?? int.MaxValue) >= 21; - - await WarmUpGatekeeper.WaitAsync(); - - try { - if (!WarmUpCompleted.CurrentValue) { - Logger.Warning("*** Warmup started ***"); - - await Task.WhenAll( - InitClient(async x => Users = await x.WarmUp()), - InitClient(async x => Streams = await x.WarmUp()), - InitClient( - async x => Projections = await x.WarmUp(), - Options.Environment["EVENTSTORE_RUN_PROJECTIONS"] != "None" - ), - InitClient(async x => Subscriptions = await x.WarmUp()), - InitClient(async x => Operations = await x.WarmUp()) - ); - - WarmUpCompleted.EnsureCalledOnce(); - - Logger.Warning("*** Warmup completed ***"); - } else { - Logger.Information("*** Warmup skipped ***"); - } - } finally { - WarmUpGatekeeper.Release(); - } - - await OnSetup(); - - return; - - async Task InitClient(Func action, bool execute = true) where T : EventStoreClientBase { - if (!execute) return default(T)!; - - var client = (Activator.CreateInstance(typeof(T), new object?[] { ClientSettings }) as T)!; - await action(client); - return client; - } - - static Version GetEventStoreVersion() { - const string versionPrefix = "EventStoreDB version"; - - using var cancellator = new CancellationTokenSource(FromSeconds(30)); - using var eventstore = new Builder() - .UseContainer() - .UseImage(GlobalEnvironment.DockerImage) - .Command("--version") - .Build() - .Start(); - - using var log = eventstore.Logs(true, cancellator.Token); - foreach (var line in log.ReadToEnd()) { - if (line.StartsWith(versionPrefix) && - Version.TryParse( - new string(ReadVersion(line[(versionPrefix.Length + 1)..]).ToArray()), - out var version - )) { - return version; - } - } - - throw new InvalidOperationException("Could not determine server version."); - - IEnumerable ReadVersion(string s) { - foreach (var c in s.TakeWhile(c => c == '.' || char.IsDigit(c))) { - yield return c; - } - } - } - } - - public async Task DisposeAsync() { - try { - await OnTearDown(); - } catch { - // ignored - } - - await Service.DisposeAsync().AsTask().WithTimeout(FromMinutes(5)); - - foreach (var testRunId in TestRuns) - Logging.ReleaseLogs(testRunId); - } - - async ValueTask IAsyncDisposable.DisposeAsync() => await DisposeAsync(); -} - -[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; diff --git a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestCluster.cs b/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestCluster.cs deleted file mode 100644 index ad8246843..000000000 --- a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestCluster.cs +++ /dev/null @@ -1,52 +0,0 @@ -using Ductus.FluentDocker.Builders; -using EventStore.Client.Tests.FluentDocker; -using Serilog; -using Serilog.Extensions.Logging; - -namespace EventStore.Client.Tests; - -public class EventStoreTestCluster(EventStoreFixtureOptions options) : TestCompositeService { - EventStoreFixtureOptions Options { get; } = options; - - public static EventStoreFixtureOptions DefaultOptions() { - const string connString = "esdb://localhost:2113,localhost:2112,localhost:2111?tls=true&tlsVerifyCert=false"; - - var defaultSettings = EventStoreClientSettings - .Create(connString) - .With(x => x.LoggerFactory = new SerilogLoggerFactory(Log.Logger)) - .With(x => x.DefaultDeadline = Application.DebuggerIsAttached ? new TimeSpan?() : TimeSpan.FromSeconds(30)) - .With(x => x.ConnectivitySettings.MaxDiscoverAttempts = 30) - .With(x => x.ConnectivitySettings.DiscoveryInterval = TimeSpan.FromSeconds(1)); - - var defaultEnvironment = new Dictionary(GlobalEnvironment.Variables) { - ["ES_CERTS_CLUSTER"] = Path.Combine(Environment.CurrentDirectory, "certs-cluster"), - ["EVENTSTORE_CLUSTER_SIZE"] = "3", - ["EVENTSTORE_INT_TCP_PORT"] = "1112", - ["EVENTSTORE_HTTP_PORT"] = "2113", - ["EVENTSTORE_DISCOVER_VIA_DNS"] = "false", - ["EVENTSTORE_STREAM_EXISTENCE_FILTER_SIZE"] = "10000", - ["EVENTSTORE_STREAM_INFO_CACHE_CAPACITY"] = "10000" - }; - - return new(defaultSettings, defaultEnvironment); - } - - protected override CompositeBuilder Configure() { - var env = Options.Environment.Select(pair => $"{pair.Key}={pair.Value}").ToArray(); - - var builder = new Builder() - .UseContainer() - .FromComposeFile("docker-compose.yml") - .ServiceName("esdb-test-cluster") - .WithEnvironment(env) - .RemoveOrphans() - .NoRecreate() - .KeepRunning(); - - return builder; - } - - protected override async Task OnServiceStarted() { - await Service.WaitUntilNodesAreHealthy("esdb-node", TimeSpan.FromSeconds(60)); - } -} diff --git a/test/EventStore.Client.Tests.Common/Fixtures/InsecureClientTestFixture.cs b/test/EventStore.Client.Tests.Common/Fixtures/InsecureClientTestFixture.cs deleted file mode 100644 index 33407d177..000000000 --- a/test/EventStore.Client.Tests.Common/Fixtures/InsecureClientTestFixture.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace EventStore.Client.Tests; - -/// -/// The clients dont have default credentials set. -/// -[PublicAPI] -public class InsecureClientTestFixture() : EventStoreFixture(x => x.WithoutDefaultCredentials()); \ No newline at end of file diff --git a/test/EventStore.Client.Tests.Common/Fixtures/RunInMemoryTestFixture.cs b/test/EventStore.Client.Tests.Common/Fixtures/RunInMemoryTestFixture.cs deleted file mode 100644 index 61cfbc77c..000000000 --- a/test/EventStore.Client.Tests.Common/Fixtures/RunInMemoryTestFixture.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace EventStore.Client.Tests; - -[PublicAPI] -public class RunInMemoryTestFixture() : EventStoreFixture(x => x.RunInMemory()); \ No newline at end of file diff --git a/test/EventStore.Client.Tests.Common/Fixtures/RunProjectionsTestFixture.cs b/test/EventStore.Client.Tests.Common/Fixtures/RunProjectionsTestFixture.cs deleted file mode 100644 index cb42cc1db..000000000 --- a/test/EventStore.Client.Tests.Common/Fixtures/RunProjectionsTestFixture.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace EventStore.Client.Tests; - -[PublicAPI] -public class RunProjectionsTestFixture() : EventStoreFixture(x => x.RunProjections()); \ No newline at end of file diff --git a/test/EventStore.Client.Tests.Common/FluentDocker/FluentDockerBuilderExtensions.cs b/test/EventStore.Client.Tests.Common/FluentDocker/FluentDockerBuilderExtensions.cs deleted file mode 100644 index 782ab7696..000000000 --- a/test/EventStore.Client.Tests.Common/FluentDocker/FluentDockerBuilderExtensions.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Reflection; -using Ductus.FluentDocker.Builders; -using Ductus.FluentDocker.Model.Compose; -using Ductus.FluentDocker.Services; -using Ductus.FluentDocker.Services.Impl; - -namespace EventStore.Client.Tests.FluentDocker; - -public static class FluentDockerBuilderExtensions { - public static CompositeBuilder OverrideConfiguration(this CompositeBuilder compositeBuilder, Action configure) { - configure(GetInternalConfig(compositeBuilder)); - return compositeBuilder; - - static DockerComposeConfig GetInternalConfig(CompositeBuilder compositeBuilder) => - (DockerComposeConfig)typeof(CompositeBuilder) - .GetField("_config", BindingFlags.NonPublic | BindingFlags.Instance)! - .GetValue(compositeBuilder)!; - } - - public static DockerComposeConfig Configuration(this ICompositeService service) => - (DockerComposeConfig)typeof(DockerComposeCompositeService) - .GetProperty("Config", BindingFlags.NonPublic | BindingFlags.Instance)! - .GetValue(service)!; -} \ No newline at end of file diff --git a/test/EventStore.Client.Tests/EventStore.Client.Tests.csproj b/test/EventStore.Client.Tests/EventStore.Client.Tests.csproj deleted file mode 100644 index 494e5e243..000000000 --- a/test/EventStore.Client.Tests/EventStore.Client.Tests.csproj +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers - - - - - - - diff --git a/test/EventStore.Client.Tests/EventStoreClientOperationOptionsTests.cs b/test/EventStore.Client.Tests/EventStoreClientOperationOptionsTests.cs deleted file mode 100644 index baf9bf5b3..000000000 --- a/test/EventStore.Client.Tests/EventStoreClientOperationOptionsTests.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace EventStore.Client.Tests; - -public class EventStoreClientOperationOptionsTests { - [Fact] - public void setting_options_on_clone_should_not_modify_original() { - var options = EventStoreClientOperationOptions.Default; - - var clonedOptions = options.Clone(); - clonedOptions.BatchAppendSize = int.MaxValue; - - Assert.Equal(options.BatchAppendSize, EventStoreClientOperationOptions.Default.BatchAppendSize); - Assert.Equal(int.MaxValue, clonedOptions.BatchAppendSize); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Tests/GrpcServerCapabilitiesClientTests.cs b/test/EventStore.Client.Tests/GrpcServerCapabilitiesClientTests.cs deleted file mode 100644 index 2b13cf13b..000000000 --- a/test/EventStore.Client.Tests/GrpcServerCapabilitiesClientTests.cs +++ /dev/null @@ -1,102 +0,0 @@ -#if NET -using System.Net; -using EventStore.Client.ServerFeatures; -using Grpc.Core; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.TestHost; -using Microsoft.Extensions.DependencyInjection; - -namespace EventStore.Client.Tests; - -public class GrpcServerCapabilitiesClientTests { - public static IEnumerable ExpectedResultsCases() { - yield return new object?[] { new SupportedMethods(), new ServerCapabilities() }; - yield return new object?[] { - new SupportedMethods { - Methods = { - new SupportedMethod { - ServiceName = "event_store.client.streams.streams", - MethodName = "batchappend" - } - } - }, - new ServerCapabilities(true) - }; - - yield return new object?[] { - new SupportedMethods { - Methods = { - new SupportedMethod { - ServiceName = "event_store.client.persistent_subscriptions.persistentsubscriptions", - MethodName = "read", - Features = { - "all" - } - } - } - }, - new ServerCapabilities(SupportsPersistentSubscriptionsToAll: true) - }; - - yield return new object?[] { - new SupportedMethods { - Methods = { - new SupportedMethod { - ServiceName = "event_store.client.persistent_subscriptions.persistentsubscriptions", - MethodName = "read" - } - } - }, - new ServerCapabilities() - }; - } - - [Theory] - [MemberData(nameof(ExpectedResultsCases))] - internal async Task GetAsyncReturnsExpectedResults( - SupportedMethods supportedMethods, - ServerCapabilities expected - ) { - using var kestrel = new TestServer( - new WebHostBuilder() - .ConfigureServices( - services => services - .AddRouting() - .AddGrpc().Services - .AddSingleton(new FakeServerFeatures(supportedMethods)) - ) - .Configure( - app => app - .UseRouting() - .UseEndpoints(ep => ep.MapGrpcService()) - ) - ); - - var sut = new GrpcServerCapabilitiesClient(new()); - - var actual = - await sut.GetAsync( - ChannelFactory - .CreateChannel( - new() { - CreateHttpMessageHandler = kestrel.CreateHandler - }, - new DnsEndPoint("localhost", 80) - ) - .CreateCallInvoker(), - default - ); - - Assert.Equal(expected, actual); - } - - class FakeServerFeatures : ServerFeatures.ServerFeatures.ServerFeaturesBase { - readonly SupportedMethods _supportedMethods; - - public FakeServerFeatures(SupportedMethods supportedMethods) => _supportedMethods = supportedMethods; - - public override Task GetSupportedMethods(Empty request, ServerCallContext context) => Task.FromResult(_supportedMethods); - } -} -#endif diff --git a/test/EventStore.Client.Tests/Interceptors/ReportLeaderInterceptorTests.cs b/test/EventStore.Client.Tests/Interceptors/ReportLeaderInterceptorTests.cs deleted file mode 100644 index 5703c3bd7..000000000 --- a/test/EventStore.Client.Tests/Interceptors/ReportLeaderInterceptorTests.cs +++ /dev/null @@ -1,224 +0,0 @@ -using EventStore.Client.Interceptors; -using Grpc.Core; -using Grpc.Core.Interceptors; - -namespace EventStore.Client.Tests.Interceptors; - -public class ReportLeaderInterceptorTests { - public delegate Task GrpcCall(Interceptor interceptor, Task? response = null); - - static readonly StatusCode[] ForcesRediscoveryStatusCodes = { - //StatusCode.Unknown, TODO: use RPC exceptions on server - StatusCode.Unavailable - }; - - static readonly Marshaller Marshaller = new(_ => Array.Empty(), _ => new()); - - static IEnumerable GrpcCalls() { - yield return MakeUnaryCall; - yield return MakeClientStreamingCall; - yield return MakeDuplexStreamingCall; - yield return MakeServerStreamingCall; - yield return MakeClientStreamingCallForWriting; - yield return MakeDuplexStreamingCallForWriting; - } - - public static IEnumerable ReportsNewLeaderCases() => GrpcCalls().Select(call => new object[] { call }); - - [Theory] - [MemberData(nameof(ReportsNewLeaderCases))] - public async Task ReportsNewLeader(GrpcCall call) { - ReconnectionRequired? actual = default; - - var sut = new ReportLeaderInterceptor(result => actual = result); - - var result = await Assert.ThrowsAsync(() => call(sut, Task.FromException(new NotLeaderException("a.host", 2112)))); - - Assert.Equal(new ReconnectionRequired.NewLeader(result.LeaderEndpoint), actual); - } - - public static IEnumerable ForcesRediscoveryCases() => - from call in GrpcCalls() - from statusCode in ForcesRediscoveryStatusCodes - select new object[] { call, statusCode }; - - [Theory] - [MemberData(nameof(ForcesRediscoveryCases))] - public async Task ForcesRediscovery(GrpcCall call, StatusCode statusCode) { - ReconnectionRequired? actual = default; - - var sut = new ReportLeaderInterceptor(result => actual = result); - - await Assert.ThrowsAsync(() => call(sut, Task.FromException(new RpcException(new(statusCode, "oops"))))); - - Assert.Equal(ReconnectionRequired.Rediscover.Instance, actual); - } - - public static IEnumerable DoesNotForceRediscoveryCases() => - from call in GrpcCalls() - from statusCode in Enum.GetValues(typeof(StatusCode)) - .OfType() - .Except(ForcesRediscoveryStatusCodes) - select new object[] { call, statusCode }; - - [Theory] - [MemberData(nameof(DoesNotForceRediscoveryCases))] - public async Task DoesNotForceRediscovery(GrpcCall call, StatusCode statusCode) { - ReconnectionRequired actual = ReconnectionRequired.None.Instance; - - var sut = new ReportLeaderInterceptor(result => actual = result); - - await Assert.ThrowsAsync(() => call(sut, Task.FromException(new RpcException(new(statusCode, "oops"))))); - - Assert.Equal(ReconnectionRequired.None.Instance, actual); - } - - static async Task MakeUnaryCall(Interceptor interceptor, Task? response = null) { - using var call = interceptor.AsyncUnaryCall( - new(), - CreateClientInterceptorContext(MethodType.Unary), - (_, context) => new( - response ?? Task.FromResult(new object()), - Task.FromResult(context.Options.Headers!), - GetSuccess, - GetTrailers, - OnDispose - ) - ); - - await call.ResponseAsync; - } - - static async Task MakeClientStreamingCall(Interceptor interceptor, Task? response = null) { - using var call = interceptor.AsyncClientStreamingCall( - CreateClientInterceptorContext(MethodType.ClientStreaming), - context => new( - null!, - response ?? Task.FromResult(new object()), - Task.FromResult(context.Options.Headers!), - GetSuccess, - GetTrailers, - OnDispose - ) - ); - - await call.ResponseAsync; - } - - static async Task MakeServerStreamingCall(Interceptor interceptor, Task? response = null) { - using var call = interceptor.AsyncServerStreamingCall( - new(), - CreateClientInterceptorContext(MethodType.ServerStreaming), - (_, context) => new( - new TestAsyncStreamReader(response), - Task.FromResult(context.Options.Headers!), - GetSuccess, - GetTrailers, - OnDispose - ) - ); - - await call.ResponseStream.ReadAllAsync().ToArrayAsync(); - } - - static async Task MakeDuplexStreamingCall(Interceptor interceptor, Task? response = null) { - using var call = interceptor.AsyncDuplexStreamingCall( - CreateClientInterceptorContext(MethodType.ServerStreaming), - context => new( - null!, - new TestAsyncStreamReader(response), - Task.FromResult(context.Options.Headers!), - GetSuccess, - GetTrailers, - OnDispose - ) - ); - - await call.ResponseStream.ReadAllAsync().ToArrayAsync(); - } - - // we might write to the server before listening to its response. if that write fails because - // the server is down then we will never listen to its response, so the failed write should - // trigger rediscovery itself - static async Task MakeClientStreamingCallForWriting(Interceptor interceptor, Task? response = null) { - using var call = interceptor.AsyncClientStreamingCall( - CreateClientInterceptorContext(MethodType.ClientStreaming), - context => new( - new TestAsyncStreamWriter(response), - Task.FromResult(new object()), - Task.FromResult(context.Options.Headers!), - GetSuccess, - GetTrailers, - OnDispose - ) - ); - - await call.RequestStream.WriteAsync(new()); - } - - static async Task MakeDuplexStreamingCallForWriting(Interceptor interceptor, Task? response = null) { - using var call = interceptor.AsyncDuplexStreamingCall( - CreateClientInterceptorContext(MethodType.ServerStreaming), - _ => new( - new TestAsyncStreamWriter(response), - null!, - null!, - GetSuccess, - GetTrailers, - OnDispose - ) - ); - - await call.RequestStream.WriteAsync(new()); - } - - static Status GetSuccess() => Status.DefaultSuccess; - - static Metadata GetTrailers() => Metadata.Empty; - - static void OnDispose() { } - - static ClientInterceptorContext CreateClientInterceptorContext(MethodType methodType) => - new( - new( - methodType, - string.Empty, - string.Empty, - Marshaller, - Marshaller - ), - null, - new(new()) - ); - - class TestAsyncStreamReader : IAsyncStreamReader { - readonly Task _response; - - public TestAsyncStreamReader(Task? response = null) => _response = response ?? Task.FromResult(new object()); - - public Task MoveNext(CancellationToken cancellationToken) => - _response.IsFaulted - ? Task.FromException(_response.Exception!.GetBaseException()) - : Task.FromResult(false); - - public object Current => _response.Result; - } - - class TestAsyncStreamWriter : IClientStreamWriter { - readonly Task _response; - - public TestAsyncStreamWriter(Task? response = null) => _response = response ?? Task.FromResult(new object()); - - public WriteOptions? WriteOptions { - get => throw new NotImplementedException(); - set => throw new NotImplementedException(); - } - - public Task CompleteAsync() => throw new NotImplementedException(); - - public Task WriteAsync(object message) => - _response.IsFaulted - ? Task.FromException(_response.Exception!.GetBaseException()) - : Task.FromResult(false); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Tests/PrefixFilterExpressionTests.cs b/test/EventStore.Client.Tests/PrefixFilterExpressionTests.cs deleted file mode 100644 index ae2cbdcd6..000000000 --- a/test/EventStore.Client.Tests/PrefixFilterExpressionTests.cs +++ /dev/null @@ -1,11 +0,0 @@ -using AutoFixture; - -namespace EventStore.Client.Tests; - -public class PrefixFilterExpressionTests : ValueObjectTests { - public PrefixFilterExpressionTests() : base(new ScenarioFixture()) { } - - class ScenarioFixture : Fixture { - public ScenarioFixture() => Customize(composer => composer.FromFactory(value => new(value))); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.UserManagement.Tests/AssemblyInfo.cs b/test/EventStore.Client.UserManagement.Tests/AssemblyInfo.cs deleted file mode 100644 index b0b47aa73..000000000 --- a/test/EventStore.Client.UserManagement.Tests/AssemblyInfo.cs +++ /dev/null @@ -1 +0,0 @@ -[assembly: CollectionBehavior(DisableTestParallelization = true)] \ No newline at end of file diff --git a/test/EventStore.Client.UserManagement.Tests/EventStore.Client.UserManagement.Tests.csproj b/test/EventStore.Client.UserManagement.Tests/EventStore.Client.UserManagement.Tests.csproj deleted file mode 100644 index abaf5e7bf..000000000 --- a/test/EventStore.Client.UserManagement.Tests/EventStore.Client.UserManagement.Tests.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - - EventStore.Client.Tests - - - - - - - - \ No newline at end of file diff --git a/test/EventStore.Client.UserManagement.Tests/EventStore.Client.UserManagement.Tests.csproj.DotSettings b/test/EventStore.Client.UserManagement.Tests/EventStore.Client.UserManagement.Tests.csproj.DotSettings deleted file mode 100644 index 1183b3a73..000000000 --- a/test/EventStore.Client.UserManagement.Tests/EventStore.Client.UserManagement.Tests.csproj.DotSettings +++ /dev/null @@ -1,2 +0,0 @@ - - True \ No newline at end of file diff --git a/test/EventStore.Client.UserManagement.Tests/changing_user_password.cs b/test/EventStore.Client.UserManagement.Tests/changing_user_password.cs deleted file mode 100644 index d3931c1ea..000000000 --- a/test/EventStore.Client.UserManagement.Tests/changing_user_password.cs +++ /dev/null @@ -1,76 +0,0 @@ -namespace EventStore.Client.Tests; - -public class changing_user_password : IClassFixture { - public changing_user_password(ITestOutputHelper output, EventStoreFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - public static IEnumerable NullInputCases() { - yield return Fakers.Users.Generate().WithResult(x => new object?[] { null, x.Password, x.Password, "loginName" }); - yield return Fakers.Users.Generate().WithResult(x => new object?[] { x.LoginName, null, x.Password, "currentPassword" }); - yield return Fakers.Users.Generate().WithResult(x => new object?[] { x.LoginName, x.Password, null, "newPassword" }); - } - - [Theory] - [MemberData(nameof(NullInputCases))] - public async Task with_null_input_throws(string loginName, string currentPassword, string newPassword, string paramName) { - var ex = await Fixture.Users - .ChangePasswordAsync(loginName, currentPassword, newPassword, userCredentials: TestCredentials.Root) - .ShouldThrowAsync(); - - ex.ParamName.ShouldBe(paramName); - } - - public static IEnumerable EmptyInputCases() { - yield return Fakers.Users.Generate().WithResult(x => new object?[] { string.Empty, x.Password, x.Password, "loginName" }); - yield return Fakers.Users.Generate().WithResult(x => new object?[] { x.LoginName, string.Empty, x.Password, "currentPassword" }); - yield return Fakers.Users.Generate().WithResult(x => new object?[] { x.LoginName, x.Password, string.Empty, "newPassword" }); - } - - [Theory] - [MemberData(nameof(EmptyInputCases))] - public async Task with_empty_input_throws(string loginName, string currentPassword, string newPassword, string paramName) { - var ex = await Fixture.Users - .ChangePasswordAsync(loginName, currentPassword, newPassword, userCredentials: TestCredentials.Root) - .ShouldThrowAsync(); - - ex.ParamName.ShouldBe(paramName); - } - - [Theory(Skip = "This can't be right")] - [ClassData(typeof(InvalidCredentialsTestCases))] - public async Task with_user_with_insufficient_credentials_throws(string loginName, UserCredentials userCredentials) { - await Fixture.Users.CreateUserAsync(loginName, "Full Name", Array.Empty(), "password", userCredentials: TestCredentials.Root); - - await Fixture.Users - .ChangePasswordAsync(loginName, "password", "newPassword", userCredentials: userCredentials) - .ShouldThrowAsync(); - } - - [Fact] - public async Task when_the_current_password_is_wrong_throws() { - var user = await Fixture.CreateTestUser(); - - await Fixture.Users - .ChangePasswordAsync(user.LoginName, "wrong-password", "new-password", userCredentials: TestCredentials.Root) - .ShouldThrowAsync(); - } - - [Fact] - public async Task with_correct_credentials() { - var user = await Fixture.CreateTestUser(); - - await Fixture.Users - .ChangePasswordAsync(user.LoginName, user.Password, "new-password", userCredentials: TestCredentials.Root) - .ShouldNotThrowAsync(); - } - - [Fact] - public async Task with_own_credentials() { - var user = await Fixture.CreateTestUser(); - - await Fixture.Users - .ChangePasswordAsync(user.LoginName, user.Password, "new-password", userCredentials: user.Credentials) - .ShouldNotThrowAsync(); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.UserManagement.Tests/creating_a_user.cs b/test/EventStore.Client.UserManagement.Tests/creating_a_user.cs deleted file mode 100644 index abd37bab1..000000000 --- a/test/EventStore.Client.UserManagement.Tests/creating_a_user.cs +++ /dev/null @@ -1,84 +0,0 @@ -namespace EventStore.Client.Tests; - -public class creating_a_user : IClassFixture { - public creating_a_user(ITestOutputHelper outputHelper, InsecureClientTestFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(outputHelper)); - - InsecureClientTestFixture Fixture { get; } - - public static IEnumerable NullInputCases() { - yield return Fakers.Users.Generate().WithResult(x => new object?[] { null, x.FullName, x.Groups, x.Password, "loginName" }); - yield return Fakers.Users.Generate().WithResult(x => new object?[] { x.LoginName, null, x.Groups, x.Password, "fullName" }); - yield return Fakers.Users.Generate().WithResult(x => new object?[] { x.LoginName, x.FullName, null, x.Password, "groups" }); - yield return Fakers.Users.Generate().WithResult(x => new object?[] { x.LoginName, x.FullName, x.Groups, null, "password" }); - } - - [Theory] - [MemberData(nameof(NullInputCases))] - public async Task with_null_input_throws(string loginName, string fullName, string[] groups, string password, string paramName) { - var ex = await Fixture.Users - .CreateUserAsync(loginName, fullName, groups, password, userCredentials: TestCredentials.Root) - .ShouldThrowAsync(); - - ex.ParamName.ShouldBe(paramName); - } - - public static IEnumerable EmptyInputCases() { - yield return Fakers.Users.Generate().WithResult(x => new object?[] { string.Empty, x.FullName, x.Groups, x.Password, "loginName" }); - yield return Fakers.Users.Generate().WithResult(x => new object?[] { x.LoginName, string.Empty, x.Groups, x.Password, "fullName" }); - yield return Fakers.Users.Generate().WithResult(x => new object?[] { x.LoginName, x.FullName, x.Groups, string.Empty, "password" }); - } - - [Theory] - [MemberData(nameof(EmptyInputCases))] - public async Task with_empty_input_throws(string loginName, string fullName, string[] groups, string password, string paramName) { - var ex = await Fixture.Users - .CreateUserAsync(loginName, fullName, groups, password, userCredentials: TestCredentials.Root) - .ShouldThrowAsync(); - - ex.ParamName.ShouldBe(paramName); - } - - [Fact] - public async Task with_password_containing_ascii_chars() { - var user = Fakers.Users.Generate(); - - await Fixture.Users - .CreateUserAsync(user.LoginName, user.FullName, user.Groups, user.Password, userCredentials: TestCredentials.Root) - .ShouldNotThrowAsync(); - } - - [Theory] - [ClassData(typeof(InvalidCredentialsTestCases))] - public async Task with_user_with_insufficient_credentials_throws(InvalidCredentialsTestCase testCase) => - await Fixture.Users - .CreateUserAsync(testCase.User.LoginName, testCase.User.FullName, testCase.User.Groups, testCase.User.Password, userCredentials: testCase.User.Credentials) - .ShouldThrowAsync(testCase.ExpectedException); - - [Fact] - public async Task can_be_read() { - var user = Fakers.Users.Generate(); - - await Fixture.Users - .CreateUserAsync( - user.LoginName, - user.FullName, - user.Groups, - user.Password, - userCredentials: TestCredentials.Root - ) - .ShouldNotThrowAsync(); - - var actual = await Fixture.Users.GetUserAsync(user.LoginName, userCredentials: TestCredentials.Root); - - var expected = new UserDetails( - user.Details.LoginName, - user.Details.FullName, - user.Details.Groups, - user.Details.Disabled, - actual.DateLastUpdated - ); - - actual.ShouldBeEquivalentTo(expected); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.UserManagement.Tests/getting_current_user.cs b/test/EventStore.Client.UserManagement.Tests/getting_current_user.cs deleted file mode 100644 index b0cb3af2d..000000000 --- a/test/EventStore.Client.UserManagement.Tests/getting_current_user.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace EventStore.Client.Tests; - -public class getting_current_user : IClassFixture { - public getting_current_user(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - EventStoreFixture Fixture { get; } - - [Fact] - public async Task returns_the_current_user() { - var user = await Fixture.Users.GetCurrentUserAsync(TestCredentials.Root); - user.LoginName.ShouldBe(TestCredentials.Root.Username); - } -} \ No newline at end of file diff --git a/test/EventStore.Client.Tests.Common/.env b/test/Kurrent.Client.Tests.Common/.env similarity index 100% rename from test/EventStore.Client.Tests.Common/.env rename to test/Kurrent.Client.Tests.Common/.env diff --git a/test/EventStore.Client.Tests.Common/ApplicationInfo.cs b/test/Kurrent.Client.Tests.Common/ApplicationInfo.cs similarity index 98% rename from test/EventStore.Client.Tests.Common/ApplicationInfo.cs rename to test/Kurrent.Client.Tests.Common/ApplicationInfo.cs index 0120c21b4..26e78938d 100644 --- a/test/EventStore.Client.Tests.Common/ApplicationInfo.cs +++ b/test/Kurrent.Client.Tests.Common/ApplicationInfo.cs @@ -9,7 +9,7 @@ using static System.Environment; using static System.StringComparison; -namespace EventStore.Client; +namespace Kurrent.Client; /// /// Loads configuration and provides information about the application environment. diff --git a/test/EventStore.Client.ProjectionManagement.Tests/AssertEx.cs b/test/Kurrent.Client.Tests.Common/AssertEx.cs similarity index 97% rename from test/EventStore.Client.ProjectionManagement.Tests/AssertEx.cs rename to test/Kurrent.Client.Tests.Common/AssertEx.cs index f7d846294..6750e66b5 100644 --- a/test/EventStore.Client.ProjectionManagement.Tests/AssertEx.cs +++ b/test/Kurrent.Client.Tests.Common/AssertEx.cs @@ -1,7 +1,7 @@ using System.Runtime.CompilerServices; using Xunit.Sdk; -namespace EventStore.Client.ProjectionManagement.Tests; +namespace Kurrent.Client.Tests; public static class AssertEx { /// @@ -53,4 +53,4 @@ static async Task IsOrBecomesTrueImpl(Func> func, TimeSpan? tim return false; } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/Certificates.cs b/test/Kurrent.Client.Tests.Common/Certificates.cs similarity index 97% rename from test/EventStore.Client.Tests.Common/Certificates.cs rename to test/Kurrent.Client.Tests.Common/Certificates.cs index efd167d67..3b8671d9b 100644 --- a/test/EventStore.Client.Tests.Common/Certificates.cs +++ b/test/Kurrent.Client.Tests.Common/Certificates.cs @@ -1,6 +1,6 @@ // ReSharper disable InconsistentNaming -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; public static class Certificates { static readonly string BaseDirectory = AppDomain.CurrentDomain.BaseDirectory; diff --git a/test/EventStore.Client.Tests.Common/Extensions/ConfigurationExtensions.cs b/test/Kurrent.Client.Tests.Common/Extensions/ConfigurationExtensions.cs similarity index 89% rename from test/EventStore.Client.Tests.Common/Extensions/ConfigurationExtensions.cs rename to test/Kurrent.Client.Tests.Common/Extensions/ConfigurationExtensions.cs index 3e975fc23..87f06cd45 100644 --- a/test/EventStore.Client.Tests.Common/Extensions/ConfigurationExtensions.cs +++ b/test/Kurrent.Client.Tests.Common/Extensions/ConfigurationExtensions.cs @@ -1,6 +1,6 @@ using Microsoft.Extensions.Configuration; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; public static class ConfigurationExtensions { public static void EnsureValue(this IConfiguration configuration, string key, string defaultValue) { @@ -9,4 +9,4 @@ public static void EnsureValue(this IConfiguration configuration, string key, st if (string.IsNullOrEmpty(value)) configuration[key] = defaultValue; } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/Extensions/EventStoreClientExtensions.cs b/test/Kurrent.Client.Tests.Common/Extensions/KurrentClientExtensions.cs similarity index 69% rename from test/EventStore.Client.Tests.Common/Extensions/EventStoreClientExtensions.cs rename to test/Kurrent.Client.Tests.Common/Extensions/KurrentClientExtensions.cs index e1475bc16..0b0861cf3 100644 --- a/test/EventStore.Client.Tests.Common/Extensions/EventStoreClientExtensions.cs +++ b/test/Kurrent.Client.Tests.Common/Extensions/KurrentClientExtensions.cs @@ -1,11 +1,12 @@ +using EventStore.Client; using Polly; using static System.TimeSpan; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; -public static class EventStoreClientExtensions { +public static class KurrentClientExtensions { public static Task CreateUserWithRetry( - this EventStoreUserManagementClient client, string loginName, string fullName, string[] groups, string password, + this KurrentUserManagementClient client, string loginName, string fullName, string[] groups, string password, UserCredentials? userCredentials = null, CancellationToken cancellationToken = default ) => Policy.Handle() @@ -21,4 +22,4 @@ public static Task CreateUserWithRetry( ), cancellationToken ); -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/Extensions/EventStoreClientWarmupExtensions.cs b/test/Kurrent.Client.Tests.Common/Extensions/KurrentClientWarmupExtensions.cs similarity index 79% rename from test/EventStore.Client.Tests.Common/Extensions/EventStoreClientWarmupExtensions.cs rename to test/Kurrent.Client.Tests.Common/Extensions/KurrentClientWarmupExtensions.cs index dea2f4ef9..89045a44b 100644 --- a/test/EventStore.Client.Tests.Common/Extensions/EventStoreClientWarmupExtensions.cs +++ b/test/Kurrent.Client.Tests.Common/Extensions/KurrentClientWarmupExtensions.cs @@ -1,11 +1,12 @@ +using EventStore.Client; using Grpc.Core; using Polly; using Polly.Contrib.WaitAndRetry; using static System.TimeSpan; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; -public static class EventStoreClientWarmupExtensions { +public static class KurrentClientWarmupExtensions { static readonly TimeSpan RediscoverTimeout = FromSeconds(5); /// @@ -14,7 +15,7 @@ public static class EventStoreClientWarmupExtensions { static readonly IEnumerable DefaultBackoffDelay = Backoff.ConstantBackoff(FromMilliseconds(100), 300); static async Task TryWarmUp(T client, Func action, CancellationToken cancellationToken = default) - where T : EventStoreClientBase { + where T : KurrentClientBase { await Policy .Handle(ex => ex.StatusCode != StatusCode.Unimplemented) .Or() @@ -39,7 +40,7 @@ await Policy return client; } - public static Task WarmUp(this EventStoreClient client, CancellationToken cancellationToken = default) => + public static Task WarmUp(this KurrentClient client, CancellationToken cancellationToken = default) => TryWarmUp( client, async ct => { @@ -72,7 +73,7 @@ public static Task WarmUp(this EventStoreClient client, Cancel cancellationToken ); - public static Task WarmUp(this EventStoreOperationsClient client, CancellationToken cancellationToken = default) => + public static Task WarmUp(this KurrentOperationsClient client, CancellationToken cancellationToken = default) => TryWarmUp( client, async ct => { @@ -84,8 +85,8 @@ await client.RestartPersistentSubscriptions( cancellationToken ); - public static Task WarmUp( - this EventStorePersistentSubscriptionsClient client, CancellationToken cancellationToken = default + public static Task WarmUp( + this KurrentPersistentSubscriptionsClient client, CancellationToken cancellationToken = default ) => TryWarmUp( client, @@ -102,8 +103,8 @@ await client.CreateToStreamAsync( cancellationToken ); - public static Task WarmUp( - this EventStoreProjectionManagementClient client, CancellationToken cancellationToken = default + public static Task WarmUp( + this KurrentProjectionManagementClient client, CancellationToken cancellationToken = default ) => TryWarmUp( client, @@ -118,7 +119,7 @@ public static Task WarmUp( cancellationToken ); - public static Task WarmUp(this EventStoreUserManagementClient client, CancellationToken cancellationToken = default) => + public static Task WarmUp(this KurrentUserManagementClient client, CancellationToken cancellationToken = default) => TryWarmUp( client, async ct => { @@ -129,4 +130,4 @@ public static Task WarmUp(this EventStoreUserMan }, cancellationToken ); -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/Extensions/OperatingSystemExtensions.cs b/test/Kurrent.Client.Tests.Common/Extensions/OperatingSystemExtensions.cs similarity index 87% rename from test/EventStore.Client.Tests.Common/Extensions/OperatingSystemExtensions.cs rename to test/Kurrent.Client.Tests.Common/Extensions/OperatingSystemExtensions.cs index 1889b084d..fbd53f8cc 100644 --- a/test/EventStore.Client.Tests.Common/Extensions/OperatingSystemExtensions.cs +++ b/test/Kurrent.Client.Tests.Common/Extensions/OperatingSystemExtensions.cs @@ -1,7 +1,7 @@ -namespace EventStore.Client; +namespace Kurrent.Client; public static class OperatingSystemExtensions { public static bool IsWindows(this OperatingSystem operatingSystem) => operatingSystem.Platform != PlatformID.Unix && operatingSystem.Platform != PlatformID.MacOSX; -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/Extensions/ReadOnlyMemoryExtensions.cs b/test/Kurrent.Client.Tests.Common/Extensions/ReadOnlyMemoryExtensions.cs similarity index 93% rename from test/EventStore.Client.Tests.Common/Extensions/ReadOnlyMemoryExtensions.cs rename to test/Kurrent.Client.Tests.Common/Extensions/ReadOnlyMemoryExtensions.cs index 49ffd1cd9..403665653 100644 --- a/test/EventStore.Client.Tests.Common/Extensions/ReadOnlyMemoryExtensions.cs +++ b/test/Kurrent.Client.Tests.Common/Extensions/ReadOnlyMemoryExtensions.cs @@ -1,6 +1,7 @@ using System.Text.Json; +using EventStore.Client; -namespace EventStore.Client; +namespace Kurrent.Client; public static class ReadOnlyMemoryExtensions { public static Position ParsePosition(this ReadOnlyMemory json) { @@ -25,4 +26,4 @@ public static StreamPosition ParseStreamPosition(this ReadOnlyMemory json) return StreamPosition.FromInt64(int.Parse(checkPoint)); } -} \ No newline at end of file +} diff --git a/test/Kurrent.Client.Tests.Common/Extensions/ShouldThrowAsyncExtensions.cs b/test/Kurrent.Client.Tests.Common/Extensions/ShouldThrowAsyncExtensions.cs new file mode 100644 index 000000000..827133337 --- /dev/null +++ b/test/Kurrent.Client.Tests.Common/Extensions/ShouldThrowAsyncExtensions.cs @@ -0,0 +1,16 @@ +using EventStore.Client; + +namespace Kurrent.Client.Tests; + +public static class ShouldThrowAsyncExtensions { + public static Task ShouldThrowAsync(this KurrentClient.ReadStreamResult source) where TException : Exception => + source + .ToArrayAsync() + .AsTask() + .ShouldThrowAsync(); + + public static async Task ShouldThrowAsync(this KurrentClient.ReadStreamResult source, Action handler) where TException : Exception { + var ex = await source.ShouldThrowAsync(); + handler(ex); + } +} diff --git a/test/EventStore.Client.Tests.Common/Extensions/TaskExtensions.cs b/test/Kurrent.Client.Tests.Common/Extensions/TaskExtensions.cs similarity index 97% rename from test/EventStore.Client.Tests.Common/Extensions/TaskExtensions.cs rename to test/Kurrent.Client.Tests.Common/Extensions/TaskExtensions.cs index d3775b700..9fb022726 100644 --- a/test/EventStore.Client.Tests.Common/Extensions/TaskExtensions.cs +++ b/test/Kurrent.Client.Tests.Common/Extensions/TaskExtensions.cs @@ -1,6 +1,6 @@ using System.Diagnostics; -namespace EventStore.Client; +namespace Kurrent.Client; public static class TaskExtensions { public static Task WithTimeout(this Task task, TimeSpan timeout) diff --git a/test/EventStore.Client.Tests/TypeExtensions.cs b/test/Kurrent.Client.Tests.Common/Extensions/TypeExtensions.cs similarity index 96% rename from test/EventStore.Client.Tests/TypeExtensions.cs rename to test/Kurrent.Client.Tests.Common/Extensions/TypeExtensions.cs index 268109da8..355544e88 100644 --- a/test/EventStore.Client.Tests/TypeExtensions.cs +++ b/test/Kurrent.Client.Tests.Common/Extensions/TypeExtensions.cs @@ -1,8 +1,8 @@ using System.Reflection; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; -static class TypeExtensions { +public static class TypeExtensions { public static bool InvokeEqualityOperator(this Type type, object? left, object? right) => type.InvokeOperator("Equality", left, right); public static bool InvokeInequalityOperator(this Type type, object? left, object? right) => type.InvokeOperator("Inequality", left, right); @@ -36,4 +36,4 @@ static bool InvokeOperator(this Type type, string name, object? left, object? ri return (bool)op.Invoke(null, new[] { left, right })!; } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/Extensions/WithExtension.cs b/test/Kurrent.Client.Tests.Common/Extensions/WithExtension.cs similarity index 97% rename from test/EventStore.Client.Tests.Common/Extensions/WithExtension.cs rename to test/Kurrent.Client.Tests.Common/Extensions/WithExtension.cs index b2ea3dbac..b0c577e26 100644 --- a/test/EventStore.Client.Tests.Common/Extensions/WithExtension.cs +++ b/test/Kurrent.Client.Tests.Common/Extensions/WithExtension.cs @@ -1,6 +1,6 @@ using System.Diagnostics; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; public static class WithExtension { [DebuggerStepThrough] @@ -59,4 +59,4 @@ public static T With(this T instance, Func action, Func when) { return when() ? action(instance) : instance; } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/Facts/AnonymousAccess.cs b/test/Kurrent.Client.Tests.Common/Facts/AnonymousAccess.cs similarity index 90% rename from test/EventStore.Client.Tests.Common/Facts/AnonymousAccess.cs rename to test/Kurrent.Client.Tests.Common/Facts/AnonymousAccess.cs index 575093085..101a67df0 100644 --- a/test/EventStore.Client.Tests.Common/Facts/AnonymousAccess.cs +++ b/test/Kurrent.Client.Tests.Common/Facts/AnonymousAccess.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; [PublicAPI] public class AnonymousAccess { @@ -8,4 +8,4 @@ public class AnonymousAccess { public class FactAttribute() : Deprecation.FactAttribute(LegacySince, SkipMessage); public class TheoryAttribute() : Deprecation.TheoryAttribute(LegacySince, SkipMessage); -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/Facts/Deprecation.cs b/test/Kurrent.Client.Tests.Common/Facts/Deprecation.cs similarity index 73% rename from test/EventStore.Client.Tests.Common/Facts/Deprecation.cs rename to test/Kurrent.Client.Tests.Common/Facts/Deprecation.cs index 01adee242..3b374ee91 100644 --- a/test/EventStore.Client.Tests.Common/Facts/Deprecation.cs +++ b/test/Kurrent.Client.Tests.Common/Facts/Deprecation.cs @@ -1,10 +1,10 @@ -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; [PublicAPI] public class Deprecation { public class FactAttribute(Version since, string skipMessage) : Xunit.FactAttribute { public override string? Skip { - get => EventStoreTestServer.Version >= since ? skipMessage : null; + get => KurrentPermanentTestNode.Version >= since ? skipMessage : null; set => throw new NotSupportedException(); } } @@ -19,8 +19,8 @@ public TheoryAttribute(Version since, string skipMessage) { } public override string? Skip { - get => EventStoreTestServer.Version >= _legacySince ? _skipMessage : null; + get => KurrentPermanentTestNode.Version >= _legacySince ? _skipMessage : null; set => throw new NotSupportedException(); } } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/Facts/Regression.cs b/test/Kurrent.Client.Tests.Common/Facts/Regression.cs similarity index 62% rename from test/EventStore.Client.Tests.Common/Facts/Regression.cs rename to test/Kurrent.Client.Tests.Common/Facts/Regression.cs index 3c6a92f0c..09e944518 100644 --- a/test/EventStore.Client.Tests.Common/Facts/Regression.cs +++ b/test/Kurrent.Client.Tests.Common/Facts/Regression.cs @@ -1,18 +1,18 @@ -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; [PublicAPI] public class Regression { public class FactAttribute(int major, string skipMessage) : Xunit.FactAttribute { public override string? Skip { - get => (EventStoreTestServer.Version?.Major ?? int.MaxValue) < major ? skipMessage : null; + get => (KurrentPermanentTestNode.Version?.Major ?? int.MaxValue) < major ? skipMessage : null; set => throw new NotSupportedException(); } } public class TheoryAttribute(int major, string skipMessage) : Xunit.TheoryAttribute { public override string? Skip { - get => (EventStoreTestServer.Version?.Major ?? int.MaxValue) < major ? skipMessage : null; + get => (KurrentPermanentTestNode.Version?.Major ?? int.MaxValue) < major ? skipMessage : null; set => throw new NotSupportedException(); } } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/Fakers/TestUserFaker.cs b/test/Kurrent.Client.Tests.Common/Fakers/TestUserFaker.cs similarity index 96% rename from test/EventStore.Client.Tests.Common/Fakers/TestUserFaker.cs rename to test/Kurrent.Client.Tests.Common/Fakers/TestUserFaker.cs index 1aca4aac1..472aa1b15 100644 --- a/test/EventStore.Client.Tests.Common/Fakers/TestUserFaker.cs +++ b/test/Kurrent.Client.Tests.Common/Fakers/TestUserFaker.cs @@ -1,4 +1,6 @@ -namespace EventStore.Client.Tests; +using EventStore.Client; + +namespace Kurrent.Client.Tests; public class TestUser { public UserDetails Details { get; set; } = default!; @@ -50,4 +52,4 @@ public TestUser WithNonAsciiPassword() => public static partial class Fakers { public static TestUserFaker Users => TestUserFaker.Instance; -} \ No newline at end of file +} diff --git a/test/Kurrent.Client.Tests.Common/Fixtures/BaseTestNode.cs b/test/Kurrent.Client.Tests.Common/Fixtures/BaseTestNode.cs new file mode 100644 index 000000000..5ace2a507 --- /dev/null +++ b/test/Kurrent.Client.Tests.Common/Fixtures/BaseTestNode.cs @@ -0,0 +1,162 @@ +// // ReSharper disable InconsistentNaming +// +// using System.Globalization; +// using System.Net; +// using System.Net.Sockets; +// using Ductus.FluentDocker.Builders; +// using Ductus.FluentDocker.Extensions; +// using Ductus.FluentDocker.Services.Extensions; +// using Kurrent.Client.Tests.FluentDocker; +// using Humanizer; +// using Serilog; +// using Serilog.Extensions.Logging; +// using static System.TimeSpan; +// +// namespace Kurrent.Client.Tests; +// +// public abstract class BaseTestNode(EventStoreFixtureOptions? options = null) : TestContainerService { +// static readonly NetworkPortProvider NetworkPortProvider = new(NetworkPortProvider.DefaultEsdbPort); +// +// public KurrentFixtureOptions Options { get; } = options ?? DefaultOptions(); +// +// static Version? _version; +// +// public static Version Version => _version ??= GetVersion(); +// +// public static EventStoreFixtureOptions DefaultOptions() { +// const string connString = "esdb://admin:changeit@localhost:{port}/?tlsVerifyCert=false"; +// +// var port = NetworkPortProvider.NextAvailablePort; +// +// var defaultSettings = EventStoreClientSettings +// .Create(connString.Replace("{port}", $"{port}")) +// .With(x => x.LoggerFactory = new SerilogLoggerFactory(Log.Logger)) +// .With(x => x.DefaultDeadline = Application.DebuggerIsAttached ? new TimeSpan?() : FromSeconds(30)) +// .With(x => x.ConnectivitySettings.MaxDiscoverAttempts = 20) +// .With(x => x.ConnectivitySettings.DiscoveryInterval = FromSeconds(1)); +// +// var defaultEnvironment = new Dictionary(GlobalEnvironment.Variables) { +// // ["EVENTSTORE_MEM_DB"] = "true", +// // ["EVENTSTORE_CERTIFICATE_FILE"] = "/etc/eventstore/certs/node/node.crt", +// // ["EVENTSTORE_CERTIFICATE_PRIVATE_KEY_FILE"] = "/etc/eventstore/certs/node/node.key", +// // ["EVENTSTORE_STREAM_EXISTENCE_FILTER_SIZE"] = "10000", +// // ["EVENTSTORE_STREAM_INFO_CACHE_CAPACITY"] = "10000", +// // ["EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP"] = "true", +// // ["EVENTSTORE_LOG_LEVEL"] = "Default", // required to use serilog settings +// // ["EVENTSTORE_DISABLE_LOG_FILE"] = "true", +// // ["EVENTSTORE_START_STANDARD_PROJECTIONS"] = "true", +// // ["EVENTSTORE_RUN_PROJECTIONS"] = "All", +// // ["EVENTSTORE_CHUNK_SIZE"] = (1024 * 1024 * 1024).ToString(), +// // ["EVENTSTORE_MAX_APPEND_SIZE"] = 100.Kilobytes().Bytes.ToString(CultureInfo.InvariantCulture), +// // ["EVENTSTORE_ADVERTISE_HTTP_PORT_TO_CLIENT_AS"] = $"{NetworkPortProvider.DefaultEsdbPort}" +// +// ["EVENTSTORE_MEM_DB"] = "true", +// ["EVENTSTORE_CERTIFICATE_FILE"] = "/etc/eventstore/certs/node/node.crt", +// ["EVENTSTORE_CERTIFICATE_PRIVATE_KEY_FILE"] = "/etc/eventstore/certs/node/node.key", +// ["EVENTSTORE_STREAM_EXISTENCE_FILTER_SIZE"] = "10000", +// ["EVENTSTORE_STREAM_INFO_CACHE_CAPACITY"] = "10000", +// ["EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP"] = "true", +// ["EVENTSTORE_LOG_LEVEL"] = "Default", // required to use serilog settings +// ["EVENTSTORE_DISABLE_LOG_FILE"] = "true", +// ["EVENTSTORE_CHUNK_SIZE"] = (1024 * 1024 * 1024).ToString(), +// ["EVENTSTORE_MAX_APPEND_SIZE"] = 100.Kilobytes().Bytes.ToString(CultureInfo.InvariantCulture), +// ["EVENTSTORE_ADVERTISE_HTTP_PORT_TO_CLIENT_AS"] = $"{NetworkPortProvider.DefaultEsdbPort}" +// }; +// +// if (port != NetworkPortProvider.DefaultEsdbPort) { +// if (GlobalEnvironment.Variables.TryGetValue("ES_DOCKER_TAG", out var tag) && tag == "ci") +// defaultEnvironment["EVENTSTORE_ADVERTISE_NODE_PORT_TO_CLIENT_AS"] = $"{port}"; +// else +// defaultEnvironment["EVENTSTORE_ADVERTISE_HTTP_PORT_TO_CLIENT_AS"] = $"{port}"; +// } +// +// return new(defaultSettings, defaultEnvironment); +// } +// +// static Version GetVersion() { +// const string versionPrefix = "EventStoreDB version"; +// +// using var cts = new CancellationTokenSource(FromSeconds(30)); +// using var eventstore = new Builder().UseContainer() +// .UseImage(GlobalEnvironment.DockerImage) +// .Command("--version") +// .Build() +// .Start(); +// +// using var log = eventstore.Logs(true, cts.Token); +// foreach (var line in log.ReadToEnd()) { +// if (line.StartsWith(versionPrefix) && +// Version.TryParse(new string(ReadVersion(line[(versionPrefix.Length + 1)..]).ToArray()), out var version)) { +// return version; +// } +// } +// +// throw new InvalidOperationException("Could not determine server version."); +// +// IEnumerable ReadVersion(string s) { +// foreach (var c in s.TakeWhile(c => c == '.' || char.IsDigit(c))) { +// yield return c; +// } +// } +// } +// +// string[] GetEnvironmentVariables() => +// Options.Environment.Select(pair => $"{pair.Key}={pair.Value}").ToArray(); +// +// protected abstract ContainerBuilder ConfigureContainer(ContainerBuilder builder); +// +// protected override ContainerBuilder Configure() { +// var certsPath = Path.Combine(Environment.CurrentDirectory, "certs"); +// +// CertificatesManager.VerifyCertificatesExist(certsPath); +// +// var builder = new Builder().UseContainer().WithEnvironment(GetEnvironmentVariables()); +// +// return ConfigureContainer(builder); +// } +// } +// +// /// +// /// Using the default 2113 port assumes that the test is running sequentially. +// /// +// /// +// class NetworkPortProvider(int port = 2114) { +// public const int DefaultEsdbPort = 2113; +// +// static readonly SemaphoreSlim Semaphore = new(1, 1); +// +// async Task GetNextAvailablePort(TimeSpan delay = default) { +// if (port == DefaultEsdbPort) +// return port; +// +// await Semaphore.WaitAsync(); +// +// try { +// using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); +// +// while (true) { +// var nexPort = Interlocked.Increment(ref port); +// +// try { +// await socket.ConnectAsync(IPAddress.Any, nexPort); +// } catch (SocketException ex) { +// if (ex.SocketErrorCode is SocketError.ConnectionRefused or not SocketError.IsConnected) { +// return nexPort; +// } +// +// await Task.Delay(delay); +// } finally { +// #if NET +// if (socket.Connected) await socket.DisconnectAsync(true); +// #else +// if (socket.Connected) socket.Disconnect(true); +// #endif +// } +// } +// } finally { +// Semaphore.Release(); +// } +// } +// +// public int NextAvailablePort => GetNextAvailablePort(FromMilliseconds(100)).GetAwaiter().GetResult(); +// } diff --git a/test/EventStore.Client.Tests.Common/Fixtures/CertificatesManager.cs b/test/Kurrent.Client.Tests.Common/Fixtures/CertificatesManager.cs similarity index 98% rename from test/EventStore.Client.Tests.Common/Fixtures/CertificatesManager.cs rename to test/Kurrent.Client.Tests.Common/Fixtures/CertificatesManager.cs index 487bfd340..f01d9c246 100644 --- a/test/EventStore.Client.Tests.Common/Fixtures/CertificatesManager.cs +++ b/test/Kurrent.Client.Tests.Common/Fixtures/CertificatesManager.cs @@ -1,6 +1,6 @@ using Ductus.FluentDocker.Builders; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; static class CertificatesManager { static readonly DirectoryInfo CertificateDirectory; diff --git a/test/Kurrent.Client.Tests.Common/Fixtures/KurrentFixtureOptions.cs b/test/Kurrent.Client.Tests.Common/Fixtures/KurrentFixtureOptions.cs new file mode 100644 index 000000000..db5ce022e --- /dev/null +++ b/test/Kurrent.Client.Tests.Common/Fixtures/KurrentFixtureOptions.cs @@ -0,0 +1,25 @@ +using EventStore.Client; + +namespace Kurrent.Client.Tests; + +public record KurrentFixtureOptions( + KurrentClientSettings ClientSettings, + IDictionary Environment +) { + public KurrentFixtureOptions RunInMemory(bool runInMemory = true) => + this with { Environment = Environment.With(x => x["EVENTSTORE_MEM_DB"] = runInMemory.ToString()) }; + + public KurrentFixtureOptions WithoutDefaultCredentials() => this with { ClientSettings = ClientSettings.With(x => x.DefaultCredentials = null) }; + + public KurrentFixtureOptions RunProjections(bool runProjections = true) => + this with { + Environment = Environment.With( + x => { + x["EVENTSTORE_START_STANDARD_PROJECTIONS"] = runProjections.ToString(); + x["EVENTSTORE_RUN_PROJECTIONS"] = runProjections ? "All" : "None"; + } + ) + }; +} + +public delegate KurrentFixtureOptions ConfigureFixture(KurrentFixtureOptions options); diff --git a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.Helpers.cs b/test/Kurrent.Client.Tests.Common/Fixtures/KurrentPermanentFixture.Helpers.cs similarity index 74% rename from test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.Helpers.cs rename to test/Kurrent.Client.Tests.Common/Fixtures/KurrentPermanentFixture.Helpers.cs index 1e8bb3d83..7eb5d9749 100644 --- a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreFixture.Helpers.cs +++ b/test/Kurrent.Client.Tests.Common/Fixtures/KurrentPermanentFixture.Helpers.cs @@ -1,18 +1,29 @@ using System.Runtime.CompilerServices; using System.Text; +using EventStore.Client; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; -public partial class EventStoreFixture { +public partial class KurrentPermanentFixture { public const string TestEventType = "test-event-type"; public const string AnotherTestEventTypePrefix = "another"; public const string AnotherTestEventType = $"{AnotherTestEventTypePrefix}-test-event-type"; - public T NewClient(Action configure) where T : EventStoreClientBase, new() => + public T NewClient(Action configure) where T : KurrentClientBase, new() => (T)Activator.CreateInstance(typeof(T), [ClientSettings.With(configure)])!; public string GetStreamName([CallerMemberName] string? testMethod = null) => - $"{testMethod}-{Guid.NewGuid():N}"; + $"stream-{testMethod}-{Guid.NewGuid():N}"; + + public string GetGroupName([CallerMemberName] string? testMethod = null) => + $"group-{testMethod}-{Guid.NewGuid():N}"; + + public UserCredentials GetUserCredentials([CallerMemberName] string? testMethod = null) => new UserCredentials( + $"user-{testMethod}-{Guid.NewGuid():N}", "pa$$word" + ); + + public string GetProjectionName([CallerMemberName] string? testMethod = null) => + $"projection-{testMethod}-{Guid.NewGuid():N}"; public ReadOnlyMemory CreateMetadataOfSize(int metadataSize) => Encoding.UTF8.GetBytes($"\"{new string('$', metadataSize)}\""); @@ -21,6 +32,16 @@ public ReadOnlyMemory CreateMetadataOfSize(int metadataSize) => public ReadOnlyMemory CreateTestNonJsonMetadata() => "non-json-metadata"u8.ToArray(); + public (IEnumerable Events, uint size) CreateTestEventsUpToMaxSize(uint maxSize) { + var size = 0; + + var events = CreateTestEvents(int.MaxValue) + .TakeWhile(evt => (size += evt.Data.Length) < maxSize) + .ToList(); + + return (events, (uint)size); + } + public IEnumerable CreateTestEvents( int count = 1, string? type = null, ReadOnlyMemory? metadata = null, string? contentType = null ) => diff --git a/test/Kurrent.Client.Tests.Common/Fixtures/KurrentPermanentFixture.cs b/test/Kurrent.Client.Tests.Common/Fixtures/KurrentPermanentFixture.cs new file mode 100644 index 000000000..0b657b61f --- /dev/null +++ b/test/Kurrent.Client.Tests.Common/Fixtures/KurrentPermanentFixture.cs @@ -0,0 +1,183 @@ +// ReSharper disable InconsistentNaming + +using System.Net; +using Ductus.FluentDocker.Builders; +using Ductus.FluentDocker.Extensions; +using Ductus.FluentDocker.Services.Extensions; +using EventStore.Client; +using Kurrent.Client.Tests.FluentDocker; +using Serilog; +using static System.TimeSpan; +using KurrentClient = EventStore.Client.KurrentClient; + +namespace Kurrent.Client.Tests; + +[PublicAPI] +public partial class KurrentPermanentFixture : IAsyncLifetime, IAsyncDisposable { + static readonly ILogger Logger; + + static KurrentPermanentFixture() { + Logging.Initialize(); + Logger = Serilog.Log.ForContext(); + +#if NET9_0_OR_GREATER + var httpClientHandler = new HttpClientHandler(); + httpClientHandler.ServerCertificateCustomValidationCallback = delegate { return true; }; +#else + ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; +#endif + } + + public KurrentPermanentFixture() : this(options => options) { } + + protected KurrentPermanentFixture(ConfigureFixture configure) { + Options = configure(KurrentPermanentTestNode.DefaultOptions()); + Service = new KurrentPermanentTestNode(Options); + } + + List TestRuns { get; } = new(); + + public ILogger Log => Logger; + + public ITestService Service { get; } + public KurrentFixtureOptions Options { get; } + public Faker Faker { get; } = new Faker(); + + public Version EventStoreVersion { get; private set; } = null!; + public bool EventStoreHasLastStreamPosition { get; private set; } + + public KurrentClient Streams { get; private set; } = null!; + public KurrentUserManagementClient Users { get; private set; } = null!; + public KurrentProjectionManagementClient Projections { get; private set; } = null!; + public KurrentPersistentSubscriptionsClient Subscriptions { get; private set; } = null!; + public KurrentOperationsClient Operations { get; private set; } = null!; + + public bool SkipPsWarmUp { get; set; } + + public Func OnSetup { get; init; } = () => Task.CompletedTask; + public Func OnTearDown { get; init; } = () => Task.CompletedTask; + + /// + /// must test this + /// + public KurrentClientSettings ClientSettings => + new() { + Interceptors = Options.ClientSettings.Interceptors, + ConnectionName = Options.ClientSettings.ConnectionName, + CreateHttpMessageHandler = Options.ClientSettings.CreateHttpMessageHandler, + LoggerFactory = Options.ClientSettings.LoggerFactory, + ChannelCredentials = Options.ClientSettings.ChannelCredentials, + OperationOptions = Options.ClientSettings.OperationOptions, + ConnectivitySettings = Options.ClientSettings.ConnectivitySettings, + DefaultCredentials = Options.ClientSettings.DefaultCredentials, + DefaultDeadline = Options.ClientSettings.DefaultDeadline + }; + + InterlockedBoolean WarmUpCompleted { get; } = new InterlockedBoolean(); + static readonly SemaphoreSlim WarmUpGatekeeper = new(1, 1); + + public void CaptureTestRun(ITestOutputHelper outputHelper) { + var testRunId = Logging.CaptureLogs(outputHelper); + TestRuns.Add(testRunId); + Logger.Information(">>> Test Run {TestRunId} {Operation} <<<", testRunId, "starting"); + Service.ReportStatus(); + } + + public async Task InitializeAsync() { + await WarmUpGatekeeper.WaitAsync(); + + try { + await Service.Start(); + EventStoreVersion = GetKurrentVersion(); + EventStoreHasLastStreamPosition = (EventStoreVersion?.Major ?? int.MaxValue) >= 21; + + if (!WarmUpCompleted.CurrentValue) { + Logger.Warning("*** Warmup started ***"); + + await Task.WhenAll( + InitClient(async x => Users = await Task.FromResult(x)), + InitClient(async x => Streams = await Task.FromResult(x)), + InitClient( + async x => Projections = await Task.FromResult(x), + Options.Environment["EVENTSTORE_RUN_PROJECTIONS"] != "None" + ), + InitClient(async x => Subscriptions = SkipPsWarmUp ? x : await Task.FromResult(x)), + InitClient(async x => Operations = await Task.FromResult(x)) + ); + + WarmUpCompleted.EnsureCalledOnce(); + + Logger.Warning("*** Warmup completed ***"); + } else { + Logger.Information("*** Warmup skipped ***"); + } + } finally { + WarmUpGatekeeper.Release(); + } + + await OnSetup(); + + return; + + async Task InitClient(Func action, bool execute = true) where T : KurrentClientBase { + if (!execute) return default(T)!; + + var client = (Activator.CreateInstance(typeof(T), ClientSettings) as T)!; + await action(client); + return client; + } + + static Version GetKurrentVersion() { + 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()) { + Logger.Information("EventStoreDB: {Line}", line); + if (line.StartsWith(versionPrefix) && + Version.TryParse( + new string(ReadVersion(line[(versionPrefix.Length + 1)..]).ToArray()), + out var version + )) { + return version; + } + } + + throw new InvalidOperationException("Could not determine server version."); + + IEnumerable ReadVersion(string s) { + foreach (var c in s.TakeWhile(c => c == '.' || char.IsDigit(c))) { + yield return c; + } + } + } + } + + public async Task DisposeAsync() { + try { + await OnTearDown(); + } catch { + // ignored + } + + await Service.DisposeAsync().AsTask().WithTimeout(FromMinutes(5)); + + foreach (var testRunId in TestRuns) + Logging.ReleaseLogs(testRunId); + } + + async ValueTask IAsyncDisposable.DisposeAsync() => await DisposeAsync(); +} + +public abstract class KurrentPermanentTests : IClassFixture where TFixture : KurrentPermanentFixture { + protected KurrentPermanentTests(ITestOutputHelper output, TFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); + + protected TFixture Fixture { get; } +} diff --git a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestNode.cs b/test/Kurrent.Client.Tests.Common/Fixtures/KurrentPermanentTestNode.cs similarity index 52% rename from test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestNode.cs rename to test/Kurrent.Client.Tests.Common/Fixtures/KurrentPermanentTestNode.cs index 7f1da49d0..c39895cf1 100644 --- a/test/EventStore.Client.Tests.Common/Fixtures/EventStoreTestNode.cs +++ b/test/Kurrent.Client.Tests.Common/Fixtures/KurrentPermanentTestNode.cs @@ -1,30 +1,68 @@ +// ReSharper disable InconsistentNaming + +// using Ductus.FluentDocker.Builders; +// using Ductus.FluentDocker.Model.Builders; +// using Kurrent.Client.Tests.FluentDocker; +// +// namespace Kurrent.Client.Tests; +// +// public class EventStorePermanentTestNode(EventStoreFixtureOptions? options = null) : BaseTestNode(options) { +// protected override ContainerBuilder ConfigureContainer(ContainerBuilder builder) { +// var port = Options.ClientSettings.ConnectivitySettings.ResolvedAddressOrDefault.Port; +// var certsPath = Path.Combine(Environment.CurrentDirectory, "certs"); +// +// var containerName = "es-client-dotnet-test"; +// +// return builder +// .UseImage(Options.Environment["ES_DOCKER_IMAGE"]) +// .WithName(containerName) +// .WithPublicEndpointResolver() +// .MountVolume(certsPath, "/etc/eventstore/certs", MountType.ReadOnly) +// .ExposePort(port, 2113) +// .KeepContainer().KeepRunning().ReuseIfExists() +// .WaitUntilReadyWithConstantBackoff( +// 1_000, +// 60, +// service => { +// var output = service.ExecuteCommand("curl -u admin:changeit --cacert /etc/eventstore/certs/ca/ca.crt https://localhost:2113/health/live"); +// if (!output.Success) +// throw new Exception(output.Error); +// } +// ); +// } +// } + +using System.Globalization; using System.Net; -using System.Net.Http; using System.Net.Sockets; using Ductus.FluentDocker.Builders; -using Ductus.FluentDocker.Common; +using Ductus.FluentDocker.Extensions; using Ductus.FluentDocker.Model.Builders; -using EventStore.Client.Tests.FluentDocker; -using Polly; -using Polly.Contrib.WaitAndRetry; +using Ductus.FluentDocker.Services.Extensions; +using EventStore.Client; +using Kurrent.Client; +using Kurrent.Client.Tests.FluentDocker; +using Humanizer; +using Kurrent.Client.Tests; using Serilog; using Serilog.Extensions.Logging; using static System.TimeSpan; -namespace EventStore.Client.Tests; - -public class EventStoreTestNode(EventStoreFixtureOptions? options = null) : TestContainerService { - +public class KurrentPermanentTestNode(KurrentFixtureOptions? options = null) : TestContainerService { static readonly NetworkPortProvider NetworkPortProvider = new(NetworkPortProvider.DefaultEsdbPort); - - EventStoreFixtureOptions Options { get; } = options ?? DefaultOptions(); - public static EventStoreFixtureOptions DefaultOptions() { + KurrentFixtureOptions Options { get; } = options ?? DefaultOptions(); + + static Version? _version; + + public static Version Version => _version ??= GetVersion(); + + public static KurrentFixtureOptions DefaultOptions() { const string connString = "esdb://admin:changeit@localhost:{port}/?tlsVerifyCert=false"; - + var port = NetworkPortProvider.NextAvailablePort; - - var defaultSettings = EventStoreClientSettings + + var defaultSettings = KurrentClientSettings .Create(connString.Replace("{port}", $"{port}")) .With(x => x.LoggerFactory = new SerilogLoggerFactory(Log.Logger)) .With(x => x.DefaultDeadline = Application.DebuggerIsAttached ? new TimeSpan?() : FromSeconds(30)) @@ -33,13 +71,17 @@ public static EventStoreFixtureOptions DefaultOptions() { var defaultEnvironment = new Dictionary(GlobalEnvironment.Variables) { ["EVENTSTORE_MEM_DB"] = "true", - ["EVENTSTORE_CHUNK_SIZE"] = (1024 * 1024 * 1024).ToString(), ["EVENTSTORE_CERTIFICATE_FILE"] = "/etc/eventstore/certs/node/node.crt", ["EVENTSTORE_CERTIFICATE_PRIVATE_KEY_FILE"] = "/etc/eventstore/certs/node/node.key", ["EVENTSTORE_STREAM_EXISTENCE_FILTER_SIZE"] = "10000", ["EVENTSTORE_STREAM_INFO_CACHE_CAPACITY"] = "10000", ["EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP"] = "true", + ["EVENTSTORE_LOG_LEVEL"] = "Default", // required to use serilog settings ["EVENTSTORE_DISABLE_LOG_FILE"] = "true", + ["EVENTSTORE_START_STANDARD_PROJECTIONS"] = "true", + ["EVENTSTORE_RUN_PROJECTIONS"] = "All", + ["EVENTSTORE_CHUNK_SIZE"] = (1024 * 1024 * 1024).ToString(), + ["EVENTSTORE_MAX_APPEND_SIZE"] = 100.Kilobytes().Bytes.ToString(CultureInfo.InvariantCulture), ["EVENTSTORE_ADVERTISE_HTTP_PORT_TO_CLIENT_AS"] = $"{NetworkPortProvider.DefaultEsdbPort}" }; @@ -48,17 +90,43 @@ public static EventStoreFixtureOptions DefaultOptions() { defaultEnvironment["EventStore__Plugins__UserCertificates__Enabled"] = "true"; } - // TODO SS: must find a way to enable parallel tests on CI. It works locally. if (port != NetworkPortProvider.DefaultEsdbPort) { if (GlobalEnvironment.Variables.TryGetValue("ES_DOCKER_TAG", out var tag) && tag == "ci") defaultEnvironment["EVENTSTORE_ADVERTISE_NODE_PORT_TO_CLIENT_AS"] = $"{port}"; else defaultEnvironment["EVENTSTORE_ADVERTISE_HTTP_PORT_TO_CLIENT_AS"] = $"{port}"; } - + return new(defaultSettings, defaultEnvironment); } + static Version GetVersion() { + const string versionPrefix = "EventStoreDB version"; + + using var cts = new CancellationTokenSource(FromSeconds(30)); + using var eventstore = new Builder().UseContainer() + .UseImage(GlobalEnvironment.DockerImage) + .Command("--version") + .Build() + .Start(); + + using var log = eventstore.Logs(true, cts.Token); + foreach (var line in log.ReadToEnd()) { + if (line.StartsWith(versionPrefix) && + Version.TryParse(new string(ReadVersion(line[(versionPrefix.Length + 1)..]).ToArray()), out var version)) { + return version; + } + } + + throw new InvalidOperationException("Could not determine server version."); + + IEnumerable ReadVersion(string s) { + foreach (var c in s.TakeWhile(c => c == '.' || char.IsDigit(c))) { + yield return c; + } + } + } + protected override ContainerBuilder Configure() { var env = Options.Environment.Select(pair => $"{pair.Key}={pair.Value}").ToArray(); @@ -75,34 +143,18 @@ protected override ContainerBuilder Configure() { .UseContainer() .UseImage(Options.Environment["ES_DOCKER_IMAGE"]) .WithName(containerName) + .WithPublicEndpointResolver() .WithEnvironment(env) .MountVolume(certsPath, "/etc/eventstore/certs", MountType.ReadOnly) - .ExposePort(port, 2113); - } - - /// - /// max of 30 seconds (300 * 100ms) - /// - static readonly IEnumerable DefaultBackoffDelay = Backoff.ConstantBackoff(FromMilliseconds(100), 300); - - protected override async Task OnServiceStarted() { - using var http = new HttpClient( -#if NET - new SocketsHttpHandler { SslOptions = { RemoteCertificateValidationCallback = delegate { return true; } } } -#else - new WinHttpHandler { ServerCertificateValidationCallback = delegate { return true; } } -#endif - ) { - BaseAddress = Options.ClientSettings.ConnectivitySettings.Address - }; - - await Policy.Handle() - .WaitAndRetryAsync(DefaultBackoffDelay) - .ExecuteAsync( - async () => { - using var response = await http.GetAsync("/health/live", CancellationToken.None); - if (response.StatusCode >= HttpStatusCode.BadRequest) - throw new FluentDockerException($"Health check failed with status code: {response.StatusCode}."); + .ExposePort(port, 2113) + .KeepContainer().KeepRunning().ReuseIfExists() + .WaitUntilReadyWithConstantBackoff( + 1_000, + 60, + service => { + var output = service.ExecuteCommand("curl -u admin:changeit --cacert /etc/eventstore/certs/ca/ca.crt https://localhost:2113/health/live"); + if (!output.Success) + throw new Exception(output.Error); } ); } @@ -114,42 +166,39 @@ await Policy.Handle() /// class NetworkPortProvider(int port = 2114) { public const int DefaultEsdbPort = 2113; - + static readonly SemaphoreSlim Semaphore = new(1, 1); - public async Task GetNextAvailablePort(TimeSpan delay = default) { + async Task GetNextAvailablePort(TimeSpan delay = default) { // TODO SS: find a way to enable parallel tests on CI if (port == DefaultEsdbPort) return port; await Semaphore.WaitAsync(); - + try { using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - + while (true) { var nexPort = Interlocked.Increment(ref port); - + try { await socket.ConnectAsync(IPAddress.Any, nexPort); - } - catch (SocketException ex) { + } catch (SocketException ex) { if (ex.SocketErrorCode is SocketError.ConnectionRefused or not SocketError.IsConnected) { return nexPort; } - + await Task.Delay(delay); - } - finally { + } finally { #if NET if (socket.Connected) await socket.DisconnectAsync(true); #else - if (socket.Connected) socket.Disconnect(true); + if (socket.Connected) socket.Disconnect(true); #endif } } - } - finally { + } finally { Semaphore.Release(); } } diff --git a/test/Kurrent.Client.Tests.Common/Fixtures/KurrentTemporaryFixture.Helpers.cs b/test/Kurrent.Client.Tests.Common/Fixtures/KurrentTemporaryFixture.Helpers.cs new file mode 100644 index 000000000..31da9f154 --- /dev/null +++ b/test/Kurrent.Client.Tests.Common/Fixtures/KurrentTemporaryFixture.Helpers.cs @@ -0,0 +1,108 @@ +using System.Runtime.CompilerServices; +using System.Text; +using EventStore.Client; + +namespace Kurrent.Client.Tests.TestNode; + +public partial class KurrentTemporaryFixture { + public const string TestEventType = "test-event-type"; + public const string AnotherTestEventTypePrefix = "another"; + public const string AnotherTestEventType = $"{AnotherTestEventTypePrefix}-test-event-type"; + + public T NewClient(Action configure) where T : KurrentClientBase, new() => + (T)Activator.CreateInstance(typeof(T), [ClientSettings.With(configure)])!; + + public string GetStreamName([CallerMemberName] string? testMethod = null) => + $"stream-{testMethod}-{Guid.NewGuid():N}"; + + public string GetGroupName([CallerMemberName] string? testMethod = null) => + $"group-{testMethod}-{Guid.NewGuid():N}"; + + public UserCredentials GetUserCredentials([CallerMemberName] string? testMethod = null) => new UserCredentials( + $"user-{testMethod}-{Guid.NewGuid():N}", + "pa$$word" + ); + + public string GetProjectionName([CallerMemberName] string? testMethod = null) => + $"projection-{testMethod}-{Guid.NewGuid():N}"; + + public ReadOnlyMemory CreateMetadataOfSize(int metadataSize) => + Encoding.UTF8.GetBytes($"\"{new string('$', metadataSize)}\""); + + public ReadOnlyMemory CreateTestJsonMetadata() => "{\"Foo\": \"Bar\"}"u8.ToArray(); + + public ReadOnlyMemory CreateTestNonJsonMetadata() => "non-json-metadata"u8.ToArray(); + + public (IEnumerable Events, uint size) CreateTestEventsUpToMaxSize(uint maxSize) { + var size = 0; + + var events = CreateTestEvents(int.MaxValue) + .TakeWhile(evt => (size += evt.Data.Length) < maxSize) + .ToList(); + + return (events, (uint)size); + } + + public IEnumerable CreateTestEvents( + int count = 1, string? type = null, ReadOnlyMemory? metadata = null, string? contentType = null + ) => + Enumerable.Range(0, count) + .Select(index => CreateTestEvent(index, type ?? TestEventType, metadata, contentType)); + + public EventData CreateTestEvent( + string? type = null, ReadOnlyMemory? metadata = null, string? contentType = null + ) => + CreateTestEvent(0, type ?? TestEventType, metadata, contentType); + + public IEnumerable CreateTestEventsThatThrowsException() { + // Ensure initial IEnumerator.Current does not throw + yield return CreateTestEvent(1); + + // Throw after enumerator advances + throw new Exception(); + } + + protected static EventData CreateTestEvent(int index) => CreateTestEvent(index, TestEventType); + + protected static EventData CreateTestEvent( + int index, string type, ReadOnlyMemory? metadata = null, string? contentType = null + ) => + new( + Uuid.NewUuid(), + type, + Encoding.UTF8.GetBytes($$"""{"x":{{index}}}"""), + metadata, + contentType ?? "application/json" + ); + + public async Task CreateTestUser(bool withoutGroups = true, bool useUserCredentials = false) { + var result = await CreateTestUsers(1, withoutGroups, useUserCredentials); + return result.First(); + } + + public Task CreateTestUsers( + int count = 3, bool withoutGroups = true, bool useUserCredentials = false + ) => + Fakers.Users + .RuleFor(x => x.Groups, f => withoutGroups ? Array.Empty() : f.Lorem.Words()) + .Generate(count) + .Select( + async user => { + await Users.CreateUserAsync( + user.LoginName, + user.FullName, + user.Groups, + user.Password, + userCredentials: useUserCredentials ? user.Credentials : TestCredentials.Root + ); + + return user; + } + ).WhenAll(); + + public async Task RestartService(TimeSpan delay) { + await Service.Restart(delay); + await Streams.WarmUp(); + Log.Information("Service restarted."); + } +} diff --git a/test/Kurrent.Client.Tests.Common/Fixtures/KurrentTemporaryFixture.cs b/test/Kurrent.Client.Tests.Common/Fixtures/KurrentTemporaryFixture.cs new file mode 100644 index 000000000..8a71891ca --- /dev/null +++ b/test/Kurrent.Client.Tests.Common/Fixtures/KurrentTemporaryFixture.cs @@ -0,0 +1,185 @@ +// ReSharper disable InconsistentNaming + +using System.Net; +using Ductus.FluentDocker.Builders; +using Ductus.FluentDocker.Extensions; +using Ductus.FluentDocker.Services.Extensions; +using EventStore.Client; +using Kurrent.Client.Tests.FluentDocker; +using Serilog; +using static System.TimeSpan; +using KurrentClient = EventStore.Client.KurrentClient; + +namespace Kurrent.Client.Tests.TestNode; + +[PublicAPI] +public partial class KurrentTemporaryFixture : IAsyncLifetime, IAsyncDisposable { + static readonly ILogger Logger; + + static KurrentTemporaryFixture() { + Logging.Initialize(); + Logger = Serilog.Log.ForContext(); + +#if NET9_0_OR_GREATER + var httpClientHandler = new HttpClientHandler(); + httpClientHandler.ServerCertificateCustomValidationCallback = delegate { return true; }; +#else + ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; +#endif + } + + public KurrentTemporaryFixture() : this(options => options) { } + + protected KurrentTemporaryFixture(ConfigureFixture configure) { + // Options = configure(EventStoreTemporaryTestNode.DefaultOptions()); + Options = configure(KurrentTemporaryTestNode.DefaultOptions()); + Service = new KurrentTemporaryTestNode(Options); + } + + List TestRuns { get; } = new(); + + public ILogger Log => Logger; + + public ITestService Service { get; } + public KurrentFixtureOptions Options { get; } + public Faker Faker { get; } = new Faker(); + + public Version EventStoreVersion { get; private set; } = null!; + public bool EventStoreHasLastStreamPosition { get; private set; } + + public KurrentClient Streams { get; private set; } = null!; + public KurrentUserManagementClient Users { get; private set; } = null!; + public KurrentProjectionManagementClient Projections { get; private set; } = null!; + public KurrentPersistentSubscriptionsClient Subscriptions { get; private set; } = null!; + public KurrentOperationsClient Operations { get; private set; } = null!; + + public bool SkipPsWarmUp { get; set; } + + public Func OnSetup { get; init; } = () => Task.CompletedTask; + public Func OnTearDown { get; init; } = () => Task.CompletedTask; + + /// + /// must test this + /// + public KurrentClientSettings ClientSettings => + new() { + Interceptors = Options.ClientSettings.Interceptors, + ConnectionName = Options.ClientSettings.ConnectionName, + CreateHttpMessageHandler = Options.ClientSettings.CreateHttpMessageHandler, + LoggerFactory = Options.ClientSettings.LoggerFactory, + ChannelCredentials = Options.ClientSettings.ChannelCredentials, + OperationOptions = Options.ClientSettings.OperationOptions, + ConnectivitySettings = Options.ClientSettings.ConnectivitySettings, + DefaultCredentials = Options.ClientSettings.DefaultCredentials, + DefaultDeadline = Options.ClientSettings.DefaultDeadline + }; + + InterlockedBoolean WarmUpCompleted { get; } = new InterlockedBoolean(); + static readonly SemaphoreSlim WarmUpGatekeeper = new(1, 1); + + public void CaptureTestRun(ITestOutputHelper outputHelper) { + var testRunId = Logging.CaptureLogs(outputHelper); + TestRuns.Add(testRunId); + Logger.Information(">>> Test Run {TestRunId} {Operation} <<<", testRunId, "starting"); + Service.ReportStatus(); + } + + public async Task InitializeAsync() { + await WarmUpGatekeeper.WaitAsync(); + + try { + await Service.Start(); + EventStoreVersion = GetKurrentVersion(); + EventStoreHasLastStreamPosition = (EventStoreVersion?.Major ?? int.MaxValue) >= 21; + + if (!WarmUpCompleted.CurrentValue) { + Logger.Warning("*** Warmup started ***"); + + await Task.WhenAll( + InitClient(async x => Users = await Task.FromResult(x)), + InitClient(async x => Streams = await Task.FromResult(x)), + InitClient( + async x => Projections = await Task.FromResult(x), + Options.Environment["EVENTSTORE_RUN_PROJECTIONS"] != "None" + ), + InitClient(async x => Subscriptions = SkipPsWarmUp ? x : await Task.FromResult(x)), + InitClient(async x => Operations = await Task.FromResult(x)) + ); + + WarmUpCompleted.EnsureCalledOnce(); + + Logger.Warning("*** Warmup completed ***"); + } else { + Logger.Information("*** Warmup skipped ***"); + } + } finally { + WarmUpGatekeeper.Release(); + } + + await OnSetup(); + + return; + + async Task InitClient(Func action, bool execute = true) where T : KurrentClientBase { + if (!execute) return default(T)!; + + var client = (Activator.CreateInstance(typeof(T), ClientSettings) as T)!; + await action(client); + return client; + } + + static Version GetKurrentVersion() { + 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()) { + Logger.Information("EventStoreDB: {Line}", line); + if (line.StartsWith(versionPrefix) && + Version.TryParse( + new string(ReadVersion(line[(versionPrefix.Length + 1)..]).ToArray()), + out var version + )) { + return version; + } + } + + throw new InvalidOperationException("Could not determine server version."); + + IEnumerable ReadVersion(string s) { + foreach (var c in s.TakeWhile(c => c == '.' || char.IsDigit(c))) { + yield return c; + } + } + } + } + + public async Task DisposeAsync() { + try { + await OnTearDown(); + } catch { + // ignored + } + + await Service.DisposeAsync().AsTask().WithTimeout(FromMinutes(5)); + + foreach (var testRunId in TestRuns) + Logging.ReleaseLogs(testRunId); + } + + async ValueTask IAsyncDisposable.DisposeAsync() => await DisposeAsync(); +} + +public abstract class KurrentTemporaryTests : IClassFixture where TFixture : KurrentTemporaryFixture { + protected KurrentTemporaryTests(ITestOutputHelper output, TFixture fixture) => + Fixture = fixture.With(x => x.CaptureTestRun(output)); + + protected TFixture Fixture { get; } +} diff --git a/test/Kurrent.Client.Tests.Common/Fixtures/KurrentTemporaryTestNode.cs b/test/Kurrent.Client.Tests.Common/Fixtures/KurrentTemporaryTestNode.cs new file mode 100644 index 000000000..7a6a98965 --- /dev/null +++ b/test/Kurrent.Client.Tests.Common/Fixtures/KurrentTemporaryTestNode.cs @@ -0,0 +1,199 @@ +// ReSharper disable InconsistentNaming + +// using Ductus.FluentDocker.Builders; +// using Ductus.FluentDocker.Model.Builders; +// using Kurrent.Client.Tests.FluentDocker; +// +// namespace Kurrent.Client.Tests.TestNode; +// +// public class EventStoreTemporaryTestNode(EventStoreFixtureOptions? options = null) : BaseTestNode(options) { +// protected override ContainerBuilder ConfigureContainer(ContainerBuilder builder) { +// var port = Options.ClientSettings.ConnectivitySettings.ResolvedAddressOrDefault.Port; +// var certsPath = Path.Combine(Environment.CurrentDirectory, "certs"); +// +// var containerName = $"es-client-dotnet-test-{port}-{Guid.NewGuid().ToString()[30..]}"; +// +// return builder +// .UseImage(Options.Environment["ES_DOCKER_IMAGE"]) +// .WithName(containerName) +// .WithPublicEndpointResolver() +// .MountVolume(certsPath, "/etc/eventstore/certs", MountType.ReadOnly) +// .ExposePort(port, 2113) +// .WaitUntilReadyWithConstantBackoff( +// 1_000, +// 60, +// service => { +// var output = service.ExecuteCommand("curl -u admin:changeit --cacert /etc/eventstore/certs/ca/ca.crt https://localhost:2113/health/live"); +// if (!output.Success) +// throw new Exception(output.Error); +// } +// ); +// } +// } + +using System.Globalization; +using System.Net; +using System.Net.Sockets; +using Ductus.FluentDocker.Builders; +using Ductus.FluentDocker.Extensions; +using Ductus.FluentDocker.Model.Builders; +using Ductus.FluentDocker.Services.Extensions; +using EventStore.Client; +using Kurrent.Client.Tests.FluentDocker; +using Humanizer; +using Serilog; +using Serilog.Extensions.Logging; +using static System.TimeSpan; + +namespace Kurrent.Client.Tests.TestNode; + +public class KurrentTemporaryTestNode(KurrentFixtureOptions? options = null) : TestContainerService { + static readonly NetworkPortProvider NetworkPortProvider = new(NetworkPortProvider.DefaultEsdbPort); + + KurrentFixtureOptions Options { get; } = options ?? DefaultOptions(); + + static Version? _version; + + public static Version Version => _version ??= GetVersion(); + + public static KurrentFixtureOptions DefaultOptions() { + const string connString = "esdb://admin:changeit@localhost:{port}/?tlsVerifyCert=false"; + + var port = NetworkPortProvider.NextAvailablePort; + + var defaultSettings = KurrentClientSettings + .Create(connString.Replace("{port}", $"{port}")) + .With(x => x.LoggerFactory = new SerilogLoggerFactory(Log.Logger)) + .With(x => x.DefaultDeadline = Application.DebuggerIsAttached ? new TimeSpan?() : FromSeconds(30)) + .With(x => x.ConnectivitySettings.MaxDiscoverAttempts = 20) + .With(x => x.ConnectivitySettings.DiscoveryInterval = FromSeconds(1)); + + var defaultEnvironment = new Dictionary(GlobalEnvironment.Variables) { + ["EVENTSTORE_MEM_DB"] = "true", + ["EVENTSTORE_CERTIFICATE_FILE"] = "/etc/eventstore/certs/node/node.crt", + ["EVENTSTORE_CERTIFICATE_PRIVATE_KEY_FILE"] = "/etc/eventstore/certs/node/node.key", + ["EVENTSTORE_STREAM_EXISTENCE_FILTER_SIZE"] = "10000", + ["EVENTSTORE_STREAM_INFO_CACHE_CAPACITY"] = "10000", + ["EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP"] = "true", + ["EVENTSTORE_LOG_LEVEL"] = "Default", // required to use serilog settings + ["EVENTSTORE_DISABLE_LOG_FILE"] = "true", + ["EVENTSTORE_CHUNK_SIZE"] = (1024 * 1024 * 1024).ToString(), + ["EVENTSTORE_MAX_APPEND_SIZE"] = 100.Kilobytes().Bytes.ToString(CultureInfo.InvariantCulture), + ["EVENTSTORE_ADVERTISE_HTTP_PORT_TO_CLIENT_AS"] = $"{NetworkPortProvider.DefaultEsdbPort}" + }; + + if (GlobalEnvironment.DockerImage.Contains("commercial")) { + defaultEnvironment["EVENTSTORE_TRUSTED_ROOT_CERTIFICATES_PATH"] = "/etc/eventstore/certs/ca"; + defaultEnvironment["EventStore__Plugins__UserCertificates__Enabled"] = "true"; + } + + if (port != NetworkPortProvider.DefaultEsdbPort) { + if (GlobalEnvironment.Variables.TryGetValue("ES_DOCKER_TAG", out var tag) && tag == "ci") + defaultEnvironment["EVENTSTORE_ADVERTISE_NODE_PORT_TO_CLIENT_AS"] = $"{port}"; + else + defaultEnvironment["EVENTSTORE_ADVERTISE_HTTP_PORT_TO_CLIENT_AS"] = $"{port}"; + } + + return new(defaultSettings, defaultEnvironment); + } + + static Version GetVersion() { + const string versionPrefix = "EventStoreDB version"; + + using var cts = new CancellationTokenSource(FromSeconds(30)); + using var eventstore = new Builder().UseContainer() + .UseImage(GlobalEnvironment.DockerImage) + .Command("--version") + .Build() + .Start(); + + using var log = eventstore.Logs(true, cts.Token); + foreach (var line in log.ReadToEnd()) { + if (line.StartsWith(versionPrefix) && + Version.TryParse(new string(ReadVersion(line[(versionPrefix.Length + 1)..]).ToArray()), out var version)) { + return version; + } + } + + throw new InvalidOperationException("Could not determine server version."); + + IEnumerable ReadVersion(string s) { + foreach (var c in s.TakeWhile(c => c == '.' || char.IsDigit(c))) { + yield return c; + } + } + } + + protected override ContainerBuilder Configure() { + var env = Options.Environment.Select(pair => $"{pair.Key}={pair.Value}").ToArray(); + + var port = Options.ClientSettings.ConnectivitySettings.ResolvedAddressOrDefault.Port; + var certsPath = Path.Combine(Environment.CurrentDirectory, "certs"); + + var containerName = $"es-client-dotnet-test-{port}-{Guid.NewGuid().ToString()[30..]}"; + + CertificatesManager.VerifyCertificatesExist(certsPath); + + var builder = new Builder() + .UseContainer() + .UseImage(Options.Environment["ES_DOCKER_IMAGE"]) + .WithName(containerName) + .WithPublicEndpointResolver() + .WithEnvironment(env) + .MountVolume(certsPath, "/etc/eventstore/certs", MountType.ReadOnly) + .ExposePort(port, 2113) + .WaitUntilReadyWithConstantBackoff( + 1_000, + 60, + service => { + var output = service.ExecuteCommand("curl -u admin:changeit --cacert /etc/eventstore/certs/ca/ca.crt https://localhost:2113/health/live"); + if (!output.Success) + throw new Exception(output.Error); + } + ); + + return builder; + } +} + +/// +/// Using the default 2113 port assumes that the test is running sequentially. +/// +/// +class NetworkPortProvider(int port = 2114) { + public const int DefaultEsdbPort = 2113; + + static readonly SemaphoreSlim Semaphore = new(1, 1); + + async Task GetNextAvailablePort(TimeSpan delay = default) { + await Semaphore.WaitAsync(); + + try { + using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + + while (true) { + var nexPort = Interlocked.Increment(ref port); + + try { + await socket.ConnectAsync(IPAddress.Any, nexPort); + } catch (SocketException ex) { + if (ex.SocketErrorCode is SocketError.ConnectionRefused or not SocketError.IsConnected) { + return nexPort; + } + + await Task.Delay(delay); + } finally { +#if NET + if (socket.Connected) await socket.DisconnectAsync(true); +#else + if (socket.Connected) socket.Disconnect(true); +#endif + } + } + } finally { + Semaphore.Release(); + } + } + + public int NextAvailablePort => GetNextAvailablePort(FromMilliseconds(100)).GetAwaiter().GetResult(); +} diff --git a/test/Kurrent.Client.Tests.Common/FluentDocker/FluentDockerBuilderExtensions.cs b/test/Kurrent.Client.Tests.Common/FluentDocker/FluentDockerBuilderExtensions.cs new file mode 100644 index 000000000..506b4e98f --- /dev/null +++ b/test/Kurrent.Client.Tests.Common/FluentDocker/FluentDockerBuilderExtensions.cs @@ -0,0 +1,88 @@ +using System.Reflection; +using Ductus.FluentDocker.Builders; +using Ductus.FluentDocker.Common; +using Ductus.FluentDocker.Model.Compose; +using Ductus.FluentDocker.Services; +using Ductus.FluentDocker.Services.Impl; +using Polly; +using Polly.Contrib.WaitAndRetry; +using static System.TimeSpan; + +namespace Kurrent.Client.Tests.FluentDocker; + +public static class FluentDockerBuilderExtensions { + public static CompositeBuilder OverrideConfiguration(this CompositeBuilder compositeBuilder, Action configure) { + configure(GetInternalConfig(compositeBuilder)); + return compositeBuilder; + + static DockerComposeConfig GetInternalConfig(CompositeBuilder compositeBuilder) => + (DockerComposeConfig)typeof(CompositeBuilder) + .GetField("_config", BindingFlags.NonPublic | BindingFlags.Instance)! + .GetValue(compositeBuilder)!; + } + + public static DockerComposeConfig Configuration(this ICompositeService service) => + (DockerComposeConfig)typeof(DockerComposeCompositeService) + .GetProperty("Config", BindingFlags.NonPublic | BindingFlags.Instance)! + .GetValue(service)!; +} + +[PublicAPI] +public static class FluentDockerContainerBuilderExtensions { + public static ContainerBuilder WithEnvironment(this ContainerBuilder builder, Dictionary environment) => + builder.WithEnvironment(environment.Select(pair => $"{pair.Key}={pair.Value}").ToArray()); + + public static ContainerBuilder WaitUntilReady(this ContainerBuilder builder, IEnumerable sleepDurations, Action action) => + builder.Wait("", (service, _) => { + var result = Policy + .Handle() + .WaitAndRetry(sleepDurations) + .ExecuteAndCapture(() => action(service)); + + if (result.Outcome == OutcomeType.Successful) + return 0; + + throw result.FinalException is FluentDockerException + ? result.FinalException + : new FluentDockerException($"Service {service.Name} not ready: {result.FinalException.Message}"); + }); + + public static ContainerBuilder WaitUntilReadyWithConstantBackoff( + this ContainerBuilder builder, TimeSpan delay, int retryCount, Action action + ) => builder.WaitUntilReady(Backoff.ConstantBackoff(delay, retryCount), action); + + public static ContainerBuilder WaitUntilReadyWithExponentialBackoff( + this ContainerBuilder builder, TimeSpan delay, int retryCount, Action action + ) => builder.WaitUntilReady(Backoff.ExponentialBackoff(delay, retryCount), action); + + public static ContainerBuilder WaitUntilReadyWithConstantBackoff( + this ContainerBuilder builder, int delayMs, int retryCount, Action action + ) => builder.WaitUntilReadyWithConstantBackoff(FromMilliseconds(delayMs), retryCount, action); + + public static ContainerBuilder WaitUntilReadyWithExponentialBackoff( + this ContainerBuilder builder, int delayMs, int retryCount, Action action + ) => builder.WaitUntilReadyWithExponentialBackoff(FromMilliseconds(delayMs), retryCount, action); + + public static ContainerBuilder WaitUntilReadyAsync(this ContainerBuilder builder, IEnumerable sleepDurations, Func action) => + builder.WaitUntilReady(sleepDurations, service => { + var valueTask = action(service); + if (!valueTask.IsCompletedSuccessfully) + valueTask.AsTask().GetAwaiter().GetResult(); + }); + + public static ContainerBuilder WaitUntilReadyWithConstantBackoffAsync( + this ContainerBuilder builder, TimeSpan delay, int retryCount, Func action + ) => builder.WaitUntilReadyAsync(Backoff.ConstantBackoff(delay, retryCount, fastFirst: true), action); + + public static ContainerBuilder WaitUntilReadyWithExponentialBackoffAsync( + this ContainerBuilder builder, TimeSpan delay, int retryCount, Func action + ) => builder.WaitUntilReadyAsync(Backoff.ExponentialBackoff(delay, retryCount, fastFirst: true), action); + + public static ContainerBuilder WaitUntilReadyWithConstantBackoffAsync( + this ContainerBuilder builder, int delayMs, int retryCount, Func action + ) => builder.WaitUntilReadyWithConstantBackoffAsync(FromMilliseconds(delayMs), retryCount, action); + + public static ContainerBuilder WaitUntilReadyWithExponentialBackoffAsync( + this ContainerBuilder builder, int delayMs, int retryCount, Func action + ) => builder.WaitUntilReadyWithExponentialBackoffAsync(FromMilliseconds(delayMs), retryCount, action); +} diff --git a/test/EventStore.Client.Tests.Common/FluentDocker/FluentDockerServiceExtensions.cs b/test/Kurrent.Client.Tests.Common/FluentDocker/FluentDockerServiceExtensions.cs similarity index 62% rename from test/EventStore.Client.Tests.Common/FluentDocker/FluentDockerServiceExtensions.cs rename to test/Kurrent.Client.Tests.Common/FluentDocker/FluentDockerServiceExtensions.cs index c4773cede..b14bb7a43 100644 --- a/test/EventStore.Client.Tests.Common/FluentDocker/FluentDockerServiceExtensions.cs +++ b/test/Kurrent.Client.Tests.Common/FluentDocker/FluentDockerServiceExtensions.cs @@ -1,10 +1,14 @@ #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously +using System.Net; +using Ductus.FluentDocker.Builders; +using Ductus.FluentDocker.Commands; using Ductus.FluentDocker.Common; using Ductus.FluentDocker.Model.Containers; using Ductus.FluentDocker.Services; +using Ductus.FluentDocker.Services.Extensions; -namespace EventStore.Client.Tests.FluentDocker; +namespace Kurrent.Client.Tests.FluentDocker; public static class FluentDockerServiceExtensions { static readonly TimeSpan DefaultRetryDelay = TimeSpan.FromMilliseconds(100); @@ -60,3 +64,25 @@ public static async Task WaitUntilNodesAreHealthy(this ICompositeService service await WaitUntilNodesAreHealthy(service, serviceNamePrefix, cts.Token); } } + +public static class FluentDockerContainerServiceExtensions { + // IPAddress.Any defaults to IPAddress.Loopback + public static IPEndPoint GetPublicEndpoint(this IContainerService service, string portAndProtocol) { + var endpoint = service.ToHostExposedEndpoint(portAndProtocol); + return endpoint.Address.Equals(IPAddress.Any) ? new IPEndPoint(IPAddress.Loopback, endpoint.Port) : endpoint; + } + + public static IPEndPoint GetPublicEndpoint(this IContainerService service, int port) => + service.GetPublicEndpoint($"{port}/tcp"); + + public static ContainerBuilder WithPublicEndpointResolver(this ContainerBuilder builder) => + builder.UseCustomResolver((endpoints, portAndProtocol, dockerUri) => { + var endpoint = endpoints.ToHostPort(portAndProtocol, dockerUri); + return endpoint.Address.Equals(IPAddress.Any) ? new IPEndPoint(IPAddress.Loopback, endpoint.Port) : endpoint; + }); + + public static CommandResponse> ExecuteCommand(this IContainerService service, string command) { + var config = service.GetConfiguration(); + return service.DockerHost.Execute(config.Id, command, service.Certificates); + } +} diff --git a/test/EventStore.Client.Tests.Common/FluentDocker/TestBypassService.cs b/test/Kurrent.Client.Tests.Common/FluentDocker/TestBypassService.cs similarity index 97% rename from test/EventStore.Client.Tests.Common/FluentDocker/TestBypassService.cs rename to test/Kurrent.Client.Tests.Common/FluentDocker/TestBypassService.cs index 3505eb9af..d09069d48 100644 --- a/test/EventStore.Client.Tests.Common/FluentDocker/TestBypassService.cs +++ b/test/Kurrent.Client.Tests.Common/FluentDocker/TestBypassService.cs @@ -2,7 +2,7 @@ using Ductus.FluentDocker.Common; using Ductus.FluentDocker.Services; -namespace EventStore.Client.Tests.FluentDocker; +namespace Kurrent.Client.Tests.FluentDocker; public class TestBypassService : TestService { protected override BypassBuilder Configure() => throw new NotImplementedException(); diff --git a/test/EventStore.Client.Tests.Common/FluentDocker/TestCompositeService.cs b/test/Kurrent.Client.Tests.Common/FluentDocker/TestCompositeService.cs similarity index 63% rename from test/EventStore.Client.Tests.Common/FluentDocker/TestCompositeService.cs rename to test/Kurrent.Client.Tests.Common/FluentDocker/TestCompositeService.cs index 104827f30..a321ad77d 100644 --- a/test/EventStore.Client.Tests.Common/FluentDocker/TestCompositeService.cs +++ b/test/Kurrent.Client.Tests.Common/FluentDocker/TestCompositeService.cs @@ -1,6 +1,6 @@ using Ductus.FluentDocker.Builders; using Ductus.FluentDocker.Services; -namespace EventStore.Client.Tests.FluentDocker; +namespace Kurrent.Client.Tests.FluentDocker; -public abstract class TestCompositeService : TestService; \ No newline at end of file +public abstract class TestCompositeService : TestService; diff --git a/test/EventStore.Client.Tests.Common/FluentDocker/TestContainerService.cs b/test/Kurrent.Client.Tests.Common/FluentDocker/TestContainerService.cs similarity index 63% rename from test/EventStore.Client.Tests.Common/FluentDocker/TestContainerService.cs rename to test/Kurrent.Client.Tests.Common/FluentDocker/TestContainerService.cs index 40ed937fc..fb135276e 100644 --- a/test/EventStore.Client.Tests.Common/FluentDocker/TestContainerService.cs +++ b/test/Kurrent.Client.Tests.Common/FluentDocker/TestContainerService.cs @@ -1,6 +1,6 @@ using Ductus.FluentDocker.Builders; using Ductus.FluentDocker.Services; -namespace EventStore.Client.Tests.FluentDocker; +namespace Kurrent.Client.Tests.FluentDocker; -public abstract class TestContainerService : TestService; \ No newline at end of file +public abstract class TestContainerService : TestService; diff --git a/test/EventStore.Client.Tests.Common/FluentDocker/TestService.cs b/test/Kurrent.Client.Tests.Common/FluentDocker/TestService.cs similarity index 98% rename from test/EventStore.Client.Tests.Common/FluentDocker/TestService.cs rename to test/Kurrent.Client.Tests.Common/FluentDocker/TestService.cs index 890f4e9b6..4bb942517 100644 --- a/test/EventStore.Client.Tests.Common/FluentDocker/TestService.cs +++ b/test/Kurrent.Client.Tests.Common/FluentDocker/TestService.cs @@ -5,7 +5,7 @@ using Serilog; using static Serilog.Core.Constants; -namespace EventStore.Client.Tests.FluentDocker; +namespace Kurrent.Client.Tests.FluentDocker; public interface ITestService : IAsyncDisposable { Task Start(); diff --git a/test/EventStore.Client.Tests.Common/GlobalEnvironment.cs b/test/Kurrent.Client.Tests.Common/GlobalEnvironment.cs similarity index 63% rename from test/EventStore.Client.Tests.Common/GlobalEnvironment.cs rename to test/Kurrent.Client.Tests.Common/GlobalEnvironment.cs index d7d26dc67..5444a6be4 100644 --- a/test/EventStore.Client.Tests.Common/GlobalEnvironment.cs +++ b/test/Kurrent.Client.Tests.Common/GlobalEnvironment.cs @@ -1,7 +1,7 @@ using System.Collections.Immutable; using Microsoft.Extensions.Configuration; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; public static class GlobalEnvironment { static GlobalEnvironment() { @@ -26,6 +26,8 @@ static void EnsureDefaults(IConfiguration configuration) { configuration.EnsureValue("ES_DOCKER_TAG", "ci"); configuration.EnsureValue("ES_DOCKER_IMAGE", $"{configuration["ES_DOCKER_REGISTRY"]}:{configuration["ES_DOCKER_TAG"]}"); + configuration.EnsureValue("EVENTSTORE_TELEMETRY_OPTOUT", "true"); + configuration.EnsureValue("EVENTSTORE_ALLOW_UNKNOWN_OPTIONS", "true"); configuration.EnsureValue("EVENTSTORE_MEM_DB", "false"); configuration.EnsureValue("EVENTSTORE_RUN_PROJECTIONS", "None"); configuration.EnsureValue("EVENTSTORE_START_STANDARD_PROJECTIONS", "false"); @@ -33,7 +35,6 @@ static void EnsureDefaults(IConfiguration configuration) { configuration.EnsureValue("EVENTSTORE_DISABLE_LOG_FILE", "true"); configuration.EnsureValue("EVENTSTORE_TRUSTED_ROOT_CERTIFICATES_PATH", "/etc/eventstore/certs/ca"); configuration.EnsureValue("EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP", "true"); - } } @@ -42,35 +43,4 @@ static void EnsureDefaults(IConfiguration configuration) { public static bool UseCluster { get; } public static bool UseExternalServer { get; } public static string DockerImage { get; } - - #region . Obsolete . - - //[Obsolete("Use the EventStoreFixture instead so you don't have to use this method.", false)] - public static IDictionary GetEnvironmentVariables(IDictionary? overrides = null) { - var env = new Dictionary { - ["ES_DOCKER_TAG"] = "ci", - ["EVENTSTORE_DB_LOG_FORMAT"] = "V2", - }; - - foreach (var @override in overrides ?? Enumerable.Empty>()) { - if (@override.Key.StartsWith("EVENTSTORE") && !SharedEnv.Contains(@override.Key)) - throw new Exception($"Add {@override.Key} to shared.env and _sharedEnv to pass it to the cluster containers"); - - env[@override.Key] = @override.Value; - } - - return env; - } - - // matches with the pass-through vars in shared.env... better way? - static readonly HashSet SharedEnv = new() { - "EVENTSTORE_DB_LOG_FORMAT", - "EVENTSTORE_LOG_LEVEL", - "EVENTSTORE_MAX_APPEND_SIZE", - "EVENTSTORE_MEM_DB", - "EVENTSTORE_RUN_PROJECTIONS", - "EVENTSTORE_START_STANDARD_PROJECTIONS", - }; - - #endregion } diff --git a/test/EventStore.Client.Tests.Common/InterlockedBoolean.cs b/test/Kurrent.Client.Tests.Common/InterlockedBoolean.cs similarity index 100% rename from test/EventStore.Client.Tests.Common/InterlockedBoolean.cs rename to test/Kurrent.Client.Tests.Common/InterlockedBoolean.cs diff --git a/test/Kurrent.Client.Tests.Common/Kurrent.Client.Tests.Common.csproj b/test/Kurrent.Client.Tests.Common/Kurrent.Client.Tests.Common.csproj new file mode 100644 index 000000000..95d43818b --- /dev/null +++ b/test/Kurrent.Client.Tests.Common/Kurrent.Client.Tests.Common.csproj @@ -0,0 +1,83 @@ + + + Kurrent.Client.Tests + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + certs\%(RecursiveDir)/%(FileName)%(Extension) + Always + + + + + + Always + + + Always + + + Always + + + PreserveNewest + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + + + + + diff --git a/test/EventStore.Client.Tests.Common/Logging.cs b/test/Kurrent.Client.Tests.Common/Logging.cs similarity index 98% rename from test/EventStore.Client.Tests.Common/Logging.cs rename to test/Kurrent.Client.Tests.Common/Logging.cs index a9df9709a..ee991d064 100644 --- a/test/EventStore.Client.Tests.Common/Logging.cs +++ b/test/Kurrent.Client.Tests.Common/Logging.cs @@ -6,7 +6,7 @@ using Serilog.Formatting.Display; using Xunit.Sdk; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; static class Logging { static readonly Subject LogEventSubject = new(); @@ -78,4 +78,4 @@ public static void ReleaseLogs(Guid captureId) { // ignored } } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/PasswordGenerator.cs b/test/Kurrent.Client.Tests.Common/PasswordGenerator.cs similarity index 98% rename from test/EventStore.Client.Tests.Common/PasswordGenerator.cs rename to test/Kurrent.Client.Tests.Common/PasswordGenerator.cs index 298600529..bbf019ce4 100644 --- a/test/EventStore.Client.Tests.Common/PasswordGenerator.cs +++ b/test/Kurrent.Client.Tests.Common/PasswordGenerator.cs @@ -1,6 +1,6 @@ using System.Text; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; static class PasswordGenerator { static PasswordGenerator() { @@ -63,4 +63,4 @@ public static string GenerateSimplePassword(int length = 8) { return new(password); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/Shouldly/ShouldThrowAsyncExtensions.cs b/test/Kurrent.Client.Tests.Common/Shouldly/ShouldThrowAsyncExtensions.cs similarity index 80% rename from test/EventStore.Client.Tests.Common/Shouldly/ShouldThrowAsyncExtensions.cs rename to test/Kurrent.Client.Tests.Common/Shouldly/ShouldThrowAsyncExtensions.cs index b75778b47..3411cd4b9 100644 --- a/test/EventStore.Client.Tests.Common/Shouldly/ShouldThrowAsyncExtensions.cs +++ b/test/Kurrent.Client.Tests.Common/Shouldly/ShouldThrowAsyncExtensions.cs @@ -7,6 +7,6 @@ namespace Shouldly; [DebuggerStepThrough] public static class ShouldThrowAsyncExtensions { - public static Task ShouldThrowAsync(this EventStoreClient.ReadStreamResult source) where TException : Exception => + public static Task ShouldThrowAsync(this KurrentClient.ReadStreamResult source) where TException : Exception => source.ToArrayAsync().AsTask().ShouldThrowAsync(); -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/TestCaseGenerator.cs b/test/Kurrent.Client.Tests.Common/TestCaseGenerator.cs similarity index 95% rename from test/EventStore.Client.Tests.Common/TestCaseGenerator.cs rename to test/Kurrent.Client.Tests.Common/TestCaseGenerator.cs index 781d19063..b56c95794 100644 --- a/test/EventStore.Client.Tests.Common/TestCaseGenerator.cs +++ b/test/Kurrent.Client.Tests.Common/TestCaseGenerator.cs @@ -1,4 +1,4 @@ -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; using System.Collections; using Bogus; diff --git a/test/EventStore.Client.Tests.Common/TestCredentials.cs b/test/Kurrent.Client.Tests.Common/TestCredentials.cs similarity index 87% rename from test/EventStore.Client.Tests.Common/TestCredentials.cs rename to test/Kurrent.Client.Tests.Common/TestCredentials.cs index a489cd13d..9f68ea68b 100644 --- a/test/EventStore.Client.Tests.Common/TestCredentials.cs +++ b/test/Kurrent.Client.Tests.Common/TestCredentials.cs @@ -1,4 +1,6 @@ -namespace EventStore.Client.Tests; +using EventStore.Client; + +namespace Kurrent.Client.Tests; public static class TestCredentials { public static readonly UserCredentials Root = new("admin", "changeit"); @@ -6,4 +8,4 @@ public static class TestCredentials { public static readonly UserCredentials TestUser2 = new("user2", "pa$$2"); public static readonly UserCredentials TestAdmin = new("adm", "admpa$$"); public static readonly UserCredentials TestBadUser = new("badlogin", "badpass"); -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests.Common/appsettings.Development.json b/test/Kurrent.Client.Tests.Common/appsettings.Development.json similarity index 100% rename from test/EventStore.Client.Tests.Common/appsettings.Development.json rename to test/Kurrent.Client.Tests.Common/appsettings.Development.json diff --git a/test/EventStore.Client.Tests.Common/appsettings.json b/test/Kurrent.Client.Tests.Common/appsettings.json similarity index 100% rename from test/EventStore.Client.Tests.Common/appsettings.json rename to test/Kurrent.Client.Tests.Common/appsettings.json diff --git a/test/EventStore.Client.Tests.Common/docker-compose.certs.yml b/test/Kurrent.Client.Tests.Common/docker-compose.certs.yml similarity index 100% rename from test/EventStore.Client.Tests.Common/docker-compose.certs.yml rename to test/Kurrent.Client.Tests.Common/docker-compose.certs.yml diff --git a/test/EventStore.Client.Tests.Common/docker-compose.cluster.yml b/test/Kurrent.Client.Tests.Common/docker-compose.cluster.yml similarity index 100% rename from test/EventStore.Client.Tests.Common/docker-compose.cluster.yml rename to test/Kurrent.Client.Tests.Common/docker-compose.cluster.yml diff --git a/test/EventStore.Client.Tests.Common/docker-compose.node.yml b/test/Kurrent.Client.Tests.Common/docker-compose.node.yml similarity index 100% rename from test/EventStore.Client.Tests.Common/docker-compose.node.yml rename to test/Kurrent.Client.Tests.Common/docker-compose.node.yml diff --git a/test/EventStore.Client.Tests.Common/docker-compose.yml b/test/Kurrent.Client.Tests.Common/docker-compose.yml similarity index 100% rename from test/EventStore.Client.Tests.Common/docker-compose.yml rename to test/Kurrent.Client.Tests.Common/docker-compose.yml diff --git a/test/EventStore.Client.Tests.Common/shared.env b/test/Kurrent.Client.Tests.Common/shared.env similarity index 100% rename from test/EventStore.Client.Tests.Common/shared.env rename to test/Kurrent.Client.Tests.Common/shared.env diff --git a/test/EventStore.Client.Tests/Assertions/ComparableAssertion.cs b/test/Kurrent.Client.Tests/Assertions/ComparableAssertion.cs similarity index 99% rename from test/EventStore.Client.Tests/Assertions/ComparableAssertion.cs rename to test/Kurrent.Client.Tests/Assertions/ComparableAssertion.cs index 0d626cf61..cecfe6599 100644 --- a/test/EventStore.Client.Tests/Assertions/ComparableAssertion.cs +++ b/test/Kurrent.Client.Tests/Assertions/ComparableAssertion.cs @@ -3,7 +3,7 @@ using AutoFixture.Kernel; // ReSharper disable once CheckNamespace -namespace EventStore.Client; +namespace Kurrent.Client; class ComparableAssertion : CompositeIdiomaticAssertion { public ComparableAssertion(ISpecimenBuilder builder) : base(CreateChildrenAssertions(builder)) { } @@ -142,4 +142,4 @@ public override void Verify(Type type) { } } } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/Assertions/EqualityAssertion.cs b/test/Kurrent.Client.Tests/Assertions/EqualityAssertion.cs similarity index 98% rename from test/EventStore.Client.Tests/Assertions/EqualityAssertion.cs rename to test/Kurrent.Client.Tests/Assertions/EqualityAssertion.cs index 055cef40b..6c172af7f 100644 --- a/test/EventStore.Client.Tests/Assertions/EqualityAssertion.cs +++ b/test/Kurrent.Client.Tests/Assertions/EqualityAssertion.cs @@ -2,7 +2,7 @@ using AutoFixture.Kernel; // ReSharper disable once CheckNamespace -namespace EventStore.Client; +namespace Kurrent.Client; class EqualityAssertion : CompositeIdiomaticAssertion { public EqualityAssertion(ISpecimenBuilder builder) : base(CreateChildrenAssertions(builder)) { } @@ -67,4 +67,4 @@ public override void Verify(Type type) { throw new($"The type '{type}' did not implement the inequality (!=) operator correctly."); } } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/Assertions/NullArgumentAssertion.cs b/test/Kurrent.Client.Tests/Assertions/NullArgumentAssertion.cs similarity index 97% rename from test/EventStore.Client.Tests/Assertions/NullArgumentAssertion.cs rename to test/Kurrent.Client.Tests/Assertions/NullArgumentAssertion.cs index 770591afc..4efb616d5 100644 --- a/test/EventStore.Client.Tests/Assertions/NullArgumentAssertion.cs +++ b/test/Kurrent.Client.Tests/Assertions/NullArgumentAssertion.cs @@ -3,7 +3,7 @@ using AutoFixture.Kernel; // ReSharper disable once CheckNamespace -namespace EventStore.Client; +namespace Kurrent.Client; class NullArgumentAssertion : IdiomaticAssertion { readonly ISpecimenBuilder _builder; @@ -50,4 +50,4 @@ public override void Verify(Type type) { } ); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/Assertions/StringConversionAssertion.cs b/test/Kurrent.Client.Tests/Assertions/StringConversionAssertion.cs similarity index 97% rename from test/EventStore.Client.Tests/Assertions/StringConversionAssertion.cs rename to test/Kurrent.Client.Tests/Assertions/StringConversionAssertion.cs index 8b97e33f8..fa4da4970 100644 --- a/test/EventStore.Client.Tests/Assertions/StringConversionAssertion.cs +++ b/test/Kurrent.Client.Tests/Assertions/StringConversionAssertion.cs @@ -3,7 +3,7 @@ using AutoFixture.Kernel; // ReSharper disable once CheckNamespace -namespace EventStore.Client; +namespace Kurrent.Client; class StringConversionAssertion : IdiomaticAssertion { readonly ISpecimenBuilder _builder; @@ -43,4 +43,4 @@ public override void Verify(Type type) { if (toString is not null) Assert.Equal(value, toString.Invoke(instance, null)); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/Assertions/ValueObjectAssertion.cs b/test/Kurrent.Client.Tests/Assertions/ValueObjectAssertion.cs similarity index 94% rename from test/EventStore.Client.Tests/Assertions/ValueObjectAssertion.cs rename to test/Kurrent.Client.Tests/Assertions/ValueObjectAssertion.cs index dbdbb5ca2..ee3fce80d 100644 --- a/test/EventStore.Client.Tests/Assertions/ValueObjectAssertion.cs +++ b/test/Kurrent.Client.Tests/Assertions/ValueObjectAssertion.cs @@ -2,7 +2,7 @@ using AutoFixture.Kernel; // ReSharper disable once CheckNamespace -namespace EventStore.Client; +namespace Kurrent.Client; class ValueObjectAssertion : CompositeIdiomaticAssertion { public ValueObjectAssertion(ISpecimenBuilder builder) : base(CreateChildrenAssertions(builder)) { } @@ -13,4 +13,4 @@ static IEnumerable CreateChildrenAssertions(ISpecimenBuilde yield return new StringConversionAssertion(builder); yield return new NullArgumentAssertion(builder); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/AutoScenarioDataAttribute.cs b/test/Kurrent.Client.Tests/AutoScenarioDataAttribute.cs similarity index 95% rename from test/EventStore.Client.Tests/AutoScenarioDataAttribute.cs rename to test/Kurrent.Client.Tests/AutoScenarioDataAttribute.cs index d5840a41b..166e5b7ef 100644 --- a/test/EventStore.Client.Tests/AutoScenarioDataAttribute.cs +++ b/test/Kurrent.Client.Tests/AutoScenarioDataAttribute.cs @@ -3,7 +3,7 @@ using AutoFixture.Xunit2; using Xunit.Sdk; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; [DataDiscoverer("AutoFixture.Xunit2.NoPreDiscoveryDataDiscoverer", "AutoFixture.Xunit2")] public class AutoScenarioDataAttribute : DataAttribute { @@ -25,4 +25,4 @@ public override IEnumerable GetData(MethodInfo testMethod) { class CustomAutoData : AutoDataAttribute { public CustomAutoData(Type fixtureType) : base(() => (IFixture)Activator.CreateInstance(fixtureType)!) { } } -} \ No newline at end of file +} diff --git a/test/Kurrent.Client.Tests/ClientCertificatesTests.cs b/test/Kurrent.Client.Tests/ClientCertificatesTests.cs new file mode 100644 index 000000000..92d08fa51 --- /dev/null +++ b/test/Kurrent.Client.Tests/ClientCertificatesTests.cs @@ -0,0 +1,93 @@ +using EventStore.Client; +using Humanizer; +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Misc")] +[Trait("Category", "Target:Plugins")] +[Trait("Category", "Type:UserCertificate")] +public class ClientCertificateTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [SupportsPlugins.Theory(EventStoreRepository.Commercial, "This server version does not support plugins"), BadClientCertificatesTestCases] + async Task bad_certificates_combinations_should_return_authentication_error(string userCertFile, string userKeyFile, string tlsCaFile) { + var stream = Fixture.GetStreamName(); + var seedEvents = Fixture.CreateTestEvents(); + var port = Fixture.Options.ClientSettings.ConnectivitySettings.ResolvedAddressOrDefault.Port; + + var connectionString = $"esdb://localhost:{port}/?tls=true&userCertFile={userCertFile}&userKeyFile={userKeyFile}&tlsCaFile={tlsCaFile}"; + + var settings = KurrentClientSettings.Create(connectionString); + settings.ConnectivitySettings.TlsVerifyCert.ShouldBeTrue(); + + await using var client = new KurrentClient(settings); + + await client.AppendToStreamAsync(stream, StreamState.NoStream, seedEvents).ShouldThrowAsync(); + } + + [SupportsPlugins.Theory(EventStoreRepository.Commercial, "This server version does not support plugins"), ValidClientCertificatesTestCases] + async Task valid_certificates_combinations_should_write_to_stream(string userCertFile, string userKeyFile, string tlsCaFile) { + var stream = Fixture.GetStreamName(); + var seedEvents = Fixture.CreateTestEvents(); + var port = Fixture.Options.ClientSettings.ConnectivitySettings.ResolvedAddressOrDefault.Port; + + var connectionString = $"esdb://localhost:{port}/?userCertFile={userCertFile}&userKeyFile={userKeyFile}&tlsCaFile={tlsCaFile}"; + + var settings = KurrentClientSettings.Create(connectionString); + settings.ConnectivitySettings.TlsVerifyCert.ShouldBeTrue(); + + await using var client = new KurrentClient(settings); + + var result = await client.AppendToStreamAsync(stream, StreamState.NoStream, seedEvents); + result.ShouldNotBeNull(); + } + + [SupportsPlugins.Theory(EventStoreRepository.Commercial, "This server version does not support plugins"), BadClientCertificatesTestCases] + async Task basic_authentication_should_take_precedence(string userCertFile, string userKeyFile, string tlsCaFile) { + var stream = Fixture.GetStreamName(); + var seedEvents = Fixture.CreateTestEvents(); + var port = Fixture.Options.ClientSettings.ConnectivitySettings.ResolvedAddressOrDefault.Port; + + var connectionString = $"esdb://admin:changeit@localhost:{port}/?userCertFile={userCertFile}&userKeyFile={userKeyFile}&tlsCaFile={tlsCaFile}"; + + var settings = KurrentClientSettings.Create(connectionString); + settings.ConnectivitySettings.TlsVerifyCert.ShouldBeTrue(); + + await using var client = new KurrentClient(settings); + + var result = await client.AppendToStreamAsync(stream, StreamState.NoStream, seedEvents); + result.ShouldNotBeNull(); + } + + class BadClientCertificatesTestCases : TestCaseGenerator { + protected override IEnumerable Data() { + yield return [Certificates.Invalid.CertAbsolute, Certificates.Invalid.KeyAbsolute, Certificates.TlsCa.Absolute]; + yield return [Certificates.Invalid.CertRelative, Certificates.Invalid.KeyRelative, Certificates.TlsCa.Absolute]; + yield return [Certificates.Invalid.CertAbsolute, Certificates.Invalid.KeyAbsolute, Certificates.TlsCa.Relative]; + yield return [Certificates.Invalid.CertRelative, Certificates.Invalid.KeyRelative, Certificates.TlsCa.Relative]; + } + } + + class ValidClientCertificatesTestCases : TestCaseGenerator { + protected override IEnumerable Data() { + yield return [Certificates.Admin.CertAbsolute, Certificates.Admin.KeyAbsolute, Certificates.TlsCa.Absolute]; + yield return [Certificates.Admin.CertRelative, Certificates.Admin.KeyRelative, Certificates.TlsCa.Absolute]; + yield return [Certificates.Admin.CertAbsolute, Certificates.Admin.KeyAbsolute, Certificates.TlsCa.Relative]; + yield return [Certificates.Admin.CertRelative, Certificates.Admin.KeyRelative, Certificates.TlsCa.Relative]; + } + } +} + +public enum EventStoreRepository { + Commercial = 1 +} + +[PublicAPI] +public class SupportsPlugins { + public class TheoryAttribute(EventStoreRepository repository, string skipMessage) : Xunit.TheoryAttribute { + public override string? Skip { + get => !GlobalEnvironment.DockerImage.Contains(repository.Humanize().ToLower()) ? skipMessage : null; + set => throw new NotSupportedException(); + } + } +} diff --git a/test/EventStore.Client.Tests/ConnectionStringTests.cs b/test/Kurrent.Client.Tests/ConnectionStringTests.cs similarity index 75% rename from test/EventStore.Client.Tests/ConnectionStringTests.cs rename to test/Kurrent.Client.Tests/ConnectionStringTests.cs index e258c682d..7ef507b6c 100644 --- a/test/EventStore.Client.Tests/ConnectionStringTests.cs +++ b/test/Kurrent.Client.Tests/ConnectionStringTests.cs @@ -1,11 +1,14 @@ using System.Net; using System.Net.Http; -using AutoFixture; using System.Reflection; using System.Security.Cryptography.X509Certificates; +using AutoFixture; +using EventStore.Client; +using HashCode = EventStore.Client.HashCode; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; +[Trait("Category", "Target:Misc")] public class ConnectionStringTests { public static IEnumerable ValidCases() { var fixture = new Fixture(); @@ -24,14 +27,14 @@ public class ConnectionStringTests { return Enumerable.Range(0, 3).SelectMany(GetTestCases); IEnumerable GetTestCases(int _) { - var settings = new EventStoreClientSettings { + var settings = new KurrentClientSettings { ConnectionName = fixture.Create(), - ConnectivitySettings = fixture.Create(), - OperationOptions = fixture.Create() + ConnectivitySettings = fixture.Create(), + OperationOptions = fixture.Create() }; settings.ConnectivitySettings.Address = - new UriBuilder(EventStoreClientConnectivitySettings.Default.ResolvedAddressOrDefault) { + new UriBuilder(KurrentClientConnectivitySettings.Default.ResolvedAddressOrDefault) { Scheme = settings.ConnectivitySettings.ResolvedAddressOrDefault.Scheme }.Uri; @@ -45,14 +48,14 @@ public class ConnectionStringTests { settings }; - var ipGossipSettings = new EventStoreClientSettings { + var ipGossipSettings = new KurrentClientSettings { ConnectionName = fixture.Create(), - ConnectivitySettings = fixture.Create(), - OperationOptions = fixture.Create() + ConnectivitySettings = fixture.Create(), + OperationOptions = fixture.Create() }; ipGossipSettings.ConnectivitySettings.Address = - new UriBuilder(EventStoreClientConnectivitySettings.Default.ResolvedAddressOrDefault) { + new UriBuilder(KurrentClientConnectivitySettings.Default.ResolvedAddressOrDefault) { Scheme = ipGossipSettings.ConnectivitySettings.ResolvedAddressOrDefault.Scheme }.Uri; @@ -68,10 +71,10 @@ public class ConnectionStringTests { ipGossipSettings }; - var singleNodeSettings = new EventStoreClientSettings { + var singleNodeSettings = new KurrentClientSettings { ConnectionName = fixture.Create(), - ConnectivitySettings = fixture.Create(), - OperationOptions = fixture.Create() + ConnectivitySettings = fixture.Create(), + OperationOptions = fixture.Create() }; singleNodeSettings.ConnectivitySettings.DnsGossipSeeds = null; @@ -96,18 +99,18 @@ public class ConnectionStringTests { [Theory] [MemberData(nameof(ValidCases))] - public void valid_connection_string(string connectionString, EventStoreClientSettings expected) { - var result = EventStoreClientSettings.Create(connectionString); + public void valid_connection_string(string connectionString, KurrentClientSettings expected) { + var result = KurrentClientSettings.Create(connectionString); - Assert.Equal(expected, result, EventStoreClientSettingsEqualityComparer.Instance); + Assert.Equal(expected, result, KurrentClientSettingsEqualityComparer.Instance); } [Theory] [MemberData(nameof(ValidCases))] - public void valid_connection_string_with_empty_path(string connectionString, EventStoreClientSettings expected) { - var result = EventStoreClientSettings.Create(connectionString.Replace("?", "/?")); + public void valid_connection_string_with_empty_path(string connectionString, KurrentClientSettings expected) { + var result = KurrentClientSettings.Create(connectionString.Replace("?", "/?")); - Assert.Equal(expected, result, EventStoreClientSettingsEqualityComparer.Instance); + Assert.Equal(expected, result, KurrentClientSettingsEqualityComparer.Instance); } #if !GRPC_CORE @@ -116,7 +119,7 @@ public void valid_connection_string_with_empty_path(string connectionString, Eve [InlineData(true)] public void tls_verify_cert(bool tlsVerifyCert) { var connectionString = $"esdb://localhost:2113/?tlsVerifyCert={tlsVerifyCert}"; - var result = EventStoreClientSettings.Create(connectionString); + var result = KurrentClientSettings.Create(connectionString); using var handler = result.CreateHttpMessageHandler?.Invoke(); #if NET var socketsHandler = Assert.IsType(handler); @@ -130,8 +133,7 @@ public void tls_verify_cert(bool tlsVerifyCert) { default ) ); - } - else { + } else { Assert.Null(socketsHandler.SslOptions.RemoteCertificateValidationCallback); } #else @@ -156,16 +158,14 @@ public void tls_verify_cert(bool tlsVerifyCert) { [Theory] [MemberData(nameof(InvalidTlsCertificates))] public void connection_string_with_invalid_tls_certificate_should_throw(string clientCertificatePath) { - Assert.Throws( - () => EventStoreClientSettings.Create( - $"esdb://admin:changeit@localhost:2113/?tls=true&tlsVerifyCert=true&tlsCAFile={clientCertificatePath}" - ) + Assert.Throws( + () => KurrentClientSettings.Create($"esdb://admin:changeit@localhost:2113/?tls=true&tlsVerifyCert=true&tlsCAFile={clientCertificatePath}") ); } public static IEnumerable InvalidClientCertificates() { var invalidPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "path", "not", "found"); - var validPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "certs", "ca", "ca.crt"); + var validPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "certs", "ca", "ca.crt"); yield return [invalidPath, invalidPath]; yield return [validPath, invalidPath]; } @@ -174,15 +174,15 @@ public void connection_string_with_invalid_tls_certificate_should_throw(string c [MemberData(nameof(InvalidClientCertificates))] public void connection_string_with_invalid_client_certificate_should_throw(string userCertFile, string userKeyFile) { Assert.Throws( - () => EventStoreClientSettings.Create( + () => KurrentClientSettings.Create( $"esdb://admin:changeit@localhost:2113/?tls=true&tlsVerifyCert=true&userCertFile={userCertFile}&userKeyFile={userKeyFile}" ) ); } - [Fact] + [RetryFact] public void infinite_grpc_timeouts() { - var result = EventStoreClientSettings.Create("esdb://localhost:2113?keepAliveInterval=-1&keepAliveTimeout=-1"); + var result = KurrentClientSettings.Create("esdb://localhost:2113?keepAliveInterval=-1&keepAliveTimeout=-1"); Assert.Equal(System.Threading.Timeout.InfiniteTimeSpan, result.ConnectivitySettings.KeepAliveInterval); Assert.Equal(System.Threading.Timeout.InfiniteTimeSpan, result.ConnectivitySettings.KeepAliveTimeout); @@ -200,22 +200,22 @@ public void infinite_grpc_timeouts() { #endif } - [Fact] - public void connection_string_with_no_schema() => Assert.Throws(() => EventStoreClientSettings.Create(":so/mething/random")); + [RetryFact] + public void connection_string_with_no_schema() => Assert.Throws(() => KurrentClientSettings.Create(":so/mething/random")); [Theory] [InlineData("esdbwrong://")] [InlineData("wrong://")] [InlineData("badesdb://")] public void connection_string_with_invalid_scheme_should_throw(string connectionString) => - Assert.Throws(() => EventStoreClientSettings.Create(connectionString)); + Assert.Throws(() => KurrentClientSettings.Create(connectionString)); [Theory] [InlineData("esdb://userpass@127.0.0.1/")] [InlineData("esdb://user:pa:ss@127.0.0.1/")] [InlineData("esdb://us:er:pa:ss@127.0.0.1/")] public void connection_string_with_invalid_userinfo_should_throw(string connectionString) => - Assert.Throws(() => EventStoreClientSettings.Create(connectionString)); + Assert.Throws(() => KurrentClientSettings.Create(connectionString)); [Theory] [InlineData("esdb://user:pass@127.0.0.1:abc")] @@ -229,14 +229,14 @@ public void connection_string_with_invalid_userinfo_should_throw(string connecti [InlineData("esdb://user:pass@localhost:1234,,127.0.0.3:4321")] [InlineData("esdb://user:pass@localhost:1234,,127.0.0.3:4321/")] public void connection_string_with_invalid_host_should_throw(string connectionString) => - Assert.Throws(() => EventStoreClientSettings.Create(connectionString)); + Assert.Throws(() => KurrentClientSettings.Create(connectionString)); [Theory] [InlineData("esdb://user:pass@127.0.0.1/test")] [InlineData("esdb://user:pass@127.0.0.1/maxDiscoverAttempts=10")] [InlineData("esdb://user:pass@127.0.0.1/hello?maxDiscoverAttempts=10")] public void connection_string_with_non_empty_path_should_throw(string connectionString) => - Assert.Throws(() => EventStoreClientSettings.Create(connectionString)); + Assert.Throws(() => KurrentClientSettings.Create(connectionString)); [Theory] [InlineData("esdb://user:pass@127.0.0.1")] @@ -244,19 +244,19 @@ public void connection_string_with_non_empty_path_should_throw(string connection [InlineData("esdb+discover://user:pass@127.0.0.1")] [InlineData("esdb+discover://user:pass@127.0.0.1/")] public void connection_string_with_no_key_value_pairs_specified_should_not_throw(string connectionString) => - EventStoreClientSettings.Create(connectionString); + KurrentClientSettings.Create(connectionString); [Theory] [InlineData("esdb://user:pass@127.0.0.1/?maxDiscoverAttempts=12=34")] [InlineData("esdb://user:pass@127.0.0.1/?maxDiscoverAttempts1234")] public void connection_string_with_invalid_key_value_pair_should_throw(string connectionString) => - Assert.Throws(() => EventStoreClientSettings.Create(connectionString)); + Assert.Throws(() => KurrentClientSettings.Create(connectionString)); [Theory] [InlineData("esdb://user:pass@127.0.0.1/?maxDiscoverAttempts=1234&MaxDiscoverAttempts=10")] [InlineData("esdb://user:pass@127.0.0.1/?gossipTimeout=10&gossipTimeout=30")] public void connection_string_with_duplicate_key_should_throw(string connectionString) => - Assert.Throws(() => EventStoreClientSettings.Create(connectionString)); + Assert.Throws(() => KurrentClientSettings.Create(connectionString)); [Theory] [InlineData("esdb://user:pass@127.0.0.1/?unknown=1234")] @@ -269,59 +269,59 @@ public void connection_string_with_duplicate_key_should_throw(string connectionS [InlineData("esdb://user:pass@127.0.0.1/?keepAliveInterval=-2")] [InlineData("esdb://user:pass@127.0.0.1/?keepAliveTimeout=-2")] public void connection_string_with_invalid_settings_should_throw(string connectionString) => - Assert.Throws(() => EventStoreClientSettings.Create(connectionString)); + Assert.Throws(() => KurrentClientSettings.Create(connectionString)); - [Fact] + [RetryFact] public void with_default_settings() { - var settings = EventStoreClientSettings.Create("esdb://hostname:4321/"); + var settings = KurrentClientSettings.Create("esdb://hostname:4321/"); Assert.Null(settings.ConnectionName); Assert.Equal( - EventStoreClientConnectivitySettings.Default.ResolvedAddressOrDefault.Scheme, + KurrentClientConnectivitySettings.Default.ResolvedAddressOrDefault.Scheme, settings.ConnectivitySettings.ResolvedAddressOrDefault.Scheme ); Assert.Equal( - EventStoreClientConnectivitySettings.Default.DiscoveryInterval.TotalMilliseconds, + KurrentClientConnectivitySettings.Default.DiscoveryInterval.TotalMilliseconds, settings.ConnectivitySettings.DiscoveryInterval.TotalMilliseconds ); - Assert.Null(EventStoreClientConnectivitySettings.Default.DnsGossipSeeds); - Assert.Empty(EventStoreClientConnectivitySettings.Default.GossipSeeds); + Assert.Null(KurrentClientConnectivitySettings.Default.DnsGossipSeeds); + Assert.Empty(KurrentClientConnectivitySettings.Default.GossipSeeds); Assert.Equal( - EventStoreClientConnectivitySettings.Default.GossipTimeout.TotalMilliseconds, + KurrentClientConnectivitySettings.Default.GossipTimeout.TotalMilliseconds, settings.ConnectivitySettings.GossipTimeout.TotalMilliseconds ); - Assert.Null(EventStoreClientConnectivitySettings.Default.IpGossipSeeds); + Assert.Null(KurrentClientConnectivitySettings.Default.IpGossipSeeds); Assert.Equal( - EventStoreClientConnectivitySettings.Default.MaxDiscoverAttempts, + KurrentClientConnectivitySettings.Default.MaxDiscoverAttempts, settings.ConnectivitySettings.MaxDiscoverAttempts ); Assert.Equal( - EventStoreClientConnectivitySettings.Default.NodePreference, + KurrentClientConnectivitySettings.Default.NodePreference, settings.ConnectivitySettings.NodePreference ); Assert.Equal( - EventStoreClientConnectivitySettings.Default.Insecure, + KurrentClientConnectivitySettings.Default.Insecure, settings.ConnectivitySettings.Insecure ); Assert.Equal(TimeSpan.FromSeconds(10), settings.DefaultDeadline); Assert.Equal( - EventStoreClientOperationOptions.Default.ThrowOnAppendFailure, + KurrentClientOperationOptions.Default.ThrowOnAppendFailure, settings.OperationOptions.ThrowOnAppendFailure ); Assert.Equal( - EventStoreClientConnectivitySettings.Default.KeepAliveInterval, + KurrentClientConnectivitySettings.Default.KeepAliveInterval, settings.ConnectivitySettings.KeepAliveInterval ); Assert.Equal( - EventStoreClientConnectivitySettings.Default.KeepAliveTimeout, + KurrentClientConnectivitySettings.Default.KeepAliveTimeout, settings.ConnectivitySettings.KeepAliveTimeout ); } @@ -334,7 +334,7 @@ public void with_default_settings() { [InlineData("esdb://localhost1,localhost2,localhost3/?tls=false", false)] [InlineData("esdb://localhost1,localhost2,localhost3/?tls=true", true)] public void use_tls(string connectionString, bool expectedUseTls) { - var result = EventStoreClientSettings.Create(connectionString); + var result = KurrentClientSettings.Create(connectionString); var expectedScheme = expectedUseTls ? "https" : "http"; Assert.NotEqual(expectedUseTls, result.ConnectivitySettings.Insecure); Assert.Equal(expectedScheme, result.ConnectivitySettings.ResolvedAddressOrDefault.Scheme); @@ -360,7 +360,7 @@ public void use_tls(string connectionString, bool expectedUseTls) { [InlineData("esdb://localhost1,localhost2,localhost3/?tls=false", true, false)] [InlineData("esdb://localhost1,localhost2,localhost3/?tls=false", false, false)] public void allow_tls_override_for_single_node(string connectionString, bool? insecureOverride, bool expectedUseTls) { - var result = EventStoreClientSettings.Create(connectionString); + var result = KurrentClientSettings.Create(connectionString); var settings = result.ConnectivitySettings; if (insecureOverride.HasValue) @@ -379,7 +379,7 @@ public void allow_tls_override_for_single_node(string connectionString, bool? in [InlineData("esdb+discover://localhost:1234", null, null)] [InlineData("esdb+discover://localhost:1234,localhost:4567", null, null)] public void connection_string_with_custom_ports(string connectionString, string? expectedHost, int? expectedPort) { - var result = EventStoreClientSettings.Create(connectionString); + var result = KurrentClientSettings.Create(connectionString); var connectivitySettings = result.ConnectivitySettings; Assert.Equal(expectedHost, connectivitySettings.Address?.Host); @@ -387,17 +387,17 @@ public void connection_string_with_custom_ports(string connectionString, string? } static string GetConnectionString( - EventStoreClientSettings settings, + KurrentClientSettings settings, Func? getKey = default ) => $"{GetScheme(settings)}{GetAuthority(settings)}?{GetKeyValuePairs(settings, getKey)}"; - static string GetScheme(EventStoreClientSettings settings) => + static string GetScheme(KurrentClientSettings settings) => settings.ConnectivitySettings.IsSingleNode ? "esdb://" : "esdb+discover://"; - static string GetAuthority(EventStoreClientSettings settings) => + static string GetAuthority(KurrentClientSettings settings) => settings.ConnectivitySettings.IsSingleNode ? $"{settings.ConnectivitySettings.ResolvedAddressOrDefault.Host}:{settings.ConnectivitySettings.ResolvedAddressOrDefault.Port}" : string.Join( @@ -406,7 +406,7 @@ static string GetAuthority(EventStoreClientSettings settings) => ); static string GetKeyValuePairs( - EventStoreClientSettings settings, + KurrentClientSettings settings, Func? getKey = default ) { var pairs = new Dictionary { @@ -444,10 +444,10 @@ static string GetKeyValuePairs( return string.Join("&", pairs.Select(pair => $"{getKey?.Invoke(pair.Key) ?? pair.Key}={pair.Value}")); } - class EventStoreClientSettingsEqualityComparer : IEqualityComparer { - public static readonly EventStoreClientSettingsEqualityComparer Instance = new(); + class KurrentClientSettingsEqualityComparer : IEqualityComparer { + public static readonly KurrentClientSettingsEqualityComparer Instance = new(); - public bool Equals(EventStoreClientSettings? x, EventStoreClientSettings? y) { + public bool Equals(KurrentClientSettings? x, KurrentClientSettings? y) { if (ReferenceEquals(x, y)) return true; @@ -461,29 +461,29 @@ public bool Equals(EventStoreClientSettings? x, EventStoreClientSettings? y) { return false; return x.ConnectionName == y.ConnectionName && - EventStoreClientConnectivitySettingsEqualityComparer.Instance.Equals( + KurrentClientConnectivitySettingsEqualityComparer.Instance.Equals( x.ConnectivitySettings, y.ConnectivitySettings ) && - EventStoreClientOperationOptionsEqualityComparer.Instance.Equals( + KurrentClientOperationOptionsEqualityComparer.Instance.Equals( x.OperationOptions, y.OperationOptions ) && Equals(x.DefaultCredentials?.ToString(), y.DefaultCredentials?.ToString()); } - public int GetHashCode(EventStoreClientSettings obj) => + public int GetHashCode(KurrentClientSettings obj) => HashCode.Hash .Combine(obj.ConnectionName) - .Combine(EventStoreClientConnectivitySettingsEqualityComparer.Instance.GetHashCode(obj.ConnectivitySettings)) - .Combine(EventStoreClientOperationOptionsEqualityComparer.Instance.GetHashCode(obj.OperationOptions)); + .Combine(KurrentClientConnectivitySettingsEqualityComparer.Instance.GetHashCode(obj.ConnectivitySettings)) + .Combine(KurrentClientOperationOptionsEqualityComparer.Instance.GetHashCode(obj.OperationOptions)); } - class EventStoreClientConnectivitySettingsEqualityComparer - : IEqualityComparer { - public static readonly EventStoreClientConnectivitySettingsEqualityComparer Instance = new(); + class KurrentClientConnectivitySettingsEqualityComparer + : IEqualityComparer { + public static readonly KurrentClientConnectivitySettingsEqualityComparer Instance = new(); - public bool Equals(EventStoreClientConnectivitySettings? x, EventStoreClientConnectivitySettings? y) { + public bool Equals(KurrentClientConnectivitySettings? x, KurrentClientConnectivitySettings? y) { if (ReferenceEquals(x, y)) return true; @@ -507,7 +507,7 @@ public bool Equals(EventStoreClientConnectivitySettings? x, EventStoreClientConn x.Insecure == y.Insecure; } - public int GetHashCode(EventStoreClientConnectivitySettings obj) => + public int GetHashCode(KurrentClientConnectivitySettings obj) => obj.GossipSeeds.Aggregate( HashCode.Hash .Combine(obj.ResolvedAddressOrDefault.GetHashCode()) @@ -522,11 +522,11 @@ public int GetHashCode(EventStoreClientConnectivitySettings obj) => ); } - class EventStoreClientOperationOptionsEqualityComparer - : IEqualityComparer { - public static readonly EventStoreClientOperationOptionsEqualityComparer Instance = new(); + class KurrentClientOperationOptionsEqualityComparer + : IEqualityComparer { + public static readonly KurrentClientOperationOptionsEqualityComparer Instance = new(); - public bool Equals(EventStoreClientOperationOptions? x, EventStoreClientOperationOptions? y) { + public bool Equals(KurrentClientOperationOptions? x, KurrentClientOperationOptions? y) { if (ReferenceEquals(x, y)) return true; @@ -539,7 +539,7 @@ public bool Equals(EventStoreClientOperationOptions? x, EventStoreClientOperatio return x.GetType() == y.GetType(); } - public int GetHashCode(EventStoreClientOperationOptions obj) => + public int GetHashCode(KurrentClientOperationOptions obj) => System.HashCode.Combine(obj.ThrowOnAppendFailure); } } diff --git a/test/EventStore.Client.Tests/FromAllTests.cs b/test/Kurrent.Client.Tests/FromAllTests.cs similarity index 92% rename from test/EventStore.Client.Tests/FromAllTests.cs rename to test/Kurrent.Client.Tests/FromAllTests.cs index 82b8338ec..5be40e9bf 100644 --- a/test/EventStore.Client.Tests/FromAllTests.cs +++ b/test/Kurrent.Client.Tests/FromAllTests.cs @@ -1,11 +1,13 @@ using AutoFixture; +using EventStore.Client; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; +[Trait("Category", "Target:Misc")] public class FromAllTests : ValueObjectTests { public FromAllTests() : base(new ScenarioFixture()) { } - [Fact] + [RetryFact] public void IsComparable() => Assert.IsAssignableFrom>(_fixture.Create()); [Theory] @@ -28,10 +30,10 @@ public FromAllTests() : base(new ScenarioFixture()) { } [MemberData(nameof(ToStringCases))] public void ToStringReturnsExpectedResult(FromAll sut, string expected) => Assert.Equal(expected, sut.ToString()); - [Fact] + [RetryFact] public void AfterLiveThrows() => Assert.Throws(() => FromAll.After(Position.End)); - [Fact] + [RetryFact] public void ToUInt64ReturnsExpectedResults() { var position = _fixture.Create(); Assert.Equal( @@ -46,4 +48,4 @@ public ScenarioFixture() { Customize(composter => composter.FromFactory(FromAll.After)); } } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/FromStreamTests.cs b/test/Kurrent.Client.Tests/FromStreamTests.cs similarity index 83% rename from test/EventStore.Client.Tests/FromStreamTests.cs rename to test/Kurrent.Client.Tests/FromStreamTests.cs index a293aa44d..9593c8bea 100644 --- a/test/EventStore.Client.Tests/FromStreamTests.cs +++ b/test/Kurrent.Client.Tests/FromStreamTests.cs @@ -1,11 +1,13 @@ using AutoFixture; +using EventStore.Client; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; +[Trait("Category", "Target:Misc")] public class FromStreamTests : ValueObjectTests { public FromStreamTests() : base(new ScenarioFixture()) { } - [Fact] + [RetryFact] public void IsComparable() => Assert.IsAssignableFrom>(_fixture.Create()); [Theory] @@ -19,19 +21,19 @@ public FromStreamTests() : base(new ScenarioFixture()) { } public static IEnumerable ToStringCases() { var fixture = new ScenarioFixture(); var position = fixture.Create(); - yield return new object?[] { FromStream.After(position), position.ToString() }; - yield return new object?[] { FromStream.Start, "Start" }; - yield return new object?[] { FromStream.End, "Live" }; + yield return [FromStream.After(position), position.ToString()]; + yield return [FromStream.Start, "Start"]; + yield return [FromStream.End, "Live"]; } [Theory] [MemberData(nameof(ToStringCases))] public void ToStringReturnsExpectedResult(FromStream sut, string expected) => Assert.Equal(expected, sut.ToString()); - [Fact] + [RetryFact] public void AfterLiveThrows() => Assert.Throws(() => FromStream.After(StreamPosition.End)); - [Fact] + [RetryFact] public void ToUInt64ReturnsExpectedResults() { var position = _fixture.Create(); Assert.Equal(position.ToUInt64(), FromStream.After(position).ToUInt64()); @@ -43,4 +45,4 @@ public ScenarioFixture() { Customize(composter => composter.FromFactory(FromStream.After)); } } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/GossipChannelSelectorTests.cs b/test/Kurrent.Client.Tests/GossipChannelSelectorTests.cs similarity index 91% rename from test/EventStore.Client.Tests/GossipChannelSelectorTests.cs rename to test/Kurrent.Client.Tests/GossipChannelSelectorTests.cs index 5967f7384..1e5afe076 100644 --- a/test/EventStore.Client.Tests/GossipChannelSelectorTests.cs +++ b/test/Kurrent.Client.Tests/GossipChannelSelectorTests.cs @@ -1,10 +1,12 @@ using System.Net; +using EventStore.Client; using Grpc.Core; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; +[Trait("Category", "Target:Misc")] public class GossipChannelSelectorTests { - [Fact] + [RetryFact] public async Task ExplicitlySettingEndPointChangesChannels() { var firstId = Uuid.NewUuid(); var secondId = Uuid.NewUuid(); @@ -12,7 +14,7 @@ public async Task ExplicitlySettingEndPointChangesChannels() { var firstSelection = new DnsEndPoint(firstId.ToString(), 2113); var secondSelection = new DnsEndPoint(secondId.ToString(), 2113); - var settings = new EventStoreClientSettings { + var settings = new KurrentClientSettings { ConnectivitySettings = { DnsGossipSeeds = new[] { firstSelection, @@ -53,9 +55,9 @@ public async Task ExplicitlySettingEndPointChangesChannels() { Assert.Equal($"{secondSelection.Host}:{secondSelection.Port}", channel.Target); } - [Fact] + [RetryFact] public async Task ThrowsWhenDiscoveryFails() { - var settings = new EventStoreClientSettings { + var settings = new KurrentClientSettings { ConnectivitySettings = { IpGossipSeeds = new[] { new IPEndPoint(IPAddress.Loopback, 2113) @@ -93,4 +95,4 @@ CancellationToken cancellationToken ) => throw new NotSupportedException(); } -} \ No newline at end of file +} diff --git a/test/Kurrent.Client.Tests/GrpcServerCapabilitiesClientTests.cs b/test/Kurrent.Client.Tests/GrpcServerCapabilitiesClientTests.cs new file mode 100644 index 000000000..1bb44dc60 --- /dev/null +++ b/test/Kurrent.Client.Tests/GrpcServerCapabilitiesClientTests.cs @@ -0,0 +1,102 @@ +// #if NET +// using System.Net; +// using Kurrent.Client.ServerFeatures; +// using Grpc.Core; +// using Microsoft.AspNetCore.Builder; +// using Microsoft.AspNetCore.Hosting; +// using Microsoft.AspNetCore.TestHost; +// using Microsoft.Extensions.DependencyInjection; +// +// namespace Kurrent.Client.Tests; +// +// public class GrpcServerCapabilitiesClientTests { +// public static IEnumerable ExpectedResultsCases() { +// yield return new object?[] { new SupportedMethods(), new ServerCapabilities() }; +// yield return new object?[] { +// new SupportedMethods { +// Methods = { +// new SupportedMethod { +// ServiceName = "event_store.client.streams.streams", +// MethodName = "batchappend" +// } +// } +// }, +// new ServerCapabilities(true) +// }; +// +// yield return new object?[] { +// new SupportedMethods { +// Methods = { +// new SupportedMethod { +// ServiceName = "event_store.client.persistent_subscriptions.persistentsubscriptions", +// MethodName = "read", +// Features = { +// "all" +// } +// } +// } +// }, +// new ServerCapabilities(SupportsPersistentSubscriptionsToAll: true) +// }; +// +// yield return new object?[] { +// new SupportedMethods { +// Methods = { +// new SupportedMethod { +// ServiceName = "event_store.client.persistent_subscriptions.persistentsubscriptions", +// MethodName = "read" +// } +// } +// }, +// new ServerCapabilities() +// }; +// } +// +// [Theory] +// [MemberData(nameof(ExpectedResultsCases))] +// internal async Task GetAsyncReturnsExpectedResults( +// SupportedMethods supportedMethods, +// ServerCapabilities expected +// ) { +// using var kestrel = new TestServer( +// new WebHostBuilder() +// .ConfigureServices( +// services => services +// .AddRouting() +// .AddGrpc().Services +// .AddSingleton(new FakeServerFeatures(supportedMethods)) +// ) +// .Configure( +// app => app +// .UseRouting() +// .UseEndpoints(ep => ep.MapGrpcService()) +// ) +// ); +// +// var sut = new GrpcServerCapabilitiesClient(new()); +// +// var actual = +// await sut.GetAsync( +// ChannelFactory +// .CreateChannel( +// new() { +// CreateHttpMessageHandler = kestrel.CreateHandler +// }, +// new DnsEndPoint("localhost", 80) +// ) +// .CreateCallInvoker(), +// default +// ); +// +// Assert.Equal(expected, actual); +// } +// +// class FakeServerFeatures : ServerFeatures.ServerFeatures.ServerFeaturesBase { +// readonly SupportedMethods _supportedMethods; +// +// public FakeServerFeatures(SupportedMethods supportedMethods) => _supportedMethods = supportedMethods; +// +// public override Task GetSupportedMethods(Empty request, ServerCallContext context) => Task.FromResult(_supportedMethods); +// } +// } +// #endif diff --git a/test/EventStore.Client.UserManagement.Tests/InvalidCredentialsTestCases.cs b/test/Kurrent.Client.Tests/InvalidCredentialsTestCases.cs similarity index 57% rename from test/EventStore.Client.UserManagement.Tests/InvalidCredentialsTestCases.cs rename to test/Kurrent.Client.Tests/InvalidCredentialsTestCases.cs index e32a340bd..b60499693 100644 --- a/test/EventStore.Client.UserManagement.Tests/InvalidCredentialsTestCases.cs +++ b/test/Kurrent.Client.Tests/InvalidCredentialsTestCases.cs @@ -1,6 +1,7 @@ using System.Collections; +using EventStore.Client; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; public abstract record InvalidCredentialsTestCase(TestUser User, Type ExpectedException); @@ -13,18 +14,15 @@ public class InvalidCredentialsTestCases : IEnumerable { IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - public record MissingCredentials() - : InvalidCredentialsTestCase(Fakers.Users.WithNoCredentials(), typeof(AccessDeniedException)) { + public record MissingCredentials() : InvalidCredentialsTestCase(Fakers.Users.WithNoCredentials(), typeof(AccessDeniedException)) { public override string ToString() => nameof(MissingCredentials); } - public record WrongUsername() - : InvalidCredentialsTestCase(Fakers.Users.WithInvalidCredentials(false), typeof(NotAuthenticatedException)) { + public record WrongUsername() : InvalidCredentialsTestCase(Fakers.Users.WithInvalidCredentials(false), typeof(NotAuthenticatedException)) { public override string ToString() => nameof(WrongUsername); } - public record WrongPassword() - : InvalidCredentialsTestCase(Fakers.Users.WithInvalidCredentials(wrongPassword: false), typeof(NotAuthenticatedException)) { + public record WrongPassword() : InvalidCredentialsTestCase(Fakers.Users.WithInvalidCredentials(wrongPassword: false), typeof(NotAuthenticatedException)) { public override string ToString() => nameof(WrongPassword); } -} \ No newline at end of file +} diff --git a/test/Kurrent.Client.Tests/Kurrent.Client.Tests.csproj b/test/Kurrent.Client.Tests/Kurrent.Client.Tests.csproj new file mode 100644 index 000000000..ffca50910 --- /dev/null +++ b/test/Kurrent.Client.Tests/Kurrent.Client.Tests.csproj @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers + + + + + + + diff --git a/test/Kurrent.Client.Tests/KurrentClientOperationsTests.cs b/test/Kurrent.Client.Tests/KurrentClientOperationsTests.cs new file mode 100644 index 000000000..c8b70bdce --- /dev/null +++ b/test/Kurrent.Client.Tests/KurrentClientOperationsTests.cs @@ -0,0 +1,17 @@ +using EventStore.Client; + +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Misc")] +public class KurrentClientOperationOptionsTests { + [RetryFact] + public void setting_options_on_clone_should_not_modify_original() { + var options = KurrentClientOperationOptions.Default; + + var clonedOptions = options.Clone(); + clonedOptions.BatchAppendSize = int.MaxValue; + + Assert.Equal(options.BatchAppendSize, KurrentClientOperationOptions.Default.BatchAppendSize); + Assert.Equal(int.MaxValue, clonedOptions.BatchAppendSize); + } +} diff --git a/test/EventStore.Client.Tests/NodePreferenceComparerTests.cs b/test/Kurrent.Client.Tests/NodePreferenceComparerTests.cs similarity index 96% rename from test/EventStore.Client.Tests/NodePreferenceComparerTests.cs rename to test/Kurrent.Client.Tests/NodePreferenceComparerTests.cs index 1866e3444..cf42ded5e 100644 --- a/test/EventStore.Client.Tests/NodePreferenceComparerTests.cs +++ b/test/Kurrent.Client.Tests/NodePreferenceComparerTests.cs @@ -1,7 +1,9 @@ +using EventStore.Client; using static EventStore.Client.ClusterMessages.VNodeState; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; +[Trait("Category", "Target:Misc")] public class NodePreferenceComparerTests { static ClusterMessages.VNodeState RunTest(IComparer sut, params ClusterMessages.VNodeState[] states) => states @@ -56,4 +58,4 @@ internal void ReadOnlyReplicaTests(ClusterMessages.VNodeState expected, params C Assert.Equal(expected, actual); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/NodeSelectorTests.cs b/test/Kurrent.Client.Tests/NodeSelectorTests.cs similarity index 92% rename from test/EventStore.Client.Tests/NodeSelectorTests.cs rename to test/Kurrent.Client.Tests/NodeSelectorTests.cs index 9815305cd..b2b43ea2b 100644 --- a/test/EventStore.Client.Tests/NodeSelectorTests.cs +++ b/test/Kurrent.Client.Tests/NodeSelectorTests.cs @@ -1,7 +1,9 @@ using System.Net; +using EventStore.Client; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; +[Trait("Category", "Target:Misc")] public class NodeSelectorTests { static readonly ClusterMessages.VNodeState[] NotAllowedStates = { ClusterMessages.VNodeState.Manager, @@ -26,7 +28,7 @@ public class NodeSelectorTests { var notAllowedNodeId = Uuid.NewUuid(); var notAllowedNode = new DnsEndPoint(notAllowedNodeId.ToString(), 2114); - var settings = new EventStoreClientSettings { + var settings = new KurrentClientSettings { ConnectivitySettings = { DnsGossipSeeds = new[] { allowedNode, notAllowedNode }, Insecure = true @@ -50,7 +52,7 @@ public class NodeSelectorTests { [MemberData(nameof(InvalidStatesCases))] internal void InvalidStatesAreNotConsidered( ClusterMessages.ClusterInfo clusterInfo, - EventStoreClientSettings settings, + KurrentClientSettings settings, DnsEndPoint allowedNode ) { var sut = new NodeSelector(settings); @@ -60,7 +62,7 @@ DnsEndPoint allowedNode Assert.Equal(allowedNode.Port, selectedNode.Port); } - [Fact] + [RetryFact] public void DeadNodesAreNotConsidered() { var allowedNodeId = Uuid.NewUuid(); var allowedNode = new DnsEndPoint(allowedNodeId.ToString(), 2113); @@ -68,7 +70,7 @@ public void DeadNodesAreNotConsidered() { var notAllowedNodeId = Uuid.NewUuid(); var notAllowedNode = new DnsEndPoint(notAllowedNodeId.ToString(), 2114); - var settings = new EventStoreClientSettings { + var settings = new KurrentClientSettings { ConnectivitySettings = { DnsGossipSeeds = new[] { allowedNode, notAllowedNode }, Insecure = true @@ -96,7 +98,7 @@ public void DeadNodesAreNotConsidered() { [InlineData(NodePreference.ReadOnlyReplica, "readOnlyReplica")] [InlineData(NodePreference.Random, "any")] public void CanPrefer(NodePreference nodePreference, string expectedHost) { - var settings = new EventStoreClientSettings { + var settings = new KurrentClientSettings { ConnectivitySettings = { NodePreference = nodePreference } @@ -119,4 +121,4 @@ public void CanPrefer(NodePreference nodePreference, string expectedHost) { Assert.Equal(expectedHost, selectedNode.Host); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Operations.Tests/AuthenticationTests.cs b/test/Kurrent.Client.Tests/Operations/AuthenticationTests.cs similarity index 62% rename from test/EventStore.Client.Operations.Tests/AuthenticationTests.cs rename to test/Kurrent.Client.Tests/Operations/AuthenticationTests.cs index 084a92989..9a1d4dee2 100644 --- a/test/EventStore.Client.Operations.Tests/AuthenticationTests.cs +++ b/test/Kurrent.Client.Tests/Operations/AuthenticationTests.cs @@ -1,18 +1,18 @@ -namespace EventStore.Client.Operations.Tests; +using EventStore.Client; -public class AuthenticationTests : IClassFixture { - public AuthenticationTests(ITestOutputHelper output, InsecureClientTestFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); +namespace Kurrent.Client.Tests; - InsecureClientTestFixture Fixture { get; } - +[Trait("Category", "Target:Operations")] +public class AuthenticationTests(ITestOutputHelper output, AuthenticationTests.CustomFixture fixture) + : KurrentPermanentTests(output, fixture) { public enum CredentialsCase { None, TestUser, RootUser } public static IEnumerable InvalidAuthenticationCases() { - yield return new object?[] { 2, CredentialsCase.TestUser, CredentialsCase.None }; - yield return new object?[] { 3, CredentialsCase.None, CredentialsCase.None }; - yield return new object?[] { 4, CredentialsCase.RootUser, CredentialsCase.TestUser }; - yield return new object?[] { 5, CredentialsCase.TestUser, CredentialsCase.TestUser }; - yield return new object?[] { 6, CredentialsCase.None, CredentialsCase.TestUser }; + yield return [2, CredentialsCase.TestUser, CredentialsCase.None]; + yield return [3, CredentialsCase.None, CredentialsCase.None]; + yield return [4, CredentialsCase.RootUser, CredentialsCase.TestUser]; + yield return [5, CredentialsCase.TestUser, CredentialsCase.TestUser]; + yield return [6, CredentialsCase.None, CredentialsCase.TestUser]; } [Theory] @@ -21,10 +21,10 @@ public async Task system_call_with_invalid_credentials(int caseNr, CredentialsCa await ExecuteTest(caseNr, defaultCredentials, actualCredentials, true); public static IEnumerable ValidAuthenticationCases() { - yield return new object?[] { 1, CredentialsCase.RootUser, CredentialsCase.None }; - yield return new object?[] { 7, CredentialsCase.RootUser, CredentialsCase.RootUser }; - yield return new object?[] { 8, CredentialsCase.TestUser, CredentialsCase.RootUser }; - yield return new object?[] { 9, CredentialsCase.None, CredentialsCase.RootUser }; + yield return [1, CredentialsCase.RootUser, CredentialsCase.None]; + yield return [7, CredentialsCase.RootUser, CredentialsCase.RootUser]; + yield return [8, CredentialsCase.TestUser, CredentialsCase.RootUser]; + yield return [9, CredentialsCase.None, CredentialsCase.RootUser]; } [Theory] @@ -34,7 +34,7 @@ public async Task system_call_with_valid_credentials(int caseNr, CredentialsCase async Task ExecuteTest(int caseNr, CredentialsCase defaultCredentials, CredentialsCase actualCredentials, bool shouldThrow) { var testUser = await Fixture.CreateTestUser(); - + var defaultUserCredentials = GetCredentials(defaultCredentials); var actualUserCredentials = GetCredentials(actualCredentials); @@ -43,7 +43,7 @@ async Task ExecuteTest(int caseNr, CredentialsCase defaultCredentials, Credentia settings.DefaultCredentials = defaultUserCredentials; settings.ConnectionName = $"Authentication case #{caseNr} {defaultCredentials}"; - await using var operations = new EventStoreOperationsClient(settings); + await using var operations = new KurrentOperationsClient(settings); if (shouldThrow) await operations @@ -64,4 +64,6 @@ await operations _ => throw new ArgumentOutOfRangeException(nameof(credentialsCase), credentialsCase, null) }; } -} \ No newline at end of file + + public class CustomFixture() : KurrentPermanentFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/Kurrent.Client.Tests/Operations/MergeIndexTests.cs b/test/Kurrent.Client.Tests/Operations/MergeIndexTests.cs new file mode 100644 index 000000000..35112ddee --- /dev/null +++ b/test/Kurrent.Client.Tests/Operations/MergeIndexTests.cs @@ -0,0 +1,21 @@ +using EventStore.Client; + +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Operations")] +public class MergeIndexTests(ITestOutputHelper output, MergeIndexTests.CustomFixture fixture) + : KurrentPermanentTests(output, fixture) { + [RetryFact] + public async Task merge_indexes_does_not_throw() => + await Fixture.Operations + .MergeIndexesAsync(userCredentials: TestCredentials.Root) + .ShouldNotThrowAsync(); + + [RetryFact] + public async Task merge_indexes_without_credentials_throws() => + await Fixture.Operations + .MergeIndexesAsync() + .ShouldThrowAsync(); + + public class CustomFixture() : KurrentPermanentFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/Kurrent.Client.Tests/Operations/ResignNodeTests.cs b/test/Kurrent.Client.Tests/Operations/ResignNodeTests.cs new file mode 100644 index 000000000..82bd88252 --- /dev/null +++ b/test/Kurrent.Client.Tests/Operations/ResignNodeTests.cs @@ -0,0 +1,23 @@ +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; + +namespace Kurrent.Client.Tests.Operations; + +[Trait("Category", "Target:Operations")] +public class ResignNodeTests(ITestOutputHelper output, ResignNodeTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task resign_node_does_not_throw() => + await Fixture.Operations + .ResignNodeAsync(userCredentials: TestCredentials.Root) + .ShouldNotThrowAsync(); + + [RetryFact] + public async Task resign_node_without_credentials_throws() => + await Fixture.Operations + .ResignNodeAsync() + .ShouldThrowAsync(); + + public class CustomFixture() : KurrentTemporaryFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/Kurrent.Client.Tests/Operations/RestartPersistentSubscriptionsTests.cs b/test/Kurrent.Client.Tests/Operations/RestartPersistentSubscriptionsTests.cs new file mode 100644 index 000000000..f414a3529 --- /dev/null +++ b/test/Kurrent.Client.Tests/Operations/RestartPersistentSubscriptionsTests.cs @@ -0,0 +1,22 @@ +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests.Operations; + +[Trait("Category", "Target:Operations")] +public class RestartPersistentSubscriptionsTests(ITestOutputHelper output, RestartPersistentSubscriptionsTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task restart_persistent_subscriptions_does_not_throw() => + await Fixture.Operations + .RestartPersistentSubscriptions(userCredentials: TestCredentials.Root) + .ShouldNotThrowAsync(); + + [RetryFact] + public async Task restart_persistent_subscriptions_without_credentials_throws() => + await Fixture.Operations + .RestartPersistentSubscriptions() + .ShouldThrowAsync(); + + public class CustomFixture() : KurrentTemporaryFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/EventStore.Client.Operations.Tests/ScavengeTests.cs b/test/Kurrent.Client.Tests/Operations/ScavengeTests.cs similarity index 78% rename from test/EventStore.Client.Operations.Tests/ScavengeTests.cs rename to test/Kurrent.Client.Tests/Operations/ScavengeTests.cs index 35c1b3a1d..039a3b22b 100644 --- a/test/EventStore.Client.Operations.Tests/ScavengeTests.cs +++ b/test/Kurrent.Client.Tests/Operations/ScavengeTests.cs @@ -1,21 +1,20 @@ -namespace EventStore.Client.Operations.Tests; +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; -public class ScavengeTests : IClassFixture { - public class TestFixture() : EventStoreFixture(x => x.WithoutDefaultCredentials().RunInMemory(false)); - - public ScavengeTests(ITestOutputHelper output, TestFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); +namespace Kurrent.Client.Tests; - TestFixture Fixture { get; } - - [Fact] +[Trait("Category", "Target:Operations")] +public class ScavengeTests(ITestOutputHelper output, ScavengeTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] public async Task start() { var result = await Fixture.Operations.StartScavengeAsync(userCredentials: TestCredentials.Root); - result.ShouldBe(DatabaseScavengeResult.Started(result.ScavengeId)); + result.ScavengeId.ShouldNotBeNullOrEmpty(); } - [Fact] + [RetryFact] public async Task start_without_credentials_throws() => await Fixture.Operations .StartScavengeAsync() @@ -56,10 +55,10 @@ public async Task stop() { stopResult.ShouldBe(DatabaseScavengeResult.Stopped(startResult.ScavengeId)); } - [Fact] + [RetryFact] public async Task stop_when_no_scavenge_is_running() { var scavengeId = Guid.NewGuid().ToString(); - + var ex = await Fixture.Operations .StopScavengeAsync(scavengeId, userCredentials: TestCredentials.Root) .ShouldThrowAsync(); @@ -67,9 +66,11 @@ public async Task stop_when_no_scavenge_is_running() { // ex.ScavengeId.ShouldBeNull(); // it is blowing up because of this } - [Fact] + [RetryFact] public async Task stop_without_credentials_throws() => await Fixture.Operations .StopScavengeAsync(Guid.NewGuid().ToString()) .ShouldThrowAsync(); -} \ No newline at end of file + + public class CustomFixture() : KurrentTemporaryFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/Kurrent.Client.Tests/Operations/ShutdownNodeAuthenticationTests.cs b/test/Kurrent.Client.Tests/Operations/ShutdownNodeAuthenticationTests.cs new file mode 100644 index 000000000..f88fa32c8 --- /dev/null +++ b/test/Kurrent.Client.Tests/Operations/ShutdownNodeAuthenticationTests.cs @@ -0,0 +1,14 @@ +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Operations")] +public class ShutdownNodeAuthenticationTests(ITestOutputHelper output, ShutdownNodeAuthenticationTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task shutdown_without_credentials_throws() => + await Fixture.Operations.ShutdownAsync().ShouldThrowAsync(); + + public class CustomFixture() : KurrentTemporaryFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/Kurrent.Client.Tests/Operations/ShutdownNodeTests.cs b/test/Kurrent.Client.Tests/Operations/ShutdownNodeTests.cs new file mode 100644 index 000000000..4e685c37d --- /dev/null +++ b/test/Kurrent.Client.Tests/Operations/ShutdownNodeTests.cs @@ -0,0 +1,14 @@ +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; + +namespace Kurrent.Client.Tests.Operations; + +[Trait("Category", "Target:Operations")] +public class ShutdownNodeTests(ITestOutputHelper output, ShutdownNodeTests.NoDefaultCredentialsFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task shutdown_does_not_throw() => + await Fixture.Operations.ShutdownAsync(userCredentials: TestCredentials.Root).ShouldNotThrowAsync(); + + public class NoDefaultCredentialsFixture() : KurrentTemporaryFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/FilterTestCase.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/FilterTestCases.cs similarity index 94% rename from test/EventStore.Client.PersistentSubscriptions.Tests/FilterTestCase.cs rename to test/Kurrent.Client.Tests/PersistentSubscriptions/FilterTestCases.cs index 4787105a4..5dc4c098b 100644 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/FilterTestCase.cs +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/FilterTestCases.cs @@ -1,6 +1,7 @@ using System.Reflection; +using EventStore.Client; -namespace EventStore.Client.PersistentSubscriptions.Tests; +namespace Kurrent.Client.Tests.PersistentSubscriptions; public static class Filters { const string StreamNamePrefix = nameof(StreamNamePrefix); @@ -37,4 +38,4 @@ public static class Filters { public static (Func getFilter, Func prepareEvent) GetFilter(string name) => s_filters[name]; -} \ No newline at end of file +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllConnectToExistingWithStartFromNotSetObsoleteTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllConnectToExistingWithStartFromNotSetObsoleteTests.cs new file mode 100644 index 000000000..1eb96f88a --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllConnectToExistingWithStartFromNotSetObsoleteTests.cs @@ -0,0 +1,51 @@ +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllConnectToExistingWithStartFromNotSetObsoleteTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task connect_to_existing_with_start_from_not_set() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + TaskCompletionSource firstNonSystemEventSource = new(); + + foreach (var @event in Fixture.CreateTestEvents(10)) + await Fixture.Streams.AppendToStreamAsync( + stream, + StreamState.Any, + new[] { + @event + } + ); + + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(), + userCredentials: TestCredentials.Root + ); + + using var subscription = await Fixture.Subscriptions.SubscribeToAllAsync( + group, + async (subscription, e, r, ct) => { + if (SystemStreams.IsSystemStream(e.OriginalStreamId)) { + await subscription.Ack(e); + return; + } + + firstNonSystemEventSource.TrySetResult(e); + await subscription.Ack(e); + }, + (subscription, reason, ex) => { + if (reason != SubscriptionDroppedReason.Disposed) + firstNonSystemEventSource.TrySetException(ex!); + }, + TestCredentials.Root + ); + + await Assert.ThrowsAsync(() => firstNonSystemEventSource.Task.WithTimeout()); + } +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllConnectToExistingWithStartFromSetToEndPositionObsoleteTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllConnectToExistingWithStartFromSetToEndPositionObsoleteTests.cs new file mode 100644 index 000000000..2706e0669 --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllConnectToExistingWithStartFromSetToEndPositionObsoleteTests.cs @@ -0,0 +1,46 @@ +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllConnectToExistingWithStartFromSetToEndPositionObsoleteTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task connect_to_existing_with_start_from_set_to_end_position() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + TaskCompletionSource firstNonSystemEventSource = new(); + + foreach (var @event in Fixture.CreateTestEvents(10)) { + await Fixture.Streams.AppendToStreamAsync( + stream, + StreamState.Any, + [@event] + ); + } + + await Fixture.Subscriptions.CreateToAllAsync(group, new(startFrom: Position.End), userCredentials: TestCredentials.Root); + + using var subscription = await Fixture.Subscriptions.SubscribeToAllAsync( + group, + async (subscription, e, r, ct) => { + if (SystemStreams.IsSystemStream(e.OriginalStreamId)) { + await subscription.Ack(e); + return; + } + + firstNonSystemEventSource.TrySetResult(e); + await subscription.Ack(e); + }, + (subscription, reason, ex) => { + if (reason != SubscriptionDroppedReason.Disposed) + firstNonSystemEventSource.TrySetException(ex!); + }, + TestCredentials.Root + ); + + await Assert.ThrowsAsync(() => firstNonSystemEventSource.Task.WithTimeout()); + } +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllConnectWithoutReadPermissionsObsoleteTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllConnectWithoutReadPermissionsObsoleteTests.cs new file mode 100644 index 000000000..f7004b890 --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllConnectWithoutReadPermissionsObsoleteTests.cs @@ -0,0 +1,34 @@ +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllConnectWithoutReadPermissionsObsoleteTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task connect_to_existing_without_read_all_permissions() { + var group = Fixture.GetGroupName(); + var user = Fixture.GetUserCredentials(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + await Fixture.Users.CreateUserWithRetry( + user.Username!, + user.Username!, + [], + user.Password!, + TestCredentials.Root + ); + + await Assert.ThrowsAsync( + async () => { + using var _ = await Fixture.Subscriptions.SubscribeToAllAsync( + group, + delegate { return Task.CompletedTask; }, + userCredentials: user + ); + } + ); + } +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllFilterObsoleteTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllFilterObsoleteTests.cs new file mode 100644 index 000000000..95c3aba2b --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllFilterObsoleteTests.cs @@ -0,0 +1,131 @@ +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllFilterObsoleteTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryTheory] + [MemberData(nameof(FilterCases))] + public async Task happy_case_filtered_reads_all_existing_filtered_events(string filterName) { + var streamPrefix = $"{filterName}-{Fixture.GetStreamName()}"; + var group = Fixture.GetGroupName(); + var (getFilter, prepareEvent) = Filters.GetFilter(filterName); + var filter = getFilter(streamPrefix); + + await Fixture.Streams.AppendToStreamAsync( + Guid.NewGuid().ToString(), + StreamState.NoStream, + Fixture.CreateTestEvents(256) + ); + + await Fixture.Streams.SetStreamMetadataAsync( + SystemStreams.AllStream, + StreamState.Any, + new(acl: new(SystemRoles.All)), + userCredentials: TestCredentials.Root + ); + + var appearedEvents = new List(); + var events = Fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)).ToArray(); + + foreach (var e in events) { + await Fixture.Streams.AppendToStreamAsync( + $"{streamPrefix}_{Guid.NewGuid():n}", + StreamState.NoStream, + [e] + ); + } + + await Fixture.Subscriptions.CreateToAllAsync( + group, + filter, + new(startFrom: Position.Start), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + await subscription.Messages + .OfType() + .Take(events.Length) + .ForEachAwaitAsync( + async e => { + var (resolvedEvent, _) = e; + appearedEvents.Add(resolvedEvent.Event); + await subscription.Ack(resolvedEvent); + } + ) + .WithTimeout(); + + Assert.Equal(events.Select(x => x.EventId), appearedEvents.Select(x => x.EventId)); + } + + [RetryTheory] + [MemberData(nameof(FilterCases))] + public async Task happy_case_filtered_with_start_from_set(string filterName) { + var group = Fixture.GetGroupName(); + var streamPrefix = $"{filterName}-{Fixture.GetStreamName()}"; + var (getFilter, prepareEvent) = Filters.GetFilter(filterName); + var filter = getFilter(streamPrefix); + + var events = Fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)).ToArray(); + var eventsToSkip = events.Take(10).ToArray(); + var eventsToCapture = events.Skip(10).ToArray(); + + IWriteResult? eventToCaptureResult = null; + + await Fixture.Streams.AppendToStreamAsync( + Guid.NewGuid().ToString(), + StreamState.NoStream, + Fixture.CreateTestEvents(256) + ); + + await Fixture.Streams.SetStreamMetadataAsync( + SystemStreams.AllStream, + StreamState.Any, + new(acl: new(SystemRoles.All)), + userCredentials: TestCredentials.Root + ); + + foreach (var e in eventsToSkip) { + await Fixture.Streams.AppendToStreamAsync( + $"{streamPrefix}_{Guid.NewGuid():n}", + StreamState.NoStream, + new[] { e } + ); + } + + foreach (var e in eventsToCapture) { + var result = await Fixture.Streams.AppendToStreamAsync( + $"{streamPrefix}_{Guid.NewGuid():n}", + StreamState.NoStream, + new[] { e } + ); + + eventToCaptureResult ??= result; + } + + await Fixture.Subscriptions.CreateToAllAsync( + group, + filter, + new(startFrom: eventToCaptureResult!.LogPosition), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + var appearedEvents = await subscription.Messages.OfType() + .Take(10) + .Select(e => e.ResolvedEvent.Event) + .ToArrayAsync() + .AsTask() + .WithTimeout(); + + Assert.Equal(eventsToCapture.Select(x => x.EventId), appearedEvents.Select(x => x.EventId)); + } + + public static IEnumerable FilterCases() => Filters.All.Select(filter => new object[] { filter }); +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllGetInfoObsoleteTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllGetInfoObsoleteTests.cs new file mode 100644 index 000000000..2b8532ad4 --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllGetInfoObsoleteTests.cs @@ -0,0 +1,97 @@ +// ReSharper disable InconsistentNaming + +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllGetInfoObsoleteTests(SubscribeToAllGetInfoObsoleteTests.CustomFixture fixture) + : IClassFixture { + static readonly PersistentSubscriptionSettings Settings = new( + resolveLinkTos: true, + startFrom: Position.Start, + extraStatistics: true, + messageTimeout: TimeSpan.FromSeconds(9), + maxRetryCount: 11, + liveBufferSize: 303, + readBatchSize: 30, + historyBufferSize: 909, + checkPointAfter: TimeSpan.FromSeconds(1), + checkPointLowerBound: 1, + checkPointUpperBound: 1, + maxSubscriberCount: 500, + consumerStrategyName: SystemConsumerStrategies.Pinned + ); + + [RetryFact] + public async Task throws_with_non_existing_subscription() { + var group = $"NonExisting-{fixture.GetGroupName()}"; + + await Assert.ThrowsAsync( + async () => await fixture.Subscriptions.GetInfoToAllAsync(group, userCredentials: TestCredentials.Root) + ); + } + + [RetryFact] + public async Task throws_with_no_credentials() { + var group = $"NonExisting-{fixture.GetGroupName()}"; + + await Assert.ThrowsAsync( + async () => + await fixture.Subscriptions.GetInfoToAllAsync(group) + ); + } + + [RetryFact] + public async Task throws_with_non_existing_user() { + var group = $"NonExisting-{fixture.GetGroupName()}"; + + await Assert.ThrowsAsync( + async () => + await fixture.Subscriptions.GetInfoToAllAsync(group, userCredentials: TestCredentials.TestBadUser) + ); + } + + [RetryFact] + public async Task returns_result_with_normal_user_credentials() { + var result = await fixture.Subscriptions.GetInfoToAllAsync(fixture.Group, userCredentials: TestCredentials.Root); + + Assert.Equal("$all", result.EventSource); + } + + public class CustomFixture : KurrentTemporaryFixture { + public string Group { get; } + + public CustomFixture() : base(x => x.WithoutDefaultCredentials()) { + Group = GetGroupName(); + + OnSetup += async () => { + await Subscriptions.CreateToAllAsync(Group, Settings, userCredentials: TestCredentials.Root); + + var counter = 0; + var tcs = new TaskCompletionSource(); + + await Subscriptions.SubscribeToAllAsync( + Group, + (s, e, r, ct) => { + counter++; + + switch (counter) { + case 1: + s.Nack(PersistentSubscriptionNakEventAction.Park, "Test", e); + break; + + case > 10: + tcs.TrySetResult(); + break; + } + + return Task.CompletedTask; + }, + userCredentials: TestCredentials.Root + ); + }; + } + }; +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllListWithIncorrectCredentialsObsoleteTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllListWithIncorrectCredentialsObsoleteTests.cs new file mode 100644 index 000000000..7c1426073 --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllListWithIncorrectCredentialsObsoleteTests.cs @@ -0,0 +1,64 @@ +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllListWithIncorrectCredentialsObsoleteTests(ITestOutputHelper output, SubscribeToAllListWithIncorrectCredentialsObsoleteTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task throws_with_no_credentials() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + const int streamSubscriptionCount = 4; + const int allStreamSubscriptionCount = 3; + + for (var i = 0; i < streamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + for (var i = 0; i < allStreamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToAllAsync( + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + await Assert.ThrowsAsync(async () => await Fixture.Subscriptions.ListToAllAsync()); + } + + [RetryFact] + public async Task throws_with_non_existing_user() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + const int streamSubscriptionCount = 4; + const int allStreamSubscriptionCount = 3; + + for (var i = 0; i < streamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + for (var i = 0; i < allStreamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToAllAsync( + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + await Assert.ThrowsAsync( + async () => await Fixture.Subscriptions.ListToAllAsync(userCredentials: TestCredentials.TestBadUser) + ); + } + + public class CustomFixture() : KurrentTemporaryFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllNoDefaultCredentialsObsoleteTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllNoDefaultCredentialsObsoleteTests.cs new file mode 100644 index 000000000..36685373f --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllNoDefaultCredentialsObsoleteTests.cs @@ -0,0 +1,103 @@ +using EventStore.Client; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllNoDefaultCredentialsObsoleteTests(ITestOutputHelper output, SubscribeToAllNoDefaultCredentialsObsoleteTests.CustomFixture fixture) + : KurrentPermanentTests(output, fixture) { + [RetryFact] + public async Task connect_to_existing_without_permissions() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + await Assert.ThrowsAsync( + async () => { + using var _ = await Fixture.Subscriptions.SubscribeToAllAsync( + group, + delegate { return Task.CompletedTask; } + ); + } + ); + } + + [RetryFact] + public async Task throws_persistent_subscription_not_found() { + var group = Fixture.GetGroupName(); + + var ex = await Assert.ThrowsAsync( + async () => { + using var _ = await Fixture.Subscriptions.SubscribeToAllAsync( + group, + delegate { return Task.CompletedTask; }, + userCredentials: TestCredentials.Root + ); + } + ).WithTimeout(); + + Assert.Equal(SystemStreams.AllStream, ex.StreamName); + Assert.Equal(group, ex.GroupName); + } + + [RetryFact] + public async Task deleting_without_permissions() { + await Assert.ThrowsAsync(() => Fixture.Subscriptions.DeleteToAllAsync(Guid.NewGuid().ToString())); + } + + [RetryFact] + public async Task create_without_permissions() { + var group = Fixture.GetGroupName(); + + await Assert.ThrowsAsync( + () => + Fixture.Subscriptions.CreateToAllAsync( + group, + new() + ) + ); + } + + [RetryFact] + public async Task update_existing_without_permissions() { + var group = Fixture.GetGroupName(); + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(), + userCredentials: TestCredentials.Root + ); + + await Assert.ThrowsAsync( + () => Fixture.Subscriptions.UpdateToAllAsync( + group, + new() + ) + ); + } + + [RetryFact] + public async Task update_non_existent() { + var group = Fixture.GetGroupName(); + await Assert.ThrowsAsync( + () => Fixture.Subscriptions.UpdateToAllAsync( + group, + new(), + userCredentials: TestCredentials.Root + ) + ); + } + + [RetryFact] + public Task update_with_prepare_position_larger_than_commit_position() { + var group = Fixture.GetGroupName(); + return Assert.ThrowsAsync( + () => + Fixture.Subscriptions.UpdateToAllAsync( + group, + new(startFrom: new Position(0, 1)), + userCredentials: TestCredentials.Root + ) + ); + } + + public class CustomFixture() : KurrentPermanentFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllObsoleteTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllObsoleteTests.cs new file mode 100644 index 000000000..05dc4baff --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllObsoleteTests.cs @@ -0,0 +1,786 @@ +using System.Text; +using EventStore.Client; +using Grpc.Core; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllObsoleteTests(ITestOutputHelper output, KurrentPermanentFixture fixture) + : KurrentPermanentTests(output, fixture) { + [RetryFact] + public async Task connect_to_existing_with_max_one_client() { + // Arrange + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(maxSubscriberCount: 1), userCredentials: TestCredentials.Root); + + using var first = await Fixture.Subscriptions.SubscribeToAllAsync( + group, + delegate { return Task.CompletedTask; }, + userCredentials: TestCredentials.Root + ).WithTimeout(); + + var ex = await Assert.ThrowsAsync( + async () => { + using var _ = await Fixture.Subscriptions.SubscribeToAllAsync( + group, + delegate { return Task.CompletedTask; }, + userCredentials: TestCredentials.Root + ); + } + ).WithTimeout(); + + Assert.Equal(SystemStreams.AllStream, ex.StreamName); + Assert.Equal(group, ex.GroupName); + } + + [RetryFact] + public async Task connect_to_existing_with_permissions() { + // Arrange + var group = Fixture.GetGroupName(); + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); + using var subscription = await Fixture.Subscriptions.SubscribeToAllAsync( + group, + delegate { return Task.CompletedTask; }, + (s, reason, ex) => dropped.TrySetResult((reason, ex)), + TestCredentials.Root + ).WithTimeout(); + + Assert.NotNull(subscription); + + await Assert.ThrowsAsync(() => dropped.Task.WithTimeout()); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_beginning() { + var group = Fixture.GetGroupName(); + + TaskCompletionSource firstEventSource = new(); + + // append 10 events to random streams to make sure we have at least 10 events in the transaction file + foreach (var @event in Fixture.CreateTestEvents(10)) { + await Fixture.Streams.AppendToStreamAsync( + Guid.NewGuid().ToString(), + StreamState.NoStream, + [@event] + ); + } + + var events = await Fixture.Streams + .ReadAllAsync(Direction.Forwards, Position.Start, 10, userCredentials: TestCredentials.Root) + .ToArrayAsync(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(startFrom: Position.Start), userCredentials: TestCredentials.Root); + + using var subscription = await Fixture.Subscriptions.SubscribeToAllAsync( + group, + async (subscription, e, r, ct) => { + firstEventSource.TrySetResult(e); + await subscription.Ack(e); + }, + (subscription, reason, ex) => { + if (reason != SubscriptionDroppedReason.Disposed) + firstEventSource.TrySetException(ex!); + }, + TestCredentials.Root + ); + + var resolvedEvent = await firstEventSource.Task.WithTimeout(TimeSpan.FromSeconds(10)); + Assert.Equal(events![0].Event.EventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_not_set_then_event_written() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + var expectedStreamId = Guid.NewGuid().ToString(); + var expectedEvent = Fixture.CreateTestEvents(1).First(); + + TaskCompletionSource firstNonSystemEventSource = new(); + + foreach (var @event in Fixture.CreateTestEvents(10)) { + await Fixture.Streams.AppendToStreamAsync( + stream, + StreamState.Any, + [@event] + ); + } + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + using var subscription = await Fixture.Subscriptions.SubscribeToAllAsync( + group, + async (subscription, e, r, ct) => { + if (SystemStreams.IsSystemStream(e.OriginalStreamId)) { + await subscription.Ack(e); + return; + } + + firstNonSystemEventSource.TrySetResult(e); + await subscription.Ack(e); + }, + (subscription, reason, ex) => { + if (reason != SubscriptionDroppedReason.Disposed) + firstNonSystemEventSource.TrySetException(ex!); + }, + TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync(expectedStreamId, StreamState.NoStream, [expectedEvent]); + + var resolvedEvent = await firstNonSystemEventSource.Task.WithTimeout(); + Assert.Equal(expectedEvent!.EventId, resolvedEvent.Event.EventId); + Assert.Equal(expectedStreamId, resolvedEvent.Event.EventStreamId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_set_to_end_position_then_event_written() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + var expectedStreamId = Fixture.GetStreamName(); + var expectedEvent = Fixture.CreateTestEvents().First(); + + TaskCompletionSource firstNonSystemEventSource = new(); + + foreach (var @event in Fixture.CreateTestEvents(10)) { + await Fixture.Streams.AppendToStreamAsync( + stream, + StreamState.Any, + [@event] + ); + } + + await Fixture.Subscriptions.CreateToAllAsync(group, new(startFrom: Position.End), userCredentials: TestCredentials.Root); + using var subscription = await Fixture.Subscriptions.SubscribeToAllAsync( + group, + async (subscription, e, r, ct) => { + if (SystemStreams.IsSystemStream(e.OriginalStreamId)) { + await subscription.Ack(e); + return; + } + + firstNonSystemEventSource.TrySetResult(e); + await subscription.Ack(e); + }, + (subscription, reason, ex) => { + if (reason != SubscriptionDroppedReason.Disposed) + firstNonSystemEventSource.TrySetException(ex!); + }, + TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync(expectedStreamId, StreamState.NoStream, [expectedEvent]); + + var resolvedEvent = await firstNonSystemEventSource.Task.WithTimeout(); + Assert.Equal(expectedEvent.EventId, resolvedEvent.Event.EventId); + Assert.Equal(expectedStreamId, resolvedEvent.Event.EventStreamId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_set_to_invalid_middle_position() { + var group = Fixture.GetGroupName(); + + TaskCompletionSource<(SubscriptionDroppedReason, Exception?)> dropped = new(); + + var invalidPosition = new Position(1L, 1L); + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(startFrom: invalidPosition), + userCredentials: TestCredentials.Root + ); + + using var subscription = await Fixture.Subscriptions.SubscribeToAllAsync( + group, + async (subscription, e, r, ct) => await subscription.Ack(e), + (subscription, reason, ex) => { dropped.TrySetResult((reason, ex)); }, + TestCredentials.Root + ); + + var (reason, exception) = await dropped.Task.WithTimeout(); + Assert.Equal(SubscriptionDroppedReason.ServerError, reason); + Assert.IsType(exception); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_set_to_valid_middle_position() { + var group = Fixture.GetGroupName(); + + TaskCompletionSource firstEventSource = new(); + + var events = await Fixture.Streams + .ReadAllAsync(Direction.Forwards, Position.Start, 10, userCredentials: TestCredentials.Root) + .ToArrayAsync(); + + var expectedEvent = events[events.Length / 2]; //just a random event in the middle of the results + + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(startFrom: expectedEvent.OriginalPosition), + userCredentials: TestCredentials.Root + ); + + using var subscription = await Fixture.Subscriptions.SubscribeToAllAsync( + group, + async (subscription, e, r, ct) => { + firstEventSource.TrySetResult(e); + await subscription.Ack(e); + }, + (subscription, reason, ex) => { + if (reason != SubscriptionDroppedReason.Disposed) + firstEventSource.TrySetException(ex!); + }, + TestCredentials.Root + ); + + var resolvedEvent = await firstEventSource.Task.WithTimeout(); + Assert.Equal(expectedEvent.OriginalPosition, resolvedEvent.Event.Position); + Assert.Equal(expectedEvent.Event.EventId, resolvedEvent.Event.EventId); + Assert.Equal(expectedEvent.Event.EventStreamId, resolvedEvent.Event.EventStreamId); + } + + [RetryFact] + public async Task connect_with_retries() { + // Arrange + var group = Fixture.GetGroupName(); + + TaskCompletionSource retryCountSource = new(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(startFrom: Position.Start), userCredentials: TestCredentials.Root); + + // Act + using var subscription = await Fixture.Subscriptions.SubscribeToAllAsync( + group, + async (subscription, e, r, ct) => { + if (r > 4) { + retryCountSource.TrySetResult(r.Value); + await subscription.Ack(e.Event.EventId); + } else { + await subscription.Nack( + PersistentSubscriptionNakEventAction.Retry, + "Not yet tried enough times", + e + ); + } + }, + (subscription, reason, ex) => { + if (reason != SubscriptionDroppedReason.Disposed) + retryCountSource.TrySetException(ex!); + }, + TestCredentials.Root + ); + + // Assert + Assert.Equal(5, await retryCountSource.Task.WithTimeout()); + } + + [RetryFact] + public async Task deleting_existing_with_subscriber() { + var group = Fixture.GetGroupName(); + + TaskCompletionSource<(SubscriptionDroppedReason, Exception?)> dropped = new(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + using var subscription = await Fixture.Subscriptions.SubscribeToAllAsync( + group, + async (s, e, i, ct) => await s.Ack(e), + (s, r, e) => dropped.TrySetResult((r, e)), + TestCredentials.Root + ); + + // todo: investigate why this test is flaky without this delay + await Task.Delay(500); + + await Fixture.Subscriptions.DeleteToAllAsync(group, userCredentials: TestCredentials.Root); + + var (reason, exception) = await dropped.Task.WithTimeout(); + Assert.Equal(SubscriptionDroppedReason.ServerError, reason); + var ex = Assert.IsType(exception); + + Assert.Equal(SystemStreams.AllStream, ex.StreamName); + Assert.Equal(group, ex.GroupName); + } + + // [RetryFact] + // public async Task happy_case_catching_up_to_link_to_events_manual_ack() { + // var group = Fixture.GetGroupName(); + // var bufferCount = 10; + // var eventWriteCount = bufferCount * 2; + // TaskCompletionSource eventsReceived = new(); + // int eventReceivedCount = 0; + // + // var events = Fixture.CreateTestEvents(eventWriteCount) + // .Select( + // (e, i) => new EventData( + // e.EventId, + // SystemEventTypes.LinkTo, + // Encoding.UTF8.GetBytes($"{i}@test"), + // contentType: Constants.Metadata.ContentTypes.ApplicationOctetStream + // ) + // ) + // .ToArray(); + // + // foreach (var e in events) { + // await Fixture.Streams.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); + // } + // + // await Fixture.Subscriptions.CreateToAllAsync( + // group, + // new(startFrom: Position.Start, resolveLinkTos: true), + // userCredentials: TestCredentials.Root + // ); + // + // using var subscription = await Fixture.Subscriptions.SubscribeToAllAsync( + // group, + // async (subscription, e, retryCount, ct) => { + // await subscription.Ack(e); + // + // if (e.OriginalStreamId.StartsWith("test-") + // && Interlocked.Increment(ref eventReceivedCount) == events.Length) + // eventsReceived.TrySetResult(true); + // }, + // (s, r, e) => { + // if (e != null) + // eventsReceived.TrySetException(e); + // }, + // bufferSize: bufferCount, + // userCredentials: TestCredentials.Root + // ); + // + // await eventsReceived.Task.WithTimeout(); + // } + // + // [RetryFact] + // public async Task happy_case_catching_up_to_normal_events_manual_ack() { + // var group = Fixture.GetGroupName(); + // var stream = Fixture.GetStreamName(); + // var bufferCount = 10; + // var eventWriteCount = bufferCount * 2; + // int eventReceivedCount = 0; + // + // TaskCompletionSource eventsReceived = new(); + // + // var events = Fixture.CreateTestEvents(eventWriteCount).ToArray(); + // + // foreach (var e in events) + // await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, [e]); + // + // await Fixture.Subscriptions.CreateToAllAsync( + // group, + // new(startFrom: Position.Start, resolveLinkTos: true), + // userCredentials: TestCredentials.Root + // ); + // + // using var subscription = await Fixture.Subscriptions.SubscribeToAllAsync( + // group, + // async (subscription, e, retryCount, ct) => { + // await subscription.Ack(e); + // + // if (e.OriginalStreamId.StartsWith("test-") + // && Interlocked.Increment(ref eventReceivedCount) == events.Length) + // eventsReceived.TrySetResult(true); + // }, + // (s, r, e) => { + // if (e != null) + // eventsReceived.TrySetException(e); + // }, + // bufferSize: bufferCount, + // userCredentials: TestCredentials.Root + // ); + // + // await eventsReceived.Task.WithTimeout(); + // } + + [RetryFact] + public async Task happy_case_writing_and_subscribing_to_normal_events_manual_ack() { + var group = Fixture.GetGroupName(); + var bufferCount = 10; + var eventWriteCount = bufferCount * 2; + int eventReceivedCount = 0; + + TaskCompletionSource eventsReceived = new(); + + var events = Fixture.CreateTestEvents(eventWriteCount).ToArray(); + + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(startFrom: Position.End, resolveLinkTos: true), + userCredentials: TestCredentials.Root + ); + + using var subscription = await Fixture.Subscriptions.SubscribeToAllAsync( + group, + async (subscription, e, retryCount, ct) => { + await subscription.Ack(e); + if (e.OriginalStreamId.StartsWith("test-") + && Interlocked.Increment(ref eventReceivedCount) == events.Length) + eventsReceived.TrySetResult(true); + }, + (s, r, e) => { + if (e != null) + eventsReceived.TrySetException(e); + }, + bufferSize: bufferCount, + userCredentials: TestCredentials.Root + ); + + foreach (var e in events) { + await Fixture.Streams.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); + } + + await eventsReceived.Task.WithTimeout(); + } + + [RetryFact] + public async Task update_existing_with_check_point() { + var group = Fixture.GetGroupName(); + var events = Fixture.CreateTestEvents(5).ToArray(); + var appearedEvents = new List(); + + TaskCompletionSource appeared = new(); + TaskCompletionSource<(SubscriptionDroppedReason, Exception?)> droppedSource = new(); + TaskCompletionSource resumedSource = new(); + Position checkPoint = default; + + foreach (var e in events) + await Fixture.Streams.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, [e]); + + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(checkPointLowerBound: 5, checkPointAfter: TimeSpan.FromSeconds(1), startFrom: Position.Start), + userCredentials: TestCredentials.Root + ); + + using var firstSubscription = await Fixture.Subscriptions.SubscribeToAllAsync( + group, + async (s, e, r, ct) => { + appearedEvents.Add(e); + + if (appearedEvents.Count == events.Length) + appeared.TrySetResult(true); + + await s.Ack(e); + }, + (subscription, reason, ex) => droppedSource.TrySetResult((reason, ex)), + TestCredentials.Root + ); + + await Task.WhenAll(appeared.Task, WaitForCheckpoint().WithTimeout()); + + // Force restart of the subscription + await Fixture.Subscriptions.UpdateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + await droppedSource.Task.WithTimeout(); + + using var secondSubscription = await Fixture.Subscriptions.SubscribeToAllAsync( + group, + async (s, e, r, ct) => { + resumedSource.TrySetResult(e); + await s.Ack(e); + s.Dispose(); + }, + (_, reason, ex) => { + if (ex is not null) + resumedSource.TrySetException(ex); + else + resumedSource.TrySetResult(default); + }, + TestCredentials.Root + ); + + foreach (var e in events) + await Fixture.Streams.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.NoStream, new[] { e }); + + var resumedEvent = await resumedSource.Task.WithTimeout(TimeSpan.FromSeconds(10)); + Assert.True(resumedEvent.Event.Position > checkPoint); + + return; + + async Task WaitForCheckpoint() { + await using var subscription = Fixture.Streams.SubscribeToStream( + $"$persistentsubscription-$all::{group}-checkpoint", + FromStream.Start, + userCredentials: TestCredentials.Root + ); + + await foreach (var message in subscription.Messages) { + if (message is not StreamMessage.Event(var resolvedEvent)) { + continue; + } + + checkPoint = resolvedEvent.Event.Data.ParsePosition(); + return; + } + } + } + + [RetryFact] + public async Task update_existing_with_check_point_filtered() { + var group = Fixture.GetGroupName(); + + TaskCompletionSource<(SubscriptionDroppedReason, Exception?)> droppedSource = new(); + TaskCompletionSource resumedSource = new(); + TaskCompletionSource appeared = new(); + + List appearedEvents = []; + + EventData[] events = Fixture.CreateTestEvents(5).ToArray(); + + Position checkPoint = default; + + foreach (var e in events) + await Fixture.Streams.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.NoStream, [e]); + + await Fixture.Subscriptions.CreateToAllAsync( + group, + StreamFilter.Prefix("test"), + new( + checkPointLowerBound: 5, + checkPointAfter: TimeSpan.FromSeconds(1), + startFrom: Position.Start + ), + userCredentials: TestCredentials.Root + ); + + await Fixture.Subscriptions.SubscribeToAllAsync( + group, + async (s, e, r, ct) => { + appearedEvents.Add(e); + + if (appearedEvents.Count == events.Length) + appeared.TrySetResult(true); + + await s.Ack(e); + }, + (subscription, reason, ex) => droppedSource.TrySetResult((reason, ex)), + TestCredentials.Root + ); + + await Task.WhenAll(appeared.Task, Checkpointed()).WithTimeout(); + + // Force restart of the subscription + await Fixture.Subscriptions.UpdateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + await droppedSource.Task.WithTimeout(); + + await Fixture.Subscriptions.SubscribeToAllAsync( + group, + async (s, e, r, ct) => { + resumedSource.TrySetResult(e); + await s.Ack(e); + s.Dispose(); + }, + (_, reason, ex) => { + if (ex is not null) + resumedSource.TrySetException(ex); + else + resumedSource.TrySetResult(default); + }, + TestCredentials.Root + ); + + foreach (var e in events) + await Fixture.Streams.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.NoStream, new[] { e }); + + Task resumed = resumedSource.Task; + + var resumedEvent = await resumed.WithTimeout(TimeSpan.FromSeconds(10)); + Assert.True(resumedEvent.Event.Position > checkPoint); + + return; + + async Task Checkpointed() { + await using var subscription = Fixture.Streams.SubscribeToStream( + $"$persistentsubscription-$all::{group}-checkpoint", + FromStream.Start, + userCredentials: TestCredentials.Root + ); + + await foreach (var message in subscription.Messages) { + if (message is not StreamMessage.Event(var resolvedEvent)) { + continue; + } + + checkPoint = resolvedEvent.Event.Data.ParsePosition(); + return; + } + } + } + + [RetryFact] + public async Task update_existing_with_subscribers() { + var group = Fixture.GetGroupName(); + + TaskCompletionSource<(SubscriptionDroppedReason, Exception?)> droppedSource = new(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(startFrom: Position.Start), userCredentials: TestCredentials.Root); + + using var subscription = Fixture.Subscriptions.SubscribeToAllAsync( + group, + delegate { return Task.CompletedTask; }, + (subscription, reason, ex) => droppedSource.TrySetResult((reason, ex)), + TestCredentials.Root + ); + + // todo: investigate why this test is flaky without this delay + await Task.Delay(500); + + await Fixture.Subscriptions.UpdateToAllAsync( + group, + new(), + userCredentials: TestCredentials.Root + ); + + var (reason, exception) = await droppedSource.Task.WithTimeout(TimeSpan.FromSeconds(10)); + Assert.Equal(SubscriptionDroppedReason.ServerError, reason); + var ex = Assert.IsType(exception); + + Assert.Equal(SystemStreams.AllStream, ex.StreamName); + Assert.Equal(group, ex.GroupName); + } + + [RetryFact] + public async Task when_writing_and_filtering_out_events() { + var events = Fixture.CreateTestEvents(10).ToArray(); + var group = Fixture.GetGroupName(); + var prefix = Guid.NewGuid().ToString("N"); + + TaskCompletionSource appeared = new(); + + Position firstCheckPoint = default; + Position secondCheckPoint = default; + List appearedEvents = []; + + foreach (var e in events) + await Fixture.Streams.AppendToStreamAsync(prefix + Guid.NewGuid(), StreamState.Any, [e]); + + await Fixture.Subscriptions.CreateToAllAsync( + group, + StreamFilter.Prefix(prefix), + new( + checkPointLowerBound: 1, + checkPointUpperBound: 5, + checkPointAfter: TimeSpan.FromSeconds(1), + startFrom: Position.Start + ), + userCredentials: TestCredentials.Root + ); + + using var subscription = await Fixture.Subscriptions.SubscribeToAllAsync( + group, + async (s, e, r, ct) => { + appearedEvents.Add(e); + + if (appearedEvents.Count == events.Length) + appeared.TrySetResult(true); + + await s.Ack(e); + }, + userCredentials: TestCredentials.Root + ); + + await Task.WhenAll(appeared.Task, WaitForCheckpoints().WithTimeout()); + + foreach (var e in events) { + await Fixture.Streams.AppendToStreamAsync( + "filtered-out-stream-" + Guid.NewGuid(), + StreamState.Any, + [e] + ); + } + + Assert.True(secondCheckPoint > firstCheckPoint); + Assert.Equal(events.Select(e => e.EventId), appearedEvents.Select(e => e.Event.EventId)); + + return; + + async Task WaitForCheckpoints() { + bool firstCheckpointSet = false; + await using var subscription = Fixture.Streams.SubscribeToStream( + $"$persistentsubscription-$all::{group}-checkpoint", + FromStream.Start, + userCredentials: TestCredentials.Root + ); + + await foreach (var message in subscription.Messages) { + if (message is not StreamMessage.Event(var resolvedEvent)) { + continue; + } + + if (!firstCheckpointSet) { + firstCheckPoint = resolvedEvent.Event.Data.ParsePosition(); + firstCheckpointSet = true; + } else { + secondCheckPoint = resolvedEvent.Event.Data.ParsePosition(); + return; + } + } + } + } + + // [RetryFact] + // public async Task when_writing_and_subscribing_to_normal_events_manual_nack() { + // var group = Fixture.GetGroupName(); + // var bufferCount = 10; + // var eventWriteCount = bufferCount * 2; + // var prefix = $"{Guid.NewGuid():N}-"; + // + // var events = Fixture.CreateTestEvents(eventWriteCount).ToArray(); + // + // await Fixture.Subscriptions.CreateToAllAsync( + // group, + // new(startFrom: Position.Start, resolveLinkTos: true), + // userCredentials: TestCredentials.Root + // ); + // + // var subscription = Fixture.Subscriptions.SubscribeToAll(group, bufferSize: bufferCount, userCredentials: TestCredentials.Root); + // + // foreach (var e in events) + // await Fixture.Streams.AppendToStreamAsync(prefix + Guid.NewGuid(), StreamState.Any, [e]); + // + // await subscription.Messages.OfType() + // .SelectAwait( + // async e => { + // await subscription.Nack(PersistentSubscriptionNakEventAction.Park, "fail", e.ResolvedEvent); + // return e; + // } + // ) + // .Where(e => e.ResolvedEvent.OriginalStreamId.StartsWith(prefix)) + // .Take(events.Length) + // .ToArrayAsync() + // .AsTask() + // .WithTimeout(); + // } + + // [RetryFact] + // public async Task update_existing_with_commit_position_larger_than_last_indexed_position() { + // var group = Fixture.GetGroupName(); + // + // await Fixture.Subscriptions.CreateToAllAsync( + // group, + // new(), + // userCredentials: TestCredentials.Root + // ); + // + // var lastEvent = await Fixture.Streams.ReadAllAsync( + // Direction.Backwards, + // Position.End, + // 1, + // userCredentials: TestCredentials.Root + // ).FirstAsync(); + // + // var lastCommitPosition = lastEvent.OriginalPosition?.CommitPosition ?? throw new(); + // var ex = await Assert.ThrowsAsync( + // () => + // Fixture.Subscriptions.UpdateToAllAsync( + // group, + // new(startFrom: new Position(lastCommitPosition + 1, lastCommitPosition)), + // userCredentials: TestCredentials.Root + // ) + // ); + // + // Assert.Equal(StatusCode.Internal, ex.StatusCode); + // } +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllReplayParkedObsoleteTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllReplayParkedObsoleteTests.cs new file mode 100644 index 000000000..7e1f2366d --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllReplayParkedObsoleteTests.cs @@ -0,0 +1,87 @@ +using EventStore.Client; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllReplayParkedObsoleteTests(ITestOutputHelper output, SubscribeToAllReplayParkedTests.CustomFixture fixture) + : KurrentPermanentTests(output, fixture) { + [RetryFact] + public async Task does_not_throw() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + await Fixture.Subscriptions.ReplayParkedMessagesToAllAsync( + group, + userCredentials: TestCredentials.Root + ); + + await Fixture.Subscriptions.ReplayParkedMessagesToAllAsync( + group, + 100, + userCredentials: TestCredentials.Root + ); + } + + [RetryFact] + public async Task throws_when_given_non_existing_subscription() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + var nonExistingGroup = Fixture.GetGroupName(); + await Assert.ThrowsAsync( + () => + Fixture.Subscriptions.ReplayParkedMessagesToAllAsync( + nonExistingGroup, + userCredentials: TestCredentials.Root + ) + ); + } + + [RetryFact] + public async Task throws_with_no_credentials() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + await Assert.ThrowsAsync( + () => + Fixture.Subscriptions.ReplayParkedMessagesToAllAsync(group) + ); + } + + [RetryFact] + public async Task throws_with_non_existing_user() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + await Assert.ThrowsAsync( + () => + Fixture.Subscriptions.ReplayParkedMessagesToAllAsync( + group, + userCredentials: TestCredentials.TestBadUser + ) + ); + } + + [RetryFact] + public async Task throws_with_normal_user_credentials() { + var user = Fixture.GetUserCredentials(); + + await Fixture.Users + .CreateUserWithRetry(user.Username!, user.Username!, [], user.Password!, TestCredentials.Root) + .WithTimeout(); + + await Assert.ThrowsAsync( + () => + Fixture.Subscriptions.ReplayParkedMessagesToAllAsync( + Fixture.GetGroupName(), + userCredentials: user + ) + ); + } + + public class CustomFixture() : KurrentPermanentFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllResultWithNormalUserCredentialsObsoleteTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllResultWithNormalUserCredentialsObsoleteTests.cs new file mode 100644 index 000000000..e1815bf9b --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllResultWithNormalUserCredentialsObsoleteTests.cs @@ -0,0 +1,35 @@ +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllResultWithNormalUserCredentialsObsoleteTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task returns_result_with_normal_user_credentials() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + const int streamSubscriptionCount = 4; + const int allStreamSubscriptionCount = 3; + + for (var i = 0; i < streamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + for (var i = 0; i < allStreamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToAllAsync( + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + var result = await Fixture.Subscriptions.ListToAllAsync(userCredentials: TestCredentials.Root); + Assert.Equal(allStreamSubscriptionCount, result.Count()); + } +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllReturnsAllSubscriptionsObsoleteTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllReturnsAllSubscriptionsObsoleteTests.cs new file mode 100644 index 000000000..07035b60b --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllReturnsAllSubscriptionsObsoleteTests.cs @@ -0,0 +1,42 @@ +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllReturnsAllSubscriptionsObsoleteTests(ITestOutputHelper output, SubscribeToAllReturnsAllSubscriptions.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task returns_all_subscriptions() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + const int streamSubscriptionCount = 4; + const int allStreamSubscriptionCount = 3; + const int totalSubscriptionCount = streamSubscriptionCount + allStreamSubscriptionCount; + + for (var i = 0; i < streamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + for (var i = 0; i < allStreamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToAllAsync( + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + var result = (await Fixture.Subscriptions.ListAllAsync(userCredentials: TestCredentials.Root)).ToList(); + Assert.Equal(totalSubscriptionCount, result.Count); + } + + public class CustomFixture : KurrentTemporaryFixture { + public CustomFixture() { + SkipPsWarmUp = true; + } + } +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllReturnsSubscriptionsToAllStreamObsoleteTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllReturnsSubscriptionsToAllStreamObsoleteTests.cs new file mode 100644 index 000000000..e0c1f647b --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllReturnsSubscriptionsToAllStreamObsoleteTests.cs @@ -0,0 +1,36 @@ +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllReturnsSubscriptionsToAllStreamObsoleteTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task returns_subscriptions_to_all_stream() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + const int streamSubscriptionCount = 4; + const int allStreamSubscriptionCount = 3; + + for (var i = 0; i < streamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + for (var i = 0; i < allStreamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToAllAsync( + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + var result = (await Fixture.Subscriptions.ListToAllAsync(userCredentials: TestCredentials.Root)).ToList(); + Assert.Equal(allStreamSubscriptionCount, result.Count); + Assert.All(result, s => Assert.Equal("$all", s.EventSource)); + } +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllUpdateExistingWithCheckpointObsoleteTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllUpdateExistingWithCheckpointObsoleteTests.cs new file mode 100644 index 000000000..844b24644 --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllUpdateExistingWithCheckpointObsoleteTests.cs @@ -0,0 +1,88 @@ +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllUpdateExistingWithCheckpointObsoleteTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task update_existing_with_check_point_should_resumes_from_check_point() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + StreamPosition checkPoint = default; + + var events = Fixture.CreateTestEvents(5).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(checkPointLowerBound: 5, checkPointAfter: TimeSpan.FromSeconds(1), startFrom: StreamPosition.Start), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.Root); + + await using var enumerator = subscription.Messages.GetAsyncEnumerator(); + + await enumerator.MoveNextAsync(); + + await Task.WhenAll(Subscribe().WithTimeout(), WaitForCheckpoint().WithTimeout()); + + // Force restart of the subscription + await Fixture.Subscriptions.UpdateToStreamAsync(stream, group, new(), userCredentials: TestCredentials.Root); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, Fixture.CreateTestEvents(1)); + + await using var sub = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.Root); + + var resolvedEvent = await sub.Messages + .OfType() + .Select(e => e.ResolvedEvent) + .FirstAsync() + .AsTask() + .WithTimeout(); + + Assert.Equal(checkPoint.Next(), resolvedEvent.Event.EventNumber); + + return; + + async Task Subscribe() { + var count = 0; + + while (await enumerator.MoveNextAsync()) { + if (enumerator.Current is not PersistentSubscriptionMessage.Event(var resolvedEvent, _)) { + continue; + } + + count++; + + await subscription.Ack(resolvedEvent); + if (count >= events.Length) { + break; + } + } + } + + async Task WaitForCheckpoint() { + await using var subscription = Fixture.Streams.SubscribeToStream( + $"$persistentsubscription-{stream}::{group}-checkpoint", + FromStream.Start, + userCredentials: TestCredentials.Root + ); + + await foreach (var message in subscription.Messages) { + if (message is not StreamMessage.Event (var resolvedEvent)) { + continue; + } + + checkPoint = resolvedEvent.Event.Data.ParseStreamPosition(); + return; + } + } + } +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllWithoutPSObsoleteTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllWithoutPSObsoleteTests.cs new file mode 100644 index 000000000..f676c9cb0 --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/Obsolete/SubscribeToAllWithoutPSObsoleteTests.cs @@ -0,0 +1,17 @@ +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllWithoutPSObsoleteTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task list_without_persistent_subscriptions() { + await Assert.ThrowsAsync( + async () => + await Fixture.Subscriptions.ListToAllAsync(userCredentials: TestCredentials.Root) + ); + } +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllConnectToExistingWithStartFromNotSetTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllConnectToExistingWithStartFromNotSetTests.cs new file mode 100644 index 000000000..d69349f3d --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllConnectToExistingWithStartFromNotSetTests.cs @@ -0,0 +1,33 @@ +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllConnectToExistingWithStartFromNotSetTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task connect_to_existing_with_start_from_not_set() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + foreach (var @event in Fixture.CreateTestEvents(10)) + await Fixture.Streams.AppendToStreamAsync( + stream, + StreamState.Any, + [@event] + ); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + await using var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + await Assert.ThrowsAsync( + () => subscription.Messages + .OfType() + .Where(e => !SystemStreams.IsSystemStream(e.ResolvedEvent.OriginalStreamId)) + .AnyAsync() + .AsTask() + .WithTimeout() + ); + } +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllConnectToExistingWithStartFromSetToEndPositionTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllConnectToExistingWithStartFromSetToEndPositionTests.cs new file mode 100644 index 000000000..effbd67c2 --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllConnectToExistingWithStartFromSetToEndPositionTests.cs @@ -0,0 +1,35 @@ +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllConnectToExistingWithStartFromSetToEndPositionTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task connect_to_existing_with_start_from_set_to_end_position() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + foreach (var @event in Fixture.CreateTestEvents(10)) { + await Fixture.Streams.AppendToStreamAsync( + stream, + StreamState.Any, + [@event] + ); + } + + await Fixture.Subscriptions.CreateToAllAsync(group, new(startFrom: Position.End), userCredentials: TestCredentials.Root); + + var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + await Assert.ThrowsAsync( + () => subscription.Messages + .OfType() + .Where(e => !SystemStreams.IsSystemStream(e.ResolvedEvent.OriginalStreamId)) + .AnyAsync() + .AsTask() + .WithTimeout() + ); + } +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllConnectWithoutReadPermissionsTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllConnectWithoutReadPermissionsTests.cs new file mode 100644 index 000000000..99fa039e5 --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllConnectWithoutReadPermissionsTests.cs @@ -0,0 +1,31 @@ +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllConnectWithoutReadPermissionsTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task connect_to_existing_without_read_all_permissions() { + var group = Fixture.GetGroupName(); + var user = Fixture.GetUserCredentials(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + await Fixture.Users.CreateUserWithRetry( + user.Username!, + user.Username!, + [], + user.Password!, + TestCredentials.Root + ); + + await Assert.ThrowsAsync( + async () => { + await using var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: user); + await subscription.Messages.AnyAsync().AsTask().WithTimeout(); + } + ); + } +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllFilterTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllFilterTests.cs new file mode 100644 index 000000000..3021fb696 --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllFilterTests.cs @@ -0,0 +1,131 @@ +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllFilterTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryTheory] + [MemberData(nameof(FilterCases))] + public async Task happy_case_filtered_reads_all_existing_filtered_events(string filterName) { + var streamPrefix = $"{filterName}-{Fixture.GetStreamName()}"; + var group = Fixture.GetGroupName(); + var (getFilter, prepareEvent) = Filters.GetFilter(filterName); + var filter = getFilter(streamPrefix); + + await Fixture.Streams.AppendToStreamAsync( + Guid.NewGuid().ToString(), + StreamState.NoStream, + Fixture.CreateTestEvents(256) + ); + + await Fixture.Streams.SetStreamMetadataAsync( + SystemStreams.AllStream, + StreamState.Any, + new(acl: new(SystemRoles.All)), + userCredentials: TestCredentials.Root + ); + + var appearedEvents = new List(); + var events = Fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)).ToArray(); + + foreach (var e in events) { + await Fixture.Streams.AppendToStreamAsync( + $"{streamPrefix}_{Guid.NewGuid():n}", + StreamState.NoStream, + [e] + ); + } + + await Fixture.Subscriptions.CreateToAllAsync( + group, + filter, + new(startFrom: Position.Start), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + await subscription.Messages + .OfType() + .Take(events.Length) + .ForEachAwaitAsync( + async e => { + var (resolvedEvent, _) = e; + appearedEvents.Add(resolvedEvent.Event); + await subscription.Ack(resolvedEvent); + } + ) + .WithTimeout(); + + Assert.Equal(events.Select(x => x.EventId), appearedEvents.Select(x => x.EventId)); + } + + [RetryTheory] + [MemberData(nameof(FilterCases))] + public async Task happy_case_filtered_with_start_from_set(string filterName) { + var group = Fixture.GetGroupName(); + var streamPrefix = $"{filterName}-{Fixture.GetStreamName()}"; + var (getFilter, prepareEvent) = Filters.GetFilter(filterName); + var filter = getFilter(streamPrefix); + + var events = Fixture.CreateTestEvents(20).Select(e => prepareEvent(streamPrefix, e)).ToArray(); + var eventsToSkip = events.Take(10).ToArray(); + var eventsToCapture = events.Skip(10).ToArray(); + + IWriteResult? eventToCaptureResult = null; + + await Fixture.Streams.AppendToStreamAsync( + Guid.NewGuid().ToString(), + StreamState.NoStream, + Fixture.CreateTestEvents(256) + ); + + await Fixture.Streams.SetStreamMetadataAsync( + SystemStreams.AllStream, + StreamState.Any, + new(acl: new(SystemRoles.All)), + userCredentials: TestCredentials.Root + ); + + foreach (var e in eventsToSkip) { + await Fixture.Streams.AppendToStreamAsync( + $"{streamPrefix}_{Guid.NewGuid():n}", + StreamState.NoStream, + new[] { e } + ); + } + + foreach (var e in eventsToCapture) { + var result = await Fixture.Streams.AppendToStreamAsync( + $"{streamPrefix}_{Guid.NewGuid():n}", + StreamState.NoStream, + new[] { e } + ); + + eventToCaptureResult ??= result; + } + + await Fixture.Subscriptions.CreateToAllAsync( + group, + filter, + new(startFrom: eventToCaptureResult!.LogPosition), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + var appearedEvents = await subscription.Messages.OfType() + .Take(10) + .Select(e => e.ResolvedEvent.Event) + .ToArrayAsync() + .AsTask() + .WithTimeout(); + + Assert.Equal(eventsToCapture.Select(x => x.EventId), appearedEvents.Select(x => x.EventId)); + } + + public static IEnumerable FilterCases() => Filters.All.Select(filter => new object[] { filter }); +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllGetInfoTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllGetInfoTests.cs new file mode 100644 index 000000000..3b4beb81e --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllGetInfoTests.cs @@ -0,0 +1,102 @@ +// ReSharper disable InconsistentNaming + +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllGetInfoTests(SubscribeToAllGetInfoTests.CustomFixture fixture) + : IClassFixture { + static readonly PersistentSubscriptionSettings Settings = new( + resolveLinkTos: true, + startFrom: Position.Start, + extraStatistics: true, + messageTimeout: TimeSpan.FromSeconds(9), + maxRetryCount: 11, + liveBufferSize: 303, + readBatchSize: 30, + historyBufferSize: 909, + checkPointAfter: TimeSpan.FromSeconds(1), + checkPointLowerBound: 1, + checkPointUpperBound: 1, + maxSubscriberCount: 500, + consumerStrategyName: SystemConsumerStrategies.Pinned + ); + + [RetryFact] + public async Task throws_with_non_existing_subscription() { + var group = $"NonExisting-{fixture.GetGroupName()}"; + + await Assert.ThrowsAsync( + async () => await fixture.Subscriptions.GetInfoToAllAsync(group, userCredentials: TestCredentials.Root) + ); + } + + [RetryFact] + public async Task throws_with_no_credentials() { + var group = $"NonExisting-{fixture.GetGroupName()}"; + + await Assert.ThrowsAsync( + async () => + await fixture.Subscriptions.GetInfoToAllAsync(group) + ); + } + + [RetryFact] + public async Task throws_with_non_existing_user() { + var group = $"NonExisting-{fixture.GetGroupName()}"; + + await Assert.ThrowsAsync( + async () => + await fixture.Subscriptions.GetInfoToAllAsync(group, userCredentials: TestCredentials.TestBadUser) + ); + } + + [RetryFact] + public async Task returns_result_with_normal_user_credentials() { + var result = await fixture.Subscriptions.GetInfoToAllAsync(fixture.Group, userCredentials: TestCredentials.Root); + + Assert.Equal("$all", result.EventSource); + } + + public class CustomFixture : KurrentTemporaryFixture { + public string Group { get; } + + public CustomFixture() : base(x => x.WithoutDefaultCredentials()) { + Group = GetGroupName(); + + OnSetup += async () => { + await Subscriptions.CreateToAllAsync(Group, Settings, userCredentials: TestCredentials.Root); + + foreach (var eventData in CreateTestEvents(20)) { + await Streams.AppendToStreamAsync( + $"test-{Guid.NewGuid():n}", + StreamState.NoStream, + [eventData], + userCredentials: TestCredentials.Root + ); + } + + var counter = 0; + + await using var subscription = Subscriptions.SubscribeToAll(Group, userCredentials: TestCredentials.Root); + + var enumerator = subscription.Messages.GetAsyncEnumerator(); + + while (await enumerator.MoveNextAsync()) { + if (enumerator.Current is not PersistentSubscriptionMessage.Event (var resolvedEvent, _)) + continue; + + counter++; + + if (counter == 1) + await subscription.Nack(PersistentSubscriptionNakEventAction.Park, "Test", resolvedEvent); + + if (counter > 10) + return; + } + }; + } + }; +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllListWithIncorrectCredentialsTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllListWithIncorrectCredentialsTests.cs new file mode 100644 index 000000000..aa3957ed0 --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllListWithIncorrectCredentialsTests.cs @@ -0,0 +1,64 @@ +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllListWithIncorrectCredentialsTests(ITestOutputHelper output, SubscribeToAllListWithIncorrectCredentialsTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task throws_with_no_credentials() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + const int streamSubscriptionCount = 4; + const int allStreamSubscriptionCount = 3; + + for (var i = 0; i < streamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + for (var i = 0; i < allStreamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToAllAsync( + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + await Assert.ThrowsAsync(async () => await Fixture.Subscriptions.ListToAllAsync()); + } + + [RetryFact] + public async Task throws_with_non_existing_user() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + const int streamSubscriptionCount = 4; + const int allStreamSubscriptionCount = 3; + + for (var i = 0; i < streamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + for (var i = 0; i < allStreamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToAllAsync( + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + await Assert.ThrowsAsync( + async () => await Fixture.Subscriptions.ListToAllAsync(userCredentials: TestCredentials.TestBadUser) + ); + } + + public class CustomFixture() : KurrentTemporaryFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllNoDefaultCredentialsTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllNoDefaultCredentialsTests.cs new file mode 100644 index 000000000..49e8cfa30 --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllNoDefaultCredentialsTests.cs @@ -0,0 +1,96 @@ +using EventStore.Client; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllNoDefaultCredentialsTests(ITestOutputHelper output, SubscribeToAllNoDefaultCredentialsTests.CustomFixture fixture) + : KurrentPermanentTests(output, fixture) { + [RetryFact] + public async Task connect_to_existing_without_permissions() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + await Assert.ThrowsAsync( + async () => { + await using var subscription = Fixture.Subscriptions.SubscribeToAll(group); + await subscription.AnyAsync().AsTask().WithTimeout(); + } + ); + } + + [RetryFact] + public async Task throws_persistent_subscription_not_found() { + var group = Fixture.GetGroupName(); + + await using var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + Assert.True( + await subscription.Messages.OfType().AnyAsync() + .AsTask() + .WithTimeout() + ); + } + + [RetryFact] + public async Task deleting_without_permissions() { + await Assert.ThrowsAsync(() => Fixture.Subscriptions.DeleteToAllAsync(Guid.NewGuid().ToString())); + } + + [RetryFact] + public async Task create_without_permissions() { + var group = Fixture.GetGroupName(); + + await Assert.ThrowsAsync( + () => + Fixture.Subscriptions.CreateToAllAsync( + group, + new() + ) + ); + } + + [RetryFact] + public async Task update_existing_without_permissions() { + var group = Fixture.GetGroupName(); + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(), + userCredentials: TestCredentials.Root + ); + + await Assert.ThrowsAsync( + () => Fixture.Subscriptions.UpdateToAllAsync( + group, + new() + ) + ); + } + + [RetryFact] + public async Task update_non_existent() { + var group = Fixture.GetGroupName(); + await Assert.ThrowsAsync( + () => Fixture.Subscriptions.UpdateToAllAsync( + group, + new(), + userCredentials: TestCredentials.Root + ) + ); + } + + [RetryFact] + public Task update_with_prepare_position_larger_than_commit_position() { + var group = Fixture.GetGroupName(); + return Assert.ThrowsAsync( + () => + Fixture.Subscriptions.UpdateToAllAsync( + group, + new(startFrom: new Position(0, 1)), + userCredentials: TestCredentials.Root + ) + ); + } + + public class CustomFixture() : KurrentPermanentFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllReplayParkedTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllReplayParkedTests.cs new file mode 100644 index 000000000..f2eacb3e7 --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllReplayParkedTests.cs @@ -0,0 +1,87 @@ +using EventStore.Client; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllReplayParkedTests(ITestOutputHelper output, SubscribeToAllReplayParkedTests.CustomFixture fixture) + : KurrentPermanentTests(output, fixture) { + [RetryFact] + public async Task does_not_throw() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + await Fixture.Subscriptions.ReplayParkedMessagesToAllAsync( + group, + userCredentials: TestCredentials.Root + ); + + await Fixture.Subscriptions.ReplayParkedMessagesToAllAsync( + group, + 100, + userCredentials: TestCredentials.Root + ); + } + + [RetryFact] + public async Task throws_when_given_non_existing_subscription() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + var nonExistingGroup = Fixture.GetGroupName(); + await Assert.ThrowsAsync( + () => + Fixture.Subscriptions.ReplayParkedMessagesToAllAsync( + nonExistingGroup, + userCredentials: TestCredentials.Root + ) + ); + } + + [RetryFact] + public async Task throws_with_no_credentials() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + await Assert.ThrowsAsync( + () => + Fixture.Subscriptions.ReplayParkedMessagesToAllAsync(group) + ); + } + + [RetryFact] + public async Task throws_with_non_existing_user() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + await Assert.ThrowsAsync( + () => + Fixture.Subscriptions.ReplayParkedMessagesToAllAsync( + group, + userCredentials: TestCredentials.TestBadUser + ) + ); + } + + [RetryFact] + public async Task throws_with_normal_user_credentials() { + var user = Fixture.GetUserCredentials(); + + await Fixture.Users + .CreateUserWithRetry(user.Username!, user.Username!, [], user.Password!, TestCredentials.Root) + .WithTimeout(); + + await Assert.ThrowsAsync( + () => + Fixture.Subscriptions.ReplayParkedMessagesToAllAsync( + Fixture.GetGroupName(), + userCredentials: user + ) + ); + } + + public class CustomFixture() : KurrentPermanentFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllResultWithNormalUserCredentialsTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllResultWithNormalUserCredentialsTests.cs new file mode 100644 index 000000000..627a3bc19 --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllResultWithNormalUserCredentialsTests.cs @@ -0,0 +1,35 @@ +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllResultWithNormalUserCredentialsTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task returns_result_with_normal_user_credentials() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + const int streamSubscriptionCount = 4; + const int allStreamSubscriptionCount = 3; + + for (var i = 0; i < streamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + for (var i = 0; i < allStreamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToAllAsync( + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + var result = await Fixture.Subscriptions.ListToAllAsync(userCredentials: TestCredentials.Root); + Assert.Equal(allStreamSubscriptionCount, result.Count()); + } +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllReturnsAllSubscriptions.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllReturnsAllSubscriptions.cs new file mode 100644 index 000000000..148607b83 --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllReturnsAllSubscriptions.cs @@ -0,0 +1,42 @@ +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllReturnsAllSubscriptions(ITestOutputHelper output, SubscribeToAllReturnsAllSubscriptions.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task returns_all_subscriptions() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + const int streamSubscriptionCount = 4; + const int allStreamSubscriptionCount = 3; + const int totalSubscriptionCount = streamSubscriptionCount + allStreamSubscriptionCount; + + for (var i = 0; i < streamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + for (var i = 0; i < allStreamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToAllAsync( + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + var result = (await Fixture.Subscriptions.ListAllAsync(userCredentials: TestCredentials.Root)).ToList(); + Assert.Equal(totalSubscriptionCount, result.Count); + } + + public class CustomFixture : KurrentTemporaryFixture { + public CustomFixture() { + SkipPsWarmUp = true; + } + } +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllReturnsSubscriptionsToAllStreamTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllReturnsSubscriptionsToAllStreamTests.cs new file mode 100644 index 000000000..07498fc28 --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllReturnsSubscriptionsToAllStreamTests.cs @@ -0,0 +1,36 @@ +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllReturnsSubscriptionsToAllStreamTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task returns_subscriptions_to_all_stream() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + const int streamSubscriptionCount = 4; + const int allStreamSubscriptionCount = 3; + + for (var i = 0; i < streamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + for (var i = 0; i < allStreamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToAllAsync( + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + var result = (await Fixture.Subscriptions.ListToAllAsync(userCredentials: TestCredentials.Root)).ToList(); + Assert.Equal(allStreamSubscriptionCount, result.Count); + Assert.All(result, s => Assert.Equal("$all", s.EventSource)); + } +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllTests.cs new file mode 100644 index 000000000..e7e67f51f --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllTests.cs @@ -0,0 +1,853 @@ +using System.Text; +using EventStore.Client; +using Grpc.Core; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllTests(ITestOutputHelper output, KurrentPermanentFixture fixture) + : KurrentPermanentTests(output, fixture) { + [RetryFact] + public async Task can_create_duplicate_name_on_different_streams() { + // Arrange + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + // Act + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(), + userCredentials: TestCredentials.Root + ); + + await Fixture.Subscriptions.CreateToStreamAsync(stream, group, new(), userCredentials: TestCredentials.Root); + } + + [RetryFact] + public async Task connect_to_existing_with_max_one_client() { + // Arrange + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(maxSubscriberCount: 1), userCredentials: TestCredentials.Root); + + var ex = await Assert.ThrowsAsync(() => Task.WhenAll(Subscribe().WithTimeout(), Subscribe().WithTimeout())); + + Assert.Equal(SystemStreams.AllStream, ex.StreamName); + Assert.Equal(group, ex.GroupName); + return; + + async Task Subscribe() { + await using var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + await subscription.Messages.AnyAsync(); + } + } + + [RetryFact] + public async Task connect_to_existing_with_permissions() { + // Arrange + var group = Fixture.GetGroupName(); + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + // Act + await using var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + // Assert + subscription.Messages + .FirstAsync().AsTask().WithTimeout() + .GetAwaiter().GetResult() + .ShouldBeOfType(); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_beginning() { + var group = Fixture.GetGroupName(); + + // append 10 events to random streams to make sure we have at least 10 events in the transaction file + foreach (var @event in Fixture.CreateTestEvents(10)) { + await Fixture.Streams.AppendToStreamAsync( + Guid.NewGuid().ToString(), + StreamState.NoStream, + [@event] + ); + } + + var events = await Fixture.Streams + .ReadAllAsync(Direction.Forwards, Position.Start, 10, userCredentials: TestCredentials.Root) + .ToArrayAsync(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(startFrom: Position.Start), userCredentials: TestCredentials.Root); + + var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + var resolvedEvent = await subscription.Messages.OfType() + .Select(e => e.ResolvedEvent) + .FirstOrDefaultAsync().AsTask().WithTimeout(); + + Assert.Equal(events[0].Event.EventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_not_set_then_event_written() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + var expectedStreamId = Guid.NewGuid().ToString(); + var expectedEvent = Fixture.CreateTestEvents(1).First(); + + foreach (var @event in Fixture.CreateTestEvents(10)) { + await Fixture.Streams.AppendToStreamAsync( + stream, + StreamState.Any, + [@event] + ); + } + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + await Fixture.Streams.AppendToStreamAsync(expectedStreamId, StreamState.NoStream, [expectedEvent]); + + var resolvedEvent = await subscription!.Messages.OfType() + .Select(e => e.ResolvedEvent) + .Where(resolvedEvent => !SystemStreams.IsSystemStream(resolvedEvent.OriginalStreamId)) + .FirstOrDefaultAsync().AsTask().WithTimeout(); + + Assert.Equal(expectedEvent.EventId, resolvedEvent.Event.EventId); + Assert.Equal(expectedStreamId, resolvedEvent.Event.EventStreamId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_set_to_end_position_then_event_written() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + var expectedStreamId = Fixture.GetStreamName(); + var expectedEvent = Fixture.CreateTestEvents().First(); + + foreach (var @event in Fixture.CreateTestEvents(10)) { + await Fixture.Streams.AppendToStreamAsync( + stream, + StreamState.Any, + [@event] + ); + } + + await Fixture.Subscriptions.CreateToAllAsync(group, new(startFrom: Position.End), userCredentials: TestCredentials.Root); + var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + await Fixture.Streams.AppendToStreamAsync(expectedStreamId, StreamState.NoStream, [expectedEvent]); + + var resolvedEvent = await subscription!.Messages + .OfType() + .Select(e => e.ResolvedEvent) + .Where(resolvedEvent => !SystemStreams.IsSystemStream(resolvedEvent.OriginalStreamId)) + .FirstAsync() + .AsTask() + .WithTimeout(); + + Assert.Equal(expectedEvent.EventId, resolvedEvent.Event.EventId); + Assert.Equal(expectedStreamId, resolvedEvent.Event.EventStreamId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_set_to_invalid_middle_position() { + var group = Fixture.GetGroupName(); + + var invalidPosition = new Position(1L, 1L); + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(startFrom: invalidPosition), + userCredentials: TestCredentials.Root + ); + + var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + var enumerator = subscription.Messages.GetAsyncEnumerator(); + + await enumerator.MoveNextAsync(); + var ex = await Assert.ThrowsAsync( + async () => + await enumerator!.MoveNextAsync() + ); + + Assert.Equal(SystemStreams.AllStream, ex.StreamName); + Assert.Equal(group, ex.GroupName); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_set_to_valid_middle_position() { + var group = Fixture.GetGroupName(); + + var events = await Fixture.Streams + .ReadAllAsync(Direction.Forwards, Position.Start, 10, userCredentials: TestCredentials.Root) + .ToArrayAsync(); + + var expectedEvent = events[events.Length / 2]; //just a random event in the middle of the results + + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(startFrom: expectedEvent.OriginalPosition), + userCredentials: TestCredentials.Root + ); + + var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + var resolvedEvent = await subscription!.Messages.OfType() + .Select(e => e.ResolvedEvent) + .FirstAsync() + .AsTask() + .WithTimeout(); + + Assert.Equal(expectedEvent.OriginalPosition, resolvedEvent.Event.Position); + Assert.Equal(expectedEvent.Event.EventId, resolvedEvent.Event.EventId); + Assert.Equal(expectedEvent.Event.EventStreamId, resolvedEvent.Event.EventStreamId); + } + + [RetryFact] + public async Task connect_with_retries() { + // Arrange + var group = Fixture.GetGroupName(); + await Fixture.Subscriptions.CreateToAllAsync(group, new(startFrom: Position.Start), userCredentials: TestCredentials.Root); + + // Act + var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + var retryCount = await subscription.Messages.OfType() + .SelectAwait( + async e => { + if (e.RetryCount > 4) { + await subscription.Ack(e.ResolvedEvent); + } else { + await subscription.Nack( + PersistentSubscriptionNakEventAction.Retry, + "Not yet tried enough times", + e.ResolvedEvent + ); + } + + return e.RetryCount; + } + ) + .Where(retryCount => retryCount > 4) + .FirstOrDefaultAsync() + .AsTask() + .WithTimeout(); + + // Assert + retryCount.ShouldBe(5); + } + + [RetryFact] + public async Task create_after_deleting_the_same() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + await Fixture.Subscriptions.DeleteToAllAsync(group, userCredentials: TestCredentials.Root); + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + } + + [RetryFact] + public async Task create_duplicate() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(), + userCredentials: TestCredentials.Root + ); + + var ex = await Assert.ThrowsAsync( + () => Fixture.Subscriptions.CreateToAllAsync( + group, + new(), + userCredentials: TestCredentials.Root + ) + ); + + ex.StatusCode.ShouldBe(StatusCode.AlreadyExists); + } + + [RetryFact] + public async Task create_with_commit_position_equal_to_last_indexed_position() { + // Arrange + var group = Fixture.GetGroupName(); + + // Act + var lastEvent = await Fixture.Streams.ReadAllAsync( + Direction.Backwards, + Position.End, + 1, + userCredentials: TestCredentials.Root + ).FirstAsync(); + + var lastCommitPosition = lastEvent.OriginalPosition?.CommitPosition ?? throw new(); + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(startFrom: new Position(lastCommitPosition, lastCommitPosition)), + userCredentials: TestCredentials.Root + ); + } + + [RetryFact] + public Task create_with_prepare_position_larger_than_commit_position() { + var group = Fixture.GetGroupName(); + + return Assert.ThrowsAsync( + () => + Fixture.Subscriptions.CreateToAllAsync( + group, + new(startFrom: new Position(0, 1)), + userCredentials: TestCredentials.Root + ) + ); + } + + [RetryFact] + public async Task deleting_existing_with_subscriber() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + await Fixture.Subscriptions.DeleteToAllAsync(group, userCredentials: TestCredentials.Root); + + await using var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + Assert.True( + await subscription.Messages.OfType().AnyAsync() + .AsTask() + .WithTimeout() + ); + } + + [RetryFact] + public async Task deleting_existing_with_permissions() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(), + userCredentials: TestCredentials.Root + ); + + await Fixture.Subscriptions.DeleteToAllAsync( + group, + userCredentials: TestCredentials.Root + ); + } + + [RetryFact] + public async Task deleting_filtered() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync( + group, + EventTypeFilter.Prefix("prefix-filter-"), + new(), + userCredentials: TestCredentials.Root + ); + + await Fixture.Subscriptions.DeleteToAllAsync(group, userCredentials: TestCredentials.Root); + } + + [RetryFact] + public async Task deleting_nonexistent() { + await Assert.ThrowsAsync( + () => Fixture.Subscriptions.DeleteToAllAsync(Guid.NewGuid().ToString(), userCredentials: TestCredentials.Root) + ); + } + + [RetryFact] + public async Task happy_case_catching_up_to_link_to_events_manual_ack() { + var group = Fixture.GetGroupName(); + var bufferCount = 10; + var eventWriteCount = bufferCount * 2; + + var events = Fixture.CreateTestEvents(eventWriteCount) + .Select( + (e, i) => new EventData( + e.EventId, + SystemEventTypes.LinkTo, + Encoding.UTF8.GetBytes($"{i}@test"), + contentType: Constants.Metadata.ContentTypes.ApplicationOctetStream + ) + ) + .ToArray(); + + foreach (var e in events) { + await Fixture.Streams.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); + } + + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(startFrom: Position.Start, resolveLinkTos: true), + userCredentials: TestCredentials.Root + ); + + var subscription = Fixture.Subscriptions.SubscribeToAll(group, bufferSize: bufferCount, userCredentials: TestCredentials.Root); + await subscription.Messages.OfType() + .Take(events.Length) + .ForEachAwaitAsync(e => subscription.Ack(e.ResolvedEvent)) + .WithTimeout(); + } + + [RetryFact] + public async Task happy_case_catching_up_to_normal_events_manual_ack() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + var bufferCount = 10; + var eventWriteCount = bufferCount * 2; + + var events = Fixture.CreateTestEvents(eventWriteCount).ToArray(); + + foreach (var e in events) + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, [e]); + + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(startFrom: Position.Start, resolveLinkTos: true), + userCredentials: TestCredentials.Root + ); + + var subscription = Fixture.Subscriptions.SubscribeToAll(group, bufferSize: bufferCount, userCredentials: TestCredentials.Root); + await subscription!.Messages.OfType() + .Take(events.Length) + .ForEachAwaitAsync(e => subscription.Ack(e.ResolvedEvent)) + .WithTimeout(); + } + + [RetryFact] + public async Task happy_case_writing_and_subscribing_to_normal_events_manual_ack() { + var group = Fixture.GetGroupName(); + var bufferCount = 10; + var eventWriteCount = bufferCount * 2; + + var events = Fixture.CreateTestEvents(eventWriteCount).ToArray(); + + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(startFrom: Position.End, resolveLinkTos: true), + userCredentials: TestCredentials.Root + ); + + var subscription = Fixture.Subscriptions.SubscribeToAll(group, bufferSize: bufferCount, userCredentials: TestCredentials.Root); + foreach (var e in events) { + await Fixture.Streams.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, new[] { e }); + } + + await subscription!.Messages.OfType() + .SelectAwait( + async e => { + await subscription.Ack(e.ResolvedEvent); + return e; + } + ) + .Where(e => e.ResolvedEvent.OriginalStreamId.StartsWith("test-")) + .Take(events.Length) + .ToArrayAsync() + .AsTask() + .WithTimeout(); + } + + [RetryFact] + public async Task update_existing() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(), + userCredentials: TestCredentials.Root + ); + + await Fixture.Subscriptions.UpdateToAllAsync( + group, + new(), + userCredentials: TestCredentials.Root + ); + } + + [RetryFact] + public async Task update_existing_filtered() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync( + group, + EventTypeFilter.Prefix("prefix-filter-"), + new(), + userCredentials: TestCredentials.Root + ); + + await Fixture.Subscriptions.UpdateToAllAsync( + group, + new(true), + userCredentials: TestCredentials.Root + ); + } + + [RetryFact] + public async Task update_existing_with_check_point() { + var group = Fixture.GetGroupName(); + var events = Fixture.CreateTestEvents(5).ToArray(); + var appearedEvents = new List(); + Position checkPoint = default; + + foreach (var e in events) + await Fixture.Streams.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.Any, [e]); + + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(checkPointLowerBound: 5, checkPointAfter: TimeSpan.FromSeconds(1), startFrom: Position.Start), + userCredentials: TestCredentials.Root + ); + + var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + var enumerator = subscription.Messages.GetAsyncEnumerator(); + await enumerator.MoveNextAsync(); + + await Task.WhenAll(Subscribe().WithTimeout(), WaitForCheckpoint().WithTimeout()); + + // Force restart of the subscription + await Fixture.Subscriptions.UpdateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + try { + while (await enumerator!.MoveNextAsync()) { } + } catch (PersistentSubscriptionDroppedByServerException) { } + + foreach (var e in events) { + await Fixture.Streams.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.NoStream, new[] { e }); + } + + await using var sub = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + var resumed = await sub.Messages.OfType() + .Select(e => e.ResolvedEvent) + .Take(1) + .FirstAsync() + .AsTask() + .WithTimeout(); + + Assert.True(resumed.Event.Position > checkPoint); + + return; + + async Task Subscribe() { + while (await enumerator.MoveNextAsync()) { + if (enumerator.Current is not PersistentSubscriptionMessage.Event(var resolvedEvent, _)) { + continue; + } + + appearedEvents.Add(resolvedEvent); + await subscription.Ack(resolvedEvent); + if (appearedEvents.Count == events.Length) { + break; + } + } + } + + async Task WaitForCheckpoint() { + await using var subscription = Fixture.Streams.SubscribeToStream( + $"$persistentsubscription-$all::{group}-checkpoint", + FromStream.Start, + userCredentials: TestCredentials.Root + ); + + await foreach (var message in subscription.Messages) { + if (message is not StreamMessage.Event(var resolvedEvent)) { + continue; + } + + checkPoint = resolvedEvent.Event.Data.ParsePosition(); + return; + } + } + } + + [RetryFact] + public async Task update_existing_with_check_point_filtered() { + List appearedEvents = []; + var events = Fixture.CreateTestEvents(5).ToArray(); + var group = Fixture.GetGroupName(); + Position checkPoint = default; + + foreach (var e in events) { + await Fixture.Streams.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.NoStream, [e]); + } + + await Fixture.Subscriptions.CreateToAllAsync( + group, + StreamFilter.Prefix("test"), + new(checkPointLowerBound: 5, checkPointAfter: TimeSpan.FromSeconds(1), startFrom: Position.Start), + userCredentials: TestCredentials.Root + ); + + var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + var enumerator = subscription.Messages.GetAsyncEnumerator(); + await enumerator.MoveNextAsync(); + + await Task.WhenAll(Subscribe().WithTimeout(), WaitForCheckpoint().WithTimeout()); + + // Force restart of the subscription + await Fixture.Subscriptions.UpdateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + + try { + while (await enumerator.MoveNextAsync()) { } + } catch (PersistentSubscriptionDroppedByServerException) { } + + foreach (var e in events) { + await Fixture.Streams.AppendToStreamAsync("test-" + Guid.NewGuid(), StreamState.NoStream, [e]); + } + + await using var sub = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + var resumed = await sub.Messages.OfType() + .Select(e => e.ResolvedEvent) + .Take(1) + .FirstAsync() + .AsTask() + .WithTimeout(); + + Assert.True(resumed.Event.Position > checkPoint); + + return; + + async Task Subscribe() { + while (await enumerator.MoveNextAsync()) { + if (enumerator.Current is not PersistentSubscriptionMessage.Event(var resolvedEvent, _)) { + continue; + } + + appearedEvents.Add(resolvedEvent); + await subscription.Ack(resolvedEvent); + if (appearedEvents.Count == events.Length) { + break; + } + } + } + + async Task WaitForCheckpoint() { + await using var subscription = Fixture.Streams.SubscribeToStream( + $"$persistentsubscription-$all::{group}-checkpoint", + FromStream.Start, + userCredentials: TestCredentials.Root + ); + + await foreach (var message in subscription.Messages) { + if (message is not StreamMessage.Event(var resolvedEvent)) { + continue; + } + + checkPoint = resolvedEvent.Event.Data.ParsePosition(); + return; + } + } + } + + [RetryFact] + public async Task update_existing_with_commit_position_equal_to_last_indexed_position() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync( + group, + new(), + userCredentials: TestCredentials.Root + ); + + var lastEvent = await Fixture.Streams.ReadAllAsync( + Direction.Backwards, + Position.End, + 1, + userCredentials: TestCredentials.Root + ).FirstAsync(); + + var lastCommitPosition = lastEvent.OriginalPosition?.CommitPosition ?? throw new(); + await Fixture.Subscriptions.UpdateToAllAsync( + group, + new(startFrom: new Position(lastCommitPosition, lastCommitPosition)), + userCredentials: TestCredentials.Root + ); + } + + [RetryFact] + public async Task update_existing_with_subscribers() { + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToAllAsync(group, new(startFrom: Position.Start), userCredentials: TestCredentials.Root); + + var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + + var enumerator = subscription.Messages.GetAsyncEnumerator(); + + await enumerator.MoveNextAsync(); + await Fixture.Subscriptions.UpdateToAllAsync(group, new(), userCredentials: TestCredentials.Root); + var ex = await Assert.ThrowsAsync( + async () => { + while (await enumerator.MoveNextAsync()) { } + } + ).WithTimeout(); + + Assert.Equal(SystemStreams.AllStream, ex.StreamName); + Assert.Equal(group, ex.GroupName); + } + + [RetryFact] + public async Task when_writing_and_filtering_out_events() { + var events = Fixture.CreateTestEvents(10).ToArray(); + var group = Fixture.GetGroupName(); + var prefix = Guid.NewGuid().ToString("N"); + + Position firstCheckPoint = default; + Position secondCheckPoint = default; + List appearedEvents = []; + + foreach (var e in events) + await Fixture.Streams.AppendToStreamAsync(prefix + Guid.NewGuid(), StreamState.Any, [e]); + + await Fixture.Subscriptions.CreateToAllAsync( + group, + StreamFilter.Prefix(prefix), + new( + checkPointLowerBound: 1, + checkPointUpperBound: 5, + checkPointAfter: TimeSpan.FromSeconds(1), + startFrom: Position.Start + ), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToAll(group, userCredentials: TestCredentials.Root); + await using var enumerator = subscription.Messages.GetAsyncEnumerator(); + + await Task.WhenAll(Subscribe().WithTimeout(), WaitForCheckpoints().WithTimeout()); + + foreach (var e in events) { + await Fixture.Streams.AppendToStreamAsync( + "filtered-out-stream-" + Guid.NewGuid(), + StreamState.Any, + [e] + ); + } + + Assert.True(secondCheckPoint > firstCheckPoint); + Assert.Equal(events.Select(e => e.EventId), appearedEvents.Select(e => e.Event.EventId)); + + return; + + async Task Subscribe() { + while (await enumerator.MoveNextAsync()) { + if (enumerator.Current is not PersistentSubscriptionMessage.Event(var resolvedEvent, _)) { + continue; + } + + appearedEvents.Add(resolvedEvent); + await subscription.Ack(resolvedEvent); + if (appearedEvents.Count == events.Length) { + break; + } + } + } + + async Task WaitForCheckpoints() { + bool firstCheckpointSet = false; + await using var subscription = Fixture.Streams.SubscribeToStream( + $"$persistentsubscription-$all::{group}-checkpoint", + FromStream.Start, + userCredentials: TestCredentials.Root + ); + + await foreach (var message in subscription.Messages) { + if (message is not StreamMessage.Event(var resolvedEvent)) { + continue; + } + + if (!firstCheckpointSet) { + firstCheckPoint = resolvedEvent.Event.Data.ParsePosition(); + firstCheckpointSet = true; + } else { + secondCheckPoint = resolvedEvent.Event.Data.ParsePosition(); + return; + } + } + } + } + + // [RetryFact] + // public async Task when_writing_and_subscribing_to_normal_events_manual_nack() { + // var group = Fixture.GetGroupName(); + // var bufferCount = 10; + // var eventWriteCount = bufferCount * 2; + // var prefix = $"{Guid.NewGuid():N}-"; + // + // var events = Fixture.CreateTestEvents(eventWriteCount).ToArray(); + // + // await Fixture.Subscriptions.CreateToAllAsync( + // group, + // new(startFrom: Position.Start, resolveLinkTos: true), + // userCredentials: TestCredentials.Root + // ); + // + // var subscription = Fixture.Subscriptions.SubscribeToAll(group, bufferSize: bufferCount, userCredentials: TestCredentials.Root); + // + // foreach (var e in events) + // await Fixture.Streams.AppendToStreamAsync(prefix + Guid.NewGuid(), StreamState.Any, [e]); + // + // await subscription.Messages.OfType() + // .SelectAwait( + // async e => { + // await subscription.Nack(PersistentSubscriptionNakEventAction.Park, "fail", e.ResolvedEvent); + // return e; + // } + // ) + // .Where(e => e.ResolvedEvent.OriginalStreamId.StartsWith(prefix)) + // .Take(events.Length) + // .ToArrayAsync() + // .AsTask() + // .WithTimeout(); + // } + + // [RetryFact] + // public async Task update_existing_with_commit_position_larger_than_last_indexed_position() { + // var group = Fixture.GetGroupName(); + // + // await Fixture.Subscriptions.CreateToAllAsync( + // group, + // new(), + // userCredentials: TestCredentials.Root + // ); + // + // var lastEvent = await Fixture.Streams.ReadAllAsync( + // Direction.Backwards, + // Position.End, + // 1, + // userCredentials: TestCredentials.Root + // ).FirstAsync(); + // + // var lastCommitPosition = lastEvent.OriginalPosition?.CommitPosition ?? throw new(); + // var ex = await Assert.ThrowsAsync( + // () => + // Fixture.Subscriptions.UpdateToAllAsync( + // group, + // new(startFrom: new Position(lastCommitPosition + 1, lastCommitPosition)), + // userCredentials: TestCredentials.Root + // ) + // ); + // + // Assert.Equal(StatusCode.Internal, ex.StatusCode); + // } + + [RetryFact] + public async Task create_with_commit_position_larger_than_last_indexed_position() { + var group = Fixture.GetGroupName(); + + var lastEvent = await Fixture.Streams.ReadAllAsync( + Direction.Backwards, + Position.End, + 1, + userCredentials: TestCredentials.Root + ).FirstAsync(); + + var lastCommitPosition = lastEvent.OriginalPosition?.CommitPosition ?? throw new(); + var ex = await Assert.ThrowsAsync( + () => + Fixture.Subscriptions.CreateToAllAsync( + group, + new(startFrom: new Position(lastCommitPosition + 1, lastCommitPosition)), + userCredentials: TestCredentials.Root + ) + ); + + Assert.Equal(StatusCode.Internal, ex.StatusCode); + } +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllUpdateExistingWithCheckpointTest.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllUpdateExistingWithCheckpointTest.cs new file mode 100644 index 000000000..0a0ae75f4 --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllUpdateExistingWithCheckpointTest.cs @@ -0,0 +1,88 @@ +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllUpdateExistingWithCheckpointTest(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task update_existing_with_check_point_should_resumes_from_check_point() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + StreamPosition checkPoint = default; + + var events = Fixture.CreateTestEvents(5).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(checkPointLowerBound: 5, checkPointAfter: TimeSpan.FromSeconds(1), startFrom: StreamPosition.Start), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.Root); + + await using var enumerator = subscription.Messages.GetAsyncEnumerator(); + + await enumerator.MoveNextAsync(); + + await Task.WhenAll(Subscribe().WithTimeout(), WaitForCheckpoint().WithTimeout()); + + // Force restart of the subscription + await Fixture.Subscriptions.UpdateToStreamAsync(stream, group, new(), userCredentials: TestCredentials.Root); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, Fixture.CreateTestEvents(1)); + + await using var sub = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.Root); + + var resolvedEvent = await sub.Messages + .OfType() + .Select(e => e.ResolvedEvent) + .FirstAsync() + .AsTask() + .WithTimeout(); + + Assert.Equal(checkPoint.Next(), resolvedEvent.Event.EventNumber); + + return; + + async Task Subscribe() { + var count = 0; + + while (await enumerator.MoveNextAsync()) { + if (enumerator.Current is not PersistentSubscriptionMessage.Event(var resolvedEvent, _)) { + continue; + } + + count++; + + await subscription.Ack(resolvedEvent); + if (count >= events.Length) { + break; + } + } + } + + async Task WaitForCheckpoint() { + await using var subscription = Fixture.Streams.SubscribeToStream( + $"$persistentsubscription-{stream}::{group}-checkpoint", + FromStream.Start, + userCredentials: TestCredentials.Root + ); + + await foreach (var message in subscription.Messages) { + if (message is not StreamMessage.Event (var resolvedEvent)) { + continue; + } + + checkPoint = resolvedEvent.Event.Data.ParseStreamPosition(); + return; + } + } + } +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllWithoutPSTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllWithoutPSTests.cs new file mode 100644 index 000000000..237ca1f2b --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToAll/SubscribeToAllWithoutPSTests.cs @@ -0,0 +1,17 @@ +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToAllWithoutPsTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task list_without_persistent_subscriptions() { + await Assert.ThrowsAsync( + async () => + await Fixture.Subscriptions.ListToAllAsync(userCredentials: TestCredentials.Root) + ); + } +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/Obsolete/SubscribeToStreamConnectToExistingWithoutPermissionObsoleteTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/Obsolete/SubscribeToStreamConnectToExistingWithoutPermissionObsoleteTests.cs new file mode 100644 index 000000000..fa2ca1a32 --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/Obsolete/SubscribeToStreamConnectToExistingWithoutPermissionObsoleteTests.cs @@ -0,0 +1,36 @@ +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToStreamConnectToExistingWithoutPermissionObsoleteTests( + ITestOutputHelper output, + SubscribeToStreamConnectToExistingWithoutPermissionObsoleteTests.CustomFixture fixture +) + : KurrentTemporaryTests(output, fixture) { + [Fact] + public async Task connect_to_existing_without_permissions() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + await Assert.ThrowsAsync( + async () => { + using var _ = await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + delegate { return Task.CompletedTask; } + ); + } + ).WithTimeout(); + } + + public class CustomFixture() : KurrentTemporaryFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/get_info_obsolete.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/Obsolete/SubscribeToStreamGetInfoObsoleteTests.cs similarity index 55% rename from test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/get_info_obsolete.cs rename to test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/Obsolete/SubscribeToStreamGetInfoObsoleteTests.cs index 6f42531fa..5381dc013 100644 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToAll/Obsolete/get_info_obsolete.cs +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/Obsolete/SubscribeToStreamGetInfoObsoleteTests.cs @@ -1,51 +1,46 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToAll.Obsolete; +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class get_info_obsolete : IClassFixture { - const string GroupName = nameof(get_info_obsolete); +namespace Kurrent.Client.Tests.PersistentSubscriptions; +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToStreamGetInfoObsoleteTests(SubscribeToStreamGetInfoObsoleteTests.CustomFixture fixture) + : IClassFixture { static readonly PersistentSubscriptionSettings Settings = new( - resolveLinkTos: true, - startFrom: Position.Start, - extraStatistics: true, - messageTimeout: TimeSpan.FromSeconds(9), - maxRetryCount: 11, - liveBufferSize: 303, - readBatchSize: 30, - historyBufferSize: 909, - checkPointAfter: TimeSpan.FromSeconds(1), - checkPointLowerBound: 1, - checkPointUpperBound: 1, - maxSubscriberCount: 500, - consumerStrategyName: SystemConsumerStrategies.Pinned + true, + StreamPosition.Start, + true, + TimeSpan.FromSeconds(9), + 11, + 303, + 30, + 909, + TimeSpan.FromSeconds(1), + 1, + 1, + 500, + SystemConsumerStrategies.RoundRobin ); - readonly Fixture _fixture; - - public get_info_obsolete(Fixture fixture) => _fixture = fixture; - - [Fact] - public async Task throws_when_not_supported() { - if (SupportsPSToAll.No) - await Assert.ThrowsAsync( - async () => { await _fixture.Client.GetInfoToAllAsync(GroupName, userCredentials: TestCredentials.Root); } - ); + public static IEnumerable AllowedUsers() { + yield return new object[] { TestCredentials.Root }; } - [SupportsPSToAll.Fact] - public async Task returns_expected_result() { - var result = await _fixture.Client.GetInfoToAllAsync(GroupName, userCredentials: TestCredentials.Root); - - Assert.Equal("$all", result.EventSource); - Assert.Equal(GroupName, result.GroupName); - Assert.Equal("Live", result.Status); + [Theory] + [MemberData(nameof(AllowedUsers))] + public async Task returns_expected_result(UserCredentials credentials) { + var result = await fixture.Subscriptions.GetInfoToStreamAsync(fixture.Stream, fixture.Group, userCredentials: credentials); + Assert.Equal(fixture.Stream, result.EventSource); + Assert.Equal(fixture.Group, result.GroupName); Assert.NotNull(Settings.StartFrom); Assert.True(result.Stats.TotalItems > 0); Assert.True(result.Stats.OutstandingMessagesCount > 0); Assert.True(result.Stats.AveragePerSecond >= 0); - Assert.True(result.Stats.ParkedMessageCount > 0); + Assert.True(result.Stats.ParkedMessageCount >= 0); Assert.True(result.Stats.AveragePerSecond >= 0); + Assert.True(result.Stats.ReadBufferCount >= 0); + Assert.True(result.Stats.RetryBufferCount >= 0); Assert.True(result.Stats.CountSinceLastMeasurement >= 0); Assert.True(result.Stats.TotalInFlightMessages >= 0); Assert.NotNull(result.Stats.LastKnownEventPosition); @@ -54,13 +49,12 @@ public async Task returns_expected_result() { Assert.NotNull(result.Connections); Assert.NotEmpty(result.Connections); - var connection = result.Connections.First(); Assert.NotNull(connection.From); Assert.Equal(TestCredentials.Root.Username, connection.Username); Assert.NotEmpty(connection.ConnectionName); Assert.True(connection.AverageItemsPerSecond >= 0); - Assert.True(connection.TotalItems > 0); + Assert.True(connection.TotalItems >= 0); Assert.True(connection.CountSinceLastMeasurement >= 0); Assert.True(connection.AvailableSlots >= 0); Assert.True(connection.InFlightMessages >= 0); @@ -98,86 +92,110 @@ public async Task returns_expected_result() { Assert.Equal(Settings.ConsumerStrategyName, result.Settings!.ConsumerStrategyName); } - [SupportsPSToAll.Fact] - public async Task throws_with_non_existing_subscription() => + [RetryFact] + public async Task throws_when_given_non_existing_subscription() => await Assert.ThrowsAsync( async () => { - await _fixture.Client.GetInfoToAllAsync( + await fixture.Subscriptions.GetInfoToStreamAsync( + "NonExisting", "NonExisting", userCredentials: TestCredentials.Root ); } ); - [SupportsPSToAll.Fact] - public async Task throws_with_no_credentials() => - await Assert.ThrowsAsync(async () => { await _fixture.Client.GetInfoToAllAsync("NonExisting"); }); + [Fact(Skip = "Unable to produce same behavior with HTTP fallback!")] + public async Task throws_with_non_existing_user() { + var group = $"NonExisting-{fixture.GetGroupName()}"; + var stream = $"NonExisting-{fixture.GetStreamName()}"; - [SupportsPSToAll.Fact] - public async Task throws_with_non_existing_user() => await Assert.ThrowsAsync( async () => { - await _fixture.Client.GetInfoToAllAsync( - "NonExisting", + await fixture.Subscriptions.GetInfoToStreamAsync( + stream, + group, userCredentials: TestCredentials.TestBadUser ); } ); + } - [SupportsPSToAll.Fact] - public async Task returns_result_with_normal_user_credentials() { - var result = await _fixture.Client.GetInfoToAllAsync( - GroupName, - userCredentials: TestCredentials.TestUser1 - ); + [RetryFact] + public async Task throws_with_no_credentials() { + var group = $"NonExisting-{fixture.GetGroupName()}"; + var stream = $"NonExisting-{fixture.GetStreamName()}"; - Assert.Equal("$all", result.EventSource); + await Assert.ThrowsAsync( + async () => { + await fixture.Subscriptions.GetInfoToStreamAsync( + stream, + group + ); + } + ); } - void AssertKeyAndValue(IDictionary items, string key) { - Assert.True(items.ContainsKey(key)); - Assert.True(items[key] > 0); + [RetryFact] + public async Task returns_result_for_normal_user() { + var result = await fixture.Subscriptions.GetInfoToStreamAsync( + fixture.Stream, + fixture.Group, + userCredentials: TestCredentials.Root + ); + + Assert.NotNull(result); } - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } + public class CustomFixture : KurrentTemporaryFixture { + public string Group { get; set; } + public string Stream { get; set; } - protected override async Task Given() { - if (SupportsPSToAll.No) - return; + public CustomFixture() : base(x => x.WithoutDefaultCredentials()) { + Group = GetGroupName(); + Stream = GetStreamName(); - await Client.CreateToAllAsync( - GroupName, - get_info_obsolete.Settings, - userCredentials: TestCredentials.Root - ); - } + OnSetup += async () => { + await Subscriptions.CreateToStreamAsync( + groupName: Group, + streamName: Stream, + settings: Settings, + userCredentials: TestCredentials.Root + ); - protected override async Task When() { - if (SupportsPSToAll.No) - return; + var counter = 0; + var tcs = new TaskCompletionSource(); - var counter = 0; - var tcs = new TaskCompletionSource(); + await Subscriptions.SubscribeToStreamAsync( + Stream, + Group, + (s, e, r, ct) => { + counter++; - await Client.SubscribeToAllAsync( - GroupName, - (s, e, r, ct) => { - counter++; + if (counter == 1) + s.Nack(PersistentSubscriptionNakEventAction.Park, "Test", e); - switch (counter) { - case 1: s.Nack(PersistentSubscriptionNakEventAction.Park, "Test", e); - break; - case > 10: + if (counter > 10) tcs.TrySetResult(); - break; - } - return Task.CompletedTask; - }, - userCredentials: TestCredentials.Root - ); - - await tcs.Task; + + return Task.CompletedTask; + }, + userCredentials: TestCredentials.Root + ); + + for (var i = 0; i < 15; i++) { + await Streams.AppendToStreamAsync( + Stream, + StreamState.Any, + [new EventData(Uuid.NewUuid(), "test-event", ReadOnlyMemory.Empty)], + userCredentials: TestCredentials.Root + ); + } + }; } + }; + + void AssertKeyAndValue(IDictionary items, string key) { + Assert.True(items.ContainsKey(key)); + Assert.True(items[key] > 0); } } diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/Obsolete/SubscribeToStreamObsoleteTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/Obsolete/SubscribeToStreamObsoleteTests.cs new file mode 100644 index 000000000..2f192c426 --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/Obsolete/SubscribeToStreamObsoleteTests.cs @@ -0,0 +1,948 @@ +using System.Text; +using EventStore.Client; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToStreamObsoleteTests(ITestOutputHelper output, KurrentPermanentFixture fixture) + : KurrentPermanentTests(output, fixture) { + [RetryFact] + public async Task connect_to_existing_with_max_one_client() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(maxSubscriberCount: 1), + userCredentials: TestCredentials.Root + ); + + using var first = await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + delegate { return Task.CompletedTask; }, + userCredentials: TestCredentials.Root + ).WithTimeout(); + + var ex = await Assert.ThrowsAsync( + async () => { + using var _ = await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + delegate { return Task.CompletedTask; }, + userCredentials: TestCredentials.Root + ); + } + ).WithTimeout(); + + Assert.Equal(stream, ex.StreamName); + Assert.Equal(group, ex.GroupName); + } + + [RetryFact] + public async Task connect_to_existing_with_permissions() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + var dropped = new TaskCompletionSource<(SubscriptionDroppedReason, Exception?)>(); + using var subscription = await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + delegate { return Task.CompletedTask; }, + (s, reason, ex) => dropped.TrySetResult((reason, ex)), + TestCredentials.Root + ).WithTimeout(); + + Assert.NotNull(subscription); + + await Assert.ThrowsAsync(() => dropped.Task.WithTimeout()); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_beginning_and_events_in_it() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + TaskCompletionSource firstEventSource = new(); + + var events = Fixture.CreateTestEvents(10).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: StreamPosition.Start), + userCredentials: TestCredentials.Root + ); + + using var subscription = await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + async (subscription, e, r, ct) => { + firstEventSource.TrySetResult(e); + await subscription.Ack(e); + }, + (subscription, reason, ex) => { + if (reason != SubscriptionDroppedReason.Disposed) + firstEventSource.TrySetException(ex!); + }, + TestCredentials.Root + ); + + var firstEvent = firstEventSource.Task; + + var resolvedEvent = await firstEvent.WithTimeout(TimeSpan.FromSeconds(10)); + Assert.Equal(StreamPosition.Start, resolvedEvent.Event.EventNumber); + Assert.Equal(events[0].EventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_beginning_and_no_stream() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + TaskCompletionSource firstEventSource = new(); + + var events = Fixture.CreateTestEvents().ToArray(); + + var eventId = events.Single().EventId; + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + using var subscription = await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + async (subscription, e, r, ct) => { + firstEventSource.TrySetResult(e); + await subscription.Ack(e); + }, + (subscription, reason, ex) => { + if (reason != SubscriptionDroppedReason.Disposed) + firstEventSource.TrySetException(ex!); + }, + TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + + var firstEvent = await firstEventSource.Task.WithTimeout(TimeSpan.FromSeconds(10)); + Assert.Equal(StreamPosition.Start, firstEvent.Event.EventNumber); + Assert.Equal(eventId, firstEvent.Event.EventId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_not_set_and_events_in_it() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + TaskCompletionSource firstEventSource = new(); + + var events = Fixture.CreateTestEvents(10).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + using var subscription = await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + async (subscription, e, r, ct) => { + firstEventSource.TrySetResult(e); + await subscription.Ack(e); + }, + (subscription, reason, ex) => { + if (reason != SubscriptionDroppedReason.Disposed) + firstEventSource.TrySetException(ex!); + }, + TestCredentials.Root + ); + + var firstEvent = firstEventSource.Task; + + await Assert.ThrowsAsync(() => firstEvent.WithTimeout()); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + TaskCompletionSource firstEventSource = new(); + + var events = Fixture.CreateTestEvents(11).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(10)); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + using var subscription = await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + async (subscription, e, r, ct) => { + firstEventSource.TrySetResult(e); + await subscription.Ack(e); + }, + (subscription, reason, ex) => { + if (reason != SubscriptionDroppedReason.Disposed) + firstEventSource.TrySetException(ex!); + }, + TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(9), events.Skip(10)); + + var firstEvent = firstEventSource.Task; + + var resolvedEvent = await firstEvent.WithTimeout(); + Assert.Equal(new(10), resolvedEvent.Event.EventNumber); + Assert.Equal(events.Last().EventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_set_to_end_position_and_events_in_it() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + TaskCompletionSource firstEventSource = new(); + + var events = Fixture.CreateTestEvents(10).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: StreamPosition.End), + userCredentials: TestCredentials.Root + ); + + using var subscription = await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + async (subscription, e, r, ct) => { + firstEventSource.TrySetResult(e); + await subscription.Ack(e); + }, + (subscription, reason, ex) => { + if (reason != SubscriptionDroppedReason.Disposed) + firstEventSource.TrySetException(ex!); + }, + TestCredentials.Root + ); + + var firstEvent = firstEventSource.Task; + await Assert.ThrowsAsync(() => firstEvent.WithTimeout()); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + TaskCompletionSource firstEventSource = new(); + + var events = Fixture.CreateTestEvents(11).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(10)); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: StreamPosition.End), + userCredentials: TestCredentials.Root + ); + + using var subscription = await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + async (subscription, e, r, ct) => { + firstEventSource.TrySetResult(e); + await subscription.Ack(e); + }, + (subscription, reason, ex) => { + if (reason != SubscriptionDroppedReason.Disposed) + firstEventSource.TrySetException(ex!); + }, + TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(9), events.Skip(10)); + + var firstEvent = firstEventSource.Task; + + var resolvedEvent = await firstEvent.WithTimeout(); + Assert.Equal(new(10), resolvedEvent.Event.EventNumber); + Assert.Equal(events.Last().EventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_two_and_no_stream() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + TaskCompletionSource firstEventSource = new(); + + var events = Fixture.CreateTestEvents(3).ToArray(); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: new StreamPosition(2)), + userCredentials: TestCredentials.Root + ); + + using var subscription = await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + async (subscription, e, r, ct) => { + firstEventSource.TrySetResult(e); + await subscription.Ack(e); + }, + (subscription, reason, ex) => { + if (reason != SubscriptionDroppedReason.Disposed) + firstEventSource.TrySetException(ex!); + }, + TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + + var firstEvent = firstEventSource.Task; + var resolvedEvent = await firstEvent.WithTimeout(TimeSpan.FromSeconds(10)); + var eventId = events.Last().EventId; + + Assert.Equal(new(2), resolvedEvent.Event.EventNumber); + Assert.Equal(eventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_x_set_and_events_in_it() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + TaskCompletionSource firstEventSource = new(); + + var events = Fixture.CreateTestEvents(10).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(10)); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: new StreamPosition(4)), + userCredentials: TestCredentials.Root + ); + + using var subscription = await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + async (subscription, e, r, ct) => { + firstEventSource.TrySetResult(e); + await subscription.Ack(e); + }, + (subscription, reason, ex) => { + if (reason != SubscriptionDroppedReason.Disposed) + firstEventSource.TrySetException(ex!); + }, + TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(9), events.Skip(10)); + + var firstEvent = firstEventSource.Task; + + var resolvedEvent = await firstEvent.WithTimeout(); + Assert.Equal(new(4), resolvedEvent.Event.EventNumber); + Assert.Equal(events.Skip(4).First().EventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + TaskCompletionSource firstEventSource = new(); + + var events = Fixture.CreateTestEvents(11).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(10)); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: new StreamPosition(10)), + userCredentials: TestCredentials.Root + ); + + using var subscription = await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + async (subscription, e, r, ct) => { + firstEventSource.TrySetResult(e); + await subscription.Ack(e); + }, + (subscription, reason, ex) => { + if (reason != SubscriptionDroppedReason.Disposed) + firstEventSource.TrySetException(ex!); + }, + TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(9), events.Skip(10)); + + var firstEvent = firstEventSource.Task; + + var resolvedEvent = await firstEvent.WithTimeout(); + Assert.Equal(new(10), resolvedEvent.Event.EventNumber); + Assert.Equal(events.Last().EventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + TaskCompletionSource firstEventSource = new(); + + var events = Fixture.CreateTestEvents(12).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(11)); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: new StreamPosition(11)), + userCredentials: TestCredentials.Root + ); + + using var subscription = await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + async (subscription, e, r, ct) => { + firstEventSource.TrySetResult(e); + await subscription.Ack(e); + }, + (subscription, reason, ex) => { + if (reason != SubscriptionDroppedReason.Disposed) + firstEventSource.TrySetException(ex!); + }, + TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(10), events.Skip(11)); + + var firstEvent = firstEventSource.Task; + + var resolvedEvent = await firstEvent.WithTimeout(); + Assert.Equal(new(11), resolvedEvent.Event.EventNumber); + Assert.Equal(events.Last().EventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task connect_to_non_existing_with_permissions() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + var ex = await Assert.ThrowsAsync( + async () => { + using var _ = await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + delegate { return Task.CompletedTask; }, + userCredentials: TestCredentials.Root + ); + } + ).WithTimeout(); + + Assert.Equal(stream, ex.StreamName); + Assert.Equal(group, ex.GroupName); + } + + [RetryFact] + public async Task connect_with_retries() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + TaskCompletionSource retryCountSource = new(); + + var events = Fixture.CreateTestEvents().ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: StreamPosition.Start), + userCredentials: TestCredentials.Root + ); + + using var subscription = await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + async (subscription, e, r, ct) => { + if (r > 4) { + retryCountSource.TrySetResult(r.Value); + await subscription.Ack(e.Event.EventId); + } else { + await subscription.Nack( + PersistentSubscriptionNakEventAction.Retry, + "Not yet tried enough times", + e + ); + } + }, + (subscription, reason, ex) => { + if (reason != SubscriptionDroppedReason.Disposed) + retryCountSource.TrySetException(ex!); + }, + TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + + Task retryCount = retryCountSource.Task; + Assert.Equal(5, await retryCount.WithTimeout()); + } + + [RetryFact] + public async Task connecting_to_a_persistent_subscription() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + TaskCompletionSource firstEventSource = new(); + + var events = Fixture.CreateTestEvents(12).ToArray(); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(11)); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: new StreamPosition(11)), + userCredentials: TestCredentials.Root + ); + + using var subscription = await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + async (subscription, e, r, ct) => { + firstEventSource.TrySetResult(e); + await subscription.Ack(e); + }, + (subscription, reason, ex) => { + if (reason != SubscriptionDroppedReason.Disposed) + firstEventSource.TrySetException(ex!); + }, + TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(10), events.Skip(11)); + + Task firstEvent = firstEventSource.Task; + + var resolvedEvent = await firstEvent.WithTimeout(); + Assert.Equal(new(11), resolvedEvent.Event.EventNumber); + Assert.Equal(events.Last().EventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task deleting_existing_with_subscriber_the_subscription_is_dropped() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + TaskCompletionSource<(SubscriptionDroppedReason, Exception?)> dropped = new(); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + using var subscription = await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + (_, _, _, _) => Task.CompletedTask, + (_, r, e) => dropped.TrySetResult((r, e)), + TestCredentials.Root + ); + + await Fixture.Subscriptions.DeleteToStreamAsync( + stream, + group, + userCredentials: TestCredentials.Root + ); + + var (reason, exception) = await dropped.Task.WithTimeout(); + Assert.Equal(SubscriptionDroppedReason.ServerError, reason); + var ex = Assert.IsType(exception); + + Assert.Equal(stream, ex.StreamName); + Assert.Equal(group, ex.GroupName); + } + + [Fact(Skip = "Isn't this how it should work?")] + public async Task deleting_existing_with_subscriber_the_subscription_is_dropped_with_not_found() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + TaskCompletionSource<(SubscriptionDroppedReason, Exception?)> _dropped = new(); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + using var subscription = await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + (_, _, _, _) => Task.CompletedTask, + (_, r, e) => _dropped.TrySetResult((r, e)), + TestCredentials.Root + ); + + await Fixture.Subscriptions.DeleteToStreamAsync( + stream, + group, + userCredentials: TestCredentials.Root + ); + + Task<(SubscriptionDroppedReason, Exception?)> dropped = _dropped.Task; + + var (reason, exception) = await dropped.WithTimeout(); + Assert.Equal(SubscriptionDroppedReason.ServerError, reason); + var ex = Assert.IsType(exception); + Assert.Equal(stream, ex.StreamName); + Assert.Equal("groupname123", ex.GroupName); + } + + [RetryFact] + public async Task happy_case_catching_up_to_link_to_events_manual_ack() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + const int bufferCount = 10; + const int eventWriteCount = bufferCount * 2; + + EventData[] events; + TaskCompletionSource eventsReceived = new(); + int eventReceivedCount = 0; + + events = Fixture.CreateTestEvents(eventWriteCount) + .Select( + (e, i) => new EventData( + e.EventId, + SystemEventTypes.LinkTo, + Encoding.UTF8.GetBytes($"{i}@{stream}"), + contentType: Constants.Metadata.ContentTypes.ApplicationOctetStream + ) + ) + .ToArray(); + + foreach (var e in events) + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, new[] { e }); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: StreamPosition.Start, resolveLinkTos: true), + userCredentials: TestCredentials.Root + ); + + using var subscription = await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + async (subscription, e, retryCount, ct) => { + await subscription.Ack(e); + + if (Interlocked.Increment(ref eventReceivedCount) == events.Length) + eventsReceived.TrySetResult(true); + }, + (s, r, e) => { + if (e != null) + eventsReceived.TrySetException(e); + }, + bufferSize: bufferCount, + userCredentials: TestCredentials.Root + ); + + await eventsReceived.Task.WithTimeout(); + } + + [RetryFact] + public async Task happy_case_catching_up_to_normal_events_manual_ack() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + const int bufferCount = 10; + const int eventWriteCount = bufferCount * 2; + + int eventReceivedCount = 0; + + var events = Fixture.CreateTestEvents(eventWriteCount).ToArray(); + TaskCompletionSource eventsReceived = new(); + + foreach (var e in events) + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, new[] { e }); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: StreamPosition.Start, resolveLinkTos: true), + userCredentials: TestCredentials.Root + ); + + using var subscription = await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + async (subscription, e, retryCount, ct) => { + await subscription.Ack(e); + + if (Interlocked.Increment(ref eventReceivedCount) == events.Length) + eventsReceived.TrySetResult(true); + }, + (s, r, e) => { + if (e != null) + eventsReceived.TrySetException(e); + }, + bufferSize: bufferCount, + userCredentials: TestCredentials.Root + ); + + await eventsReceived.Task.WithTimeout(); + } + + [RetryFact] + public async Task happy_case_writing_and_subscribing_to_normal_events_manual_ack() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + const int bufferCount = 10; + const int eventWriteCount = bufferCount * 2; + + int eventReceivedCount = 0; + + var events = Fixture.CreateTestEvents(eventWriteCount).ToArray(); + TaskCompletionSource eventsReceived = new(); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: StreamPosition.End, resolveLinkTos: true), + userCredentials: TestCredentials.Root + ); + + using var subscription = await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + async (subscription, e, retryCount, ct) => { + await subscription.Ack(e); + if (Interlocked.Increment(ref eventReceivedCount) == events.Length) + eventsReceived.TrySetResult(true); + }, + (s, r, e) => { + if (e != null) + eventsReceived.TrySetException(e); + }, + bufferSize: bufferCount, + userCredentials: TestCredentials.Root + ); + + foreach (var e in events) + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, [e]); + + await eventsReceived.Task.WithTimeout(); + } + + [RetryFact] + public async Task update_existing_with_check_point() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + StreamPosition checkPoint = default; + + TaskCompletionSource<(SubscriptionDroppedReason, Exception?)> droppedSource = new(); + TaskCompletionSource resumedSource = new(); + TaskCompletionSource appeared = new(); + List appearedEvents = []; + EventData[] events = Fixture.CreateTestEvents(5).ToArray(); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new( + checkPointLowerBound: 5, + checkPointAfter: TimeSpan.FromSeconds(1), + startFrom: StreamPosition.Start + ), + userCredentials: TestCredentials.Root + ); + + var checkPointStream = $"$persistentsubscription-{stream}::{group}-checkpoint"; + + await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + async (s, e, _, _) => { + appearedEvents.Add(e); + await s.Ack(e); + + if (appearedEvents.Count == events.Length) + appeared.TrySetResult(true); + }, + (_, reason, ex) => droppedSource.TrySetResult((reason, ex)), + TestCredentials.Root + ); + + await Task.WhenAll(appeared.Task.WithTimeout(), Checkpointed()); + + // Force restart of the subscription + await Fixture.Subscriptions.UpdateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + await droppedSource.Task.WithTimeout(); + + await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + async (s, e, _, _) => { + resumedSource.TrySetResult(e); + await s.Ack(e); + }, + (_, reason, ex) => { + if (ex is not null) + resumedSource.TrySetException(ex); + else + resumedSource.TrySetResult(default); + }, + TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, Fixture.CreateTestEvents(1)); + + var resumedEvent = await resumedSource.Task.WithTimeout(TimeSpan.FromSeconds(10)); + Assert.Equal(checkPoint.Next(), resumedEvent.Event.EventNumber); + + return; + + async Task Checkpointed() { + await using var subscription = Fixture.Streams.SubscribeToStream( + checkPointStream, + FromStream.Start, + userCredentials: TestCredentials.Root + ); + + await foreach (var message in subscription.Messages) { + if (message is not StreamMessage.Event(var resolvedEvent)) { + continue; + } + + checkPoint = resolvedEvent.Event.Data.ParseStreamPosition(); + return; + } + + throw new InvalidOperationException(); + } + } + + [RetryFact] + public async Task update_existing_with_subscribers() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + TaskCompletionSource<(SubscriptionDroppedReason, Exception?)> droppedSource = new(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + delegate { return Task.CompletedTask; }, + (_, reason, ex) => droppedSource.TrySetResult((reason, ex)), + TestCredentials.Root + ); + + await Fixture.Subscriptions.UpdateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + var dropped = droppedSource.Task; + + var (reason, exception) = await dropped.WithTimeout(TimeSpan.FromSeconds(10)); + Assert.Equal(SubscriptionDroppedReason.ServerError, reason); + var ex = Assert.IsType(exception); + + Assert.Equal(stream, ex.StreamName); + Assert.Equal(group, ex.GroupName); + } + + [RetryFact] + public async Task when_writing_and_subscribing_to_normal_events_manual_nack() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + const int bufferCount = 10; + const int eventWriteCount = bufferCount * 2; + + int eventReceivedCount = 0; + + EventData[] events = Fixture.CreateTestEvents(eventWriteCount) + .ToArray(); + + TaskCompletionSource eventsReceived = new(); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: StreamPosition.Start, resolveLinkTos: true), + userCredentials: TestCredentials.Root + ); + + using var subscription = await Fixture.Subscriptions.SubscribeToStreamAsync( + stream, + group, + async (subscription, e, retryCount, ct) => { + await subscription.Nack(PersistentSubscriptionNakEventAction.Park, "fail", e); + + if (Interlocked.Increment(ref eventReceivedCount) == events.Length) + eventsReceived.TrySetResult(true); + }, + (s, r, e) => { + if (e != null) + eventsReceived.TrySetException(e); + }, + bufferSize: bufferCount, + userCredentials: TestCredentials.Root + ); + + foreach (var e in events) + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, [e]); + + await eventsReceived.Task.WithTimeout(); + } +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/SubscribeToStreamConnectToExistingWithStartFromBeginningTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/SubscribeToStreamConnectToExistingWithStartFromBeginningTests.cs new file mode 100644 index 000000000..61eb46eb0 --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/SubscribeToStreamConnectToExistingWithStartFromBeginningTests.cs @@ -0,0 +1,33 @@ +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToStreamConnectToExistingWithStartFromBeginningTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task connect_to_existing_with_start_from_beginning_and_no_streamconnect_to_existing_with_start_from_not_set_and_events_in_it() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + var events = Fixture.CreateTestEvents(10).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream( + stream, + group, + userCredentials: TestCredentials.Root + ); + + await Assert.ThrowsAsync( + () => subscription.Messages.AnyAsync(message => message is PersistentSubscriptionMessage.Event).AsTask().WithTimeout() + ); + } +} diff --git a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/get_info_obsolete.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/SubscribeToStreamGetInfoTests.cs similarity index 50% rename from test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/get_info_obsolete.cs rename to test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/SubscribeToStreamGetInfoTests.cs index 34068a937..d0c593078 100644 --- a/test/EventStore.Client.PersistentSubscriptions.Tests/SubscriptionToStream/Obsolete/get_info_obsolete.cs +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/SubscribeToStreamGetInfoTests.cs @@ -1,11 +1,14 @@ -namespace EventStore.Client.PersistentSubscriptions.Tests.SubscriptionToStream.Obsolete; +// ReSharper disable InconsistentNaming -[Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class get_info_obsolete : IClassFixture { - const string GroupName = nameof(get_info_obsolete); - const string StreamName = nameof(get_info_obsolete); +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; - static readonly PersistentSubscriptionSettings _settings = new( +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToStreamGetInfoTests(SubscribeToStreamGetInfoTests.CustomFixture fixture) + : IClassFixture { + static readonly PersistentSubscriptionSettings Settings = new( true, StreamPosition.Start, true, @@ -21,27 +24,18 @@ public class get_info_obsolete : IClassFixture { SystemConsumerStrategies.RoundRobin ); - readonly Fixture _fixture; - - public get_info_obsolete(Fixture fixture) => _fixture = fixture; - public static IEnumerable AllowedUsers() { yield return new object[] { TestCredentials.Root }; - yield return new object[] { TestCredentials.TestUser1 }; } [Theory] [MemberData(nameof(AllowedUsers))] public async Task returns_expected_result(UserCredentials credentials) { - var result = await _fixture.Client.GetInfoToStreamAsync( - StreamName, - GroupName, - userCredentials: credentials - ); + var result = await fixture.Subscriptions.GetInfoToStreamAsync(fixture.Stream, fixture.Group, userCredentials: credentials); - Assert.Equal(StreamName, result.EventSource); - Assert.Equal(GroupName, result.GroupName); - Assert.NotNull(_settings.StartFrom); + Assert.Equal(fixture.Stream, result.EventSource); + Assert.Equal(fixture.Group, result.GroupName); + Assert.NotNull(Settings.StartFrom); Assert.True(result.Stats.TotalItems > 0); Assert.True(result.Stats.OutstandingMessagesCount > 0); Assert.True(result.Stats.AveragePerSecond >= 0); @@ -85,26 +79,26 @@ public async Task returns_expected_result(UserCredentials credentials) { AssertKeyAndValue(connection.ExtraStatistics, PersistentSubscriptionExtraStatistic.NinetyNinePointNinePercent); Assert.NotNull(result.Settings); - Assert.Equal(_settings.StartFrom, result.Settings!.StartFrom); - Assert.Equal(_settings.ResolveLinkTos, result.Settings!.ResolveLinkTos); - Assert.Equal(_settings.ExtraStatistics, result.Settings!.ExtraStatistics); - Assert.Equal(_settings.MessageTimeout, result.Settings!.MessageTimeout); - Assert.Equal(_settings.MaxRetryCount, result.Settings!.MaxRetryCount); - Assert.Equal(_settings.LiveBufferSize, result.Settings!.LiveBufferSize); - Assert.Equal(_settings.ReadBatchSize, result.Settings!.ReadBatchSize); - Assert.Equal(_settings.HistoryBufferSize, result.Settings!.HistoryBufferSize); - Assert.Equal(_settings.CheckPointAfter, result.Settings!.CheckPointAfter); - Assert.Equal(_settings.CheckPointLowerBound, result.Settings!.CheckPointLowerBound); - Assert.Equal(_settings.CheckPointUpperBound, result.Settings!.CheckPointUpperBound); - Assert.Equal(_settings.MaxSubscriberCount, result.Settings!.MaxSubscriberCount); - Assert.Equal(_settings.ConsumerStrategyName, result.Settings!.ConsumerStrategyName); + Assert.Equal(Settings.StartFrom, result.Settings!.StartFrom); + Assert.Equal(Settings.ResolveLinkTos, result.Settings!.ResolveLinkTos); + Assert.Equal(Settings.ExtraStatistics, result.Settings!.ExtraStatistics); + Assert.Equal(Settings.MessageTimeout, result.Settings!.MessageTimeout); + Assert.Equal(Settings.MaxRetryCount, result.Settings!.MaxRetryCount); + Assert.Equal(Settings.LiveBufferSize, result.Settings!.LiveBufferSize); + Assert.Equal(Settings.ReadBatchSize, result.Settings!.ReadBatchSize); + Assert.Equal(Settings.HistoryBufferSize, result.Settings!.HistoryBufferSize); + Assert.Equal(Settings.CheckPointAfter, result.Settings!.CheckPointAfter); + Assert.Equal(Settings.CheckPointLowerBound, result.Settings!.CheckPointLowerBound); + Assert.Equal(Settings.CheckPointUpperBound, result.Settings!.CheckPointUpperBound); + Assert.Equal(Settings.MaxSubscriberCount, result.Settings!.MaxSubscriberCount); + Assert.Equal(Settings.ConsumerStrategyName, result.Settings!.ConsumerStrategyName); } - [Fact] + [RetryFact] public async Task throws_when_given_non_existing_subscription() => await Assert.ThrowsAsync( async () => { - await _fixture.Client.GetInfoToStreamAsync( + await fixture.Subscriptions.GetInfoToStreamAsync( "NonExisting", "NonExisting", userCredentials: TestCredentials.Root @@ -113,87 +107,105 @@ await _fixture.Client.GetInfoToStreamAsync( ); [Fact(Skip = "Unable to produce same behavior with HTTP fallback!")] - public async Task throws_with_non_existing_user() => + public async Task throws_with_non_existing_user() { + var group = $"NonExisting-{fixture.GetGroupName()}"; + var stream = $"NonExisting-{fixture.GetStreamName()}"; + await Assert.ThrowsAsync( async () => { - await _fixture.Client.GetInfoToStreamAsync( - "NonExisting", - "NonExisting", + await fixture.Subscriptions.GetInfoToStreamAsync( + stream, + group, userCredentials: TestCredentials.TestBadUser ); } ); + } + + [RetryFact] + public async Task throws_with_no_credentials() { + var group = $"NonExisting-{fixture.GetGroupName()}"; + var stream = $"NonExisting-{fixture.GetStreamName()}"; - [Fact] - public async Task throws_with_no_credentials() => await Assert.ThrowsAsync( async () => { - await _fixture.Client.GetInfoToStreamAsync( - "NonExisting", - "NonExisting" + await fixture.Subscriptions.GetInfoToStreamAsync( + stream, + group ); } ); + } - [Fact] + [RetryFact] public async Task returns_result_for_normal_user() { - var result = await _fixture.Client.GetInfoToStreamAsync( - StreamName, - GroupName, - userCredentials: TestCredentials.TestUser1 + var result = await fixture.Subscriptions.GetInfoToStreamAsync( + fixture.Stream, + fixture.Group, + userCredentials: TestCredentials.Root ); Assert.NotNull(result); } - void AssertKeyAndValue(IDictionary items, string key) { - Assert.True(items.ContainsKey(key)); - Assert.True(items[key] > 0); - } + public class CustomFixture : KurrentTemporaryFixture { + public string Group { get; set; } + public string Stream { get; set; } - public class Fixture : EventStoreClientFixture { - public Fixture() : base(noDefaultCredentials: true) { } - - protected override Task Given() => - Client.CreateToStreamAsync( - groupName: GroupName, - streamName: StreamName, - settings: _settings, - userCredentials: TestCredentials.Root - ); - - protected override async Task When() { - var counter = 0; - var tcs = new TaskCompletionSource(); - - await Client.SubscribeToStreamAsync( - StreamName, - GroupName, - (s, e, r, ct) => { - counter++; - - if (counter == 1) - s.Nack(PersistentSubscriptionNakEventAction.Park, "Test", e); + KurrentPersistentSubscriptionsClient.PersistentSubscriptionResult? Subscription; + IAsyncEnumerator? Enumerator; - if (counter > 10) - tcs.TrySetResult(); + public CustomFixture() : base(x => x.WithoutDefaultCredentials()) { + Group = GetGroupName(); + Stream = GetStreamName(); - return Task.CompletedTask; - }, - userCredentials: TestCredentials.Root - ); - - for (var i = 0; i < 15; i++) - await StreamsClient.AppendToStreamAsync( - StreamName, - StreamState.Any, - new[] { - new EventData(Uuid.NewUuid(), "test-event", ReadOnlyMemory.Empty) - }, + OnSetup += async () => { + await Subscriptions.CreateToStreamAsync( + groupName: Group, + streamName: Stream, + settings: Settings, userCredentials: TestCredentials.Root ); - await tcs.Task; + var counter = 0; + Subscription = Subscriptions.SubscribeToStream(Stream, Group, userCredentials: TestCredentials.Root); + Enumerator = Subscription.Messages.GetAsyncEnumerator(); + + for (var i = 0; i < 15; i++) { + await Streams.AppendToStreamAsync( + Stream, + StreamState.Any, + [new EventData(Uuid.NewUuid(), "test-event", ReadOnlyMemory.Empty)], + userCredentials: TestCredentials.Root + ); + } + + while (await Enumerator.MoveNextAsync()) { + if (Enumerator.Current is not PersistentSubscriptionMessage.Event(var resolvedEvent, _)) { + continue; + } + + counter++; + + if (counter == 1) { + await Subscription.Nack(PersistentSubscriptionNakEventAction.Park, "Test", resolvedEvent); + } + + if (counter > 10) { + return; + } + } + }; + + OnTearDown += async () => { + if (Enumerator is not null) await Enumerator.DisposeAsync(); + if (Subscription is not null) await Subscription.DisposeAsync(); + }; } + }; + + void AssertKeyAndValue(IDictionary items, string key) { + Assert.True(items.ContainsKey(key)); + Assert.True(items[key] > 0); } } diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/SubscribeToStreamListTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/SubscribeToStreamListTests.cs new file mode 100644 index 000000000..e27f4eee2 --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/SubscribeToStreamListTests.cs @@ -0,0 +1,48 @@ +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToStreamListTests(ITestOutputHelper output, SubscribeToStreamListTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] + public async Task throws_with_no_credentials() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + const int streamSubscriptionCount = 4; + + for (var i = 0; i < streamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + await Assert.ThrowsAsync(async () => await Fixture.Subscriptions.ListToStreamAsync(stream)); + } + + [RetryFact] + public async Task throws_with_non_existing_user() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + const int streamSubscriptionCount = 4; + + for (var i = 0; i < streamSubscriptionCount; i++) + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group + i, + new(), + userCredentials: TestCredentials.Root + ); + + await Assert.ThrowsAsync( + async () => await Fixture.Subscriptions.ListToStreamAsync(stream, userCredentials: TestCredentials.TestBadUser) + ); + } + + public class CustomFixture() : KurrentTemporaryFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/SubscribeToStreamNoDefaultCredentialsTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/SubscribeToStreamNoDefaultCredentialsTests.cs new file mode 100644 index 000000000..b1889475c --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/SubscribeToStreamNoDefaultCredentialsTests.cs @@ -0,0 +1,80 @@ +using EventStore.Client; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToStreamNoDefaultCredentialsTests(ITestOutputHelper output, SubscribeToStreamNoDefaultCredentialsTests.CustomFixture fixture) + : KurrentPermanentTests(output, fixture) { + [RetryFact] + public async Task connect_to_existing_without_permissions() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + await Assert.ThrowsAsync( + async () => { + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group); + await subscription.Messages.AnyAsync(); + } + ).WithTimeout(); + } + + [RetryFact] + public async Task create_without_permissions() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Assert.ThrowsAsync( + () => + Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new() + ) + ); + } + + [RetryFact] + public async Task deleting_without_permissions() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Assert.ThrowsAsync(() => Fixture.Subscriptions.DeleteToStreamAsync(stream, group)); + } + + [RetryFact] + public async Task update_existing_without_permissions() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Streams.AppendToStreamAsync( + stream, + StreamState.NoStream, + Fixture.CreateTestEvents(), + userCredentials: TestCredentials.Root + ); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + await Assert.ThrowsAsync( + () => Fixture.Subscriptions.UpdateToStreamAsync( + stream, + group, + new() + ) + ); + } + + public class CustomFixture() : KurrentPermanentFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/SubscribeToStreamReplayParkedTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/SubscribeToStreamReplayParkedTests.cs new file mode 100644 index 000000000..fffe7b154 --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/SubscribeToStreamReplayParkedTests.cs @@ -0,0 +1,71 @@ +using EventStore.Client; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToStreamReplayParkedTests(ITestOutputHelper output, SubscribeToStreamReplayParkedTests.CustomFixture fixture) + : KurrentPermanentTests(output, fixture) { + [RetryFact] + public async Task does_not_throw() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToStreamAsync(stream, group, new(), userCredentials: TestCredentials.Root); + + await Fixture.Subscriptions.ReplayParkedMessagesToStreamAsync( + stream, + group, + userCredentials: TestCredentials.Root + ); + + await Fixture.Subscriptions.ReplayParkedMessagesToStreamAsync( + stream, + group, + 100, + userCredentials: TestCredentials.Root + ); + } + + [RetryFact] + public async Task throws_with_no_credentials() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + await Fixture.Subscriptions.CreateToStreamAsync(stream, group, new(), userCredentials: TestCredentials.Root); + + await Assert.ThrowsAsync( + () => + Fixture.Subscriptions.ReplayParkedMessagesToStreamAsync(stream, group) + ); + } + + [Fact(Skip = "Unable to produce same behavior with HTTP fallback!")] + public async Task throws_with_non_existing_user() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + + await Fixture.Subscriptions.CreateToStreamAsync(stream, group, new(), userCredentials: TestCredentials.Root); + + await Assert.ThrowsAsync( + () => Fixture.Subscriptions.ReplayParkedMessagesToStreamAsync(stream, group, userCredentials: TestCredentials.TestBadUser) + ); + } + + [RetryFact] + public async Task throws_with_normal_user_credentials() { + var group = Fixture.GetGroupName(); + var stream = Fixture.GetStreamName(); + var user = Fixture.GetUserCredentials(); + + await Fixture.Users + .CreateUserWithRetry(user.Username!, user.Username!, [], user.Password!, TestCredentials.Root) + .WithTimeout(); + + await Assert.ThrowsAsync( + () => + Fixture.Subscriptions.ReplayParkedMessagesToStreamAsync(stream, group, userCredentials: user) + ); + } + + public class CustomFixture() : KurrentPermanentFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/SubscribeToStreamTests.cs b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/SubscribeToStreamTests.cs new file mode 100644 index 000000000..7fc9779f5 --- /dev/null +++ b/test/Kurrent.Client.Tests/PersistentSubscriptions/SubscribeToStream/SubscribeToStreamTests.cs @@ -0,0 +1,720 @@ +using System.Text; +using EventStore.Client; +using Grpc.Core; + +namespace Kurrent.Client.Tests.PersistentSubscriptions; + +[Trait("Category", "Target:PersistentSubscriptions")] +public class SubscribeToStreamTests(ITestOutputHelper output, KurrentPermanentFixture fixture) + : KurrentPermanentTests(output, fixture) { + [RetryFact] + public async Task can_create_duplicate_name_on_different_streams() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + await Fixture.Subscriptions.CreateToStreamAsync( + "someother" + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + } + + [RetryFact] + public async Task connect_to_existing_with_max_one_client() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(maxSubscriberCount: 1), + userCredentials: TestCredentials.Root + ); + + var ex = await Assert.ThrowsAsync(() => Task.WhenAll(Subscribe().WithTimeout(), Subscribe().WithTimeout())); + + Assert.Equal(stream, ex.StreamName); + Assert.Equal(group, ex.GroupName); + return; + + async Task Subscribe() { + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.Root); + await subscription.Messages.AnyAsync(); + } + } + + [RetryFact] + public async Task connect_to_existing_with_permissions() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToStreamAsync(stream, group, new(), userCredentials: TestCredentials.Root); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.Root); + + Assert.True(await subscription.Messages.FirstAsync().AsTask().WithTimeout() is PersistentSubscriptionMessage.SubscriptionConfirmation); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_beginning_and_events_in_it() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + var events = Fixture.CreateTestEvents(10).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: StreamPosition.Start), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.Root); + var resolvedEvent = await subscription.Messages.OfType() + .Select(e => e.ResolvedEvent) + .FirstOrDefaultAsync().AsTask().WithTimeout(); + + Assert.Equal(StreamPosition.Start, resolvedEvent.Event.EventNumber); + Assert.Equal(events[0].EventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_beginning_and_no_stream() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + var events = Fixture.CreateTestEvents().ToArray(); + var eventId = events.Single().EventId; + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.Root); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + + var resolvedEvent = await subscription!.Messages.OfType() + .Select(e => e.ResolvedEvent) + .FirstOrDefaultAsync().AsTask().WithTimeout(); + + Assert.Equal(StreamPosition.Start, resolvedEvent.Event.EventNumber); + Assert.Equal(eventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_not_set_and_events_in_it_then_event_written() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + var events = Fixture.CreateTestEvents(11).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(10)); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream( + stream, + group, + userCredentials: TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(9), events.Skip(10)); + + var resolvedEvent = await subscription.Messages.OfType() + .Select(e => e.ResolvedEvent) + .FirstOrDefaultAsync().AsTask().WithTimeout(); + + Assert.Equal(new(10), resolvedEvent.Event.EventNumber); + Assert.Equal(events.Last().EventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_set_to_end_position_and_events_in_it() { + var events = Fixture.CreateTestEvents(10).ToArray(); + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: StreamPosition.End), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream( + stream, + group, + userCredentials: TestCredentials.Root + ); + + await Assert.ThrowsAsync( + () => subscription.Messages.AnyAsync(message => message is PersistentSubscriptionMessage.Event).AsTask().WithTimeout(TimeSpan.FromMilliseconds(250)) + ); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_set_to_end_position_and_events_in_it_then_event_written() { + var events = Fixture.CreateTestEvents(11).ToArray(); + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(10)); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: StreamPosition.End), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.TestUser1); + + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(9), events.Skip(10)); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_two_and_no_stream() { + var events = Fixture.CreateTestEvents(3).ToArray(); + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + var eventId = events.Last().EventId; + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: new StreamPosition(2)), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream( + stream, + group, + userCredentials: TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + + var resolvedEvent = await subscription.Messages.OfType() + .Select(e => e.ResolvedEvent) + .FirstOrDefaultAsync().AsTask().WithTimeout(); + + Assert.Equal(new(2), resolvedEvent.Event.EventNumber); + Assert.Equal(eventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_x_set_and_events_in_it() { + var events = Fixture.CreateTestEvents(10).ToArray(); + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(10)); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: new StreamPosition(4)), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream( + stream, + group, + userCredentials: TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(9), events.Skip(10)); + + var resolvedEvent = await subscription.Messages + .OfType() + .Select(e => e.ResolvedEvent) + .FirstOrDefaultAsync().AsTask().WithTimeout(); + + Assert.Equal(new(4), resolvedEvent.Event.EventNumber); + Assert.Equal(events.Skip(4).First().EventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_x_set_and_events_in_it_then_event_written() { + var events = Fixture.CreateTestEvents(11).ToArray(); + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(10)); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: new StreamPosition(10)), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream( + stream, + group, + userCredentials: TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(9), events.Skip(10)); + + var resolvedEvent = await subscription.Messages.OfType() + .Select(e => e.ResolvedEvent) + .FirstOrDefaultAsync().AsTask().WithTimeout(); + + Assert.Equal(new(10), resolvedEvent.Event.EventNumber); + Assert.Equal(events.Last().EventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task connect_to_existing_with_start_from_x_set_higher_than_x_and_events_in_it_then_event_written() { + var events = Fixture.CreateTestEvents(12).ToArray(); + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(11)); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: new StreamPosition(11)), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream( + stream, + group, + userCredentials: TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(10), events.Skip(11)); + + var resolvedEvent = await subscription.Messages.OfType() + .Select(e => e.ResolvedEvent) + .FirstOrDefaultAsync().AsTask().WithTimeout(); + + Assert.Equal(new(11), resolvedEvent.Event.EventNumber); + Assert.Equal(events.Last().EventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task connect_to_non_existing_with_permissions() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.Root); + Assert.True( + await subscription.Messages.OfType() + .AnyAsync() + .AsTask() + .WithTimeout() + ); + } + + [RetryFact] + public async Task connect_with_retries() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + var events = Fixture.CreateTestEvents().ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: StreamPosition.Start), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.Root); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + var retryCount = await subscription.Messages.OfType() + .SelectAwait( + async e => { + if (e.RetryCount > 4) { + await subscription.Ack(e.ResolvedEvent); + } else { + await subscription.Nack( + PersistentSubscriptionNakEventAction.Retry, + "Not yet tried enough times", + e.ResolvedEvent + ); + } + + return e.RetryCount; + } + ) + .Where(retryCount => retryCount > 4) + .FirstOrDefaultAsync() + .AsTask() + .WithTimeout(); + + Assert.Equal(5, retryCount); + } + + [RetryFact] + public async Task connecting_to_a_persistent_subscription() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + var events = Fixture.CreateTestEvents(12).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(11)); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: new StreamPosition(11)), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.Root); + + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(10), events.Skip(11)); + + var resolvedEvent = await subscription.Messages.OfType() + .Select(e => e.ResolvedEvent) + .FirstOrDefaultAsync().AsTask().WithTimeout(); + + Assert.Equal(new(11), resolvedEvent.Event.EventNumber); + Assert.Equal(events.Last().EventId, resolvedEvent.Event.EventId); + } + + [RetryFact] + public async Task create_after_deleting_the_same() { + var stream = Fixture.GetStreamName(); + var group = $"existing-{Fixture.GetGroupName()}"; + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, Fixture.CreateTestEvents()); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + await Fixture.Subscriptions.DeleteToStreamAsync( + stream, + group, + userCredentials: TestCredentials.Root + ); + } + + [RetryFact] + public async Task create_duplicate() { + var stream = Fixture.GetStreamName(); + var group = $"duplicate-{Fixture.GetGroupName()}"; + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + var ex = await Assert.ThrowsAsync( + () => Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ) + ); + + Assert.Equal(StatusCode.AlreadyExists, ex.StatusCode); + } + + [RetryFact] + public async Task create_on_existing_stream() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, Fixture.CreateTestEvents()); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + } + + [RetryFact] + public async Task create_on_non_existing_stream() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + } + + [RetryFact] + public async Task create_with_dont_timeout() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(messageTimeout: TimeSpan.Zero), + userCredentials: TestCredentials.Root + ); + } + + [RetryFact] + public async Task deleting_existing_with_permissions() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToStreamAsync(stream, group, new(), userCredentials: TestCredentials.Root); + await Fixture.Subscriptions.DeleteToStreamAsync(stream, group, userCredentials: TestCredentials.Root); + } + + [RetryFact] + public async Task deleting_existing_with_subscriber() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Subscriptions.CreateToStreamAsync(stream, group, new(), userCredentials: TestCredentials.Root); + + await Fixture.Subscriptions.DeleteToStreamAsync(stream, group, userCredentials: TestCredentials.Root); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.Root); + + Assert.True( + await subscription.Messages.OfType().AnyAsync() + .AsTask() + .WithTimeout() + ); + } + + [RetryFact] + public async Task deleting_nonexistent() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Assert.ThrowsAsync( + () => Fixture.Subscriptions.DeleteToStreamAsync(stream, group, userCredentials: TestCredentials.Root) + ); + } + + [RetryFact] + public async Task happy_case_catching_up_to_link_to_events_manual_ack() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + const int bufferCount = 10; + const int eventWriteCount = bufferCount * 2; + + var events = Fixture.CreateTestEvents(eventWriteCount) + .Select( + (e, i) => new EventData( + e.EventId, + SystemEventTypes.LinkTo, + Encoding.UTF8.GetBytes($"{i}@{stream}"), + contentType: Constants.Metadata.ContentTypes.ApplicationOctetStream + ) + ).ToArray(); + + foreach (var e in events) + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, [e]); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: StreamPosition.Start, resolveLinkTos: true), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream( + stream, + group, + bufferSize: bufferCount, + userCredentials: TestCredentials.Root + ); + + await subscription!.Messages.OfType() + .Take(events.Length) + .ForEachAwaitAsync(e => subscription.Ack(e.ResolvedEvent)) + .WithTimeout(); + } + + [RetryFact] + public async Task happy_case_catching_up_to_normal_events_manual_ack() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + const int bufferCount = 10; + const int eventWriteCount = bufferCount * 2; + + var events = Fixture.CreateTestEvents(eventWriteCount).ToArray(); + + foreach (var e in events) + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, new[] { e }); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: StreamPosition.Start, resolveLinkTos: true), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream( + stream, + group, + bufferSize: bufferCount, + userCredentials: TestCredentials.Root + ); + + await subscription!.Messages.OfType() + .Take(events.Length) + .ForEachAwaitAsync(e => subscription.Ack(e.ResolvedEvent)) + .WithTimeout(); + } + + [RetryFact] + public async Task happy_case_writing_and_subscribing_to_normal_events_manual_ack() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + const int bufferCount = 10; + const int eventWriteCount = bufferCount * 2; + + var events = Fixture.CreateTestEvents(eventWriteCount).ToArray(); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: StreamPosition.End, resolveLinkTos: true), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream( + stream, + group, + bufferSize: bufferCount, + userCredentials: TestCredentials.Root + ); + + foreach (var e in events) + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, [e]); + + await subscription.Messages.OfType() + .Take(events.Length) + .ForEachAwaitAsync(e => subscription.Ack(e.ResolvedEvent)) + .WithTimeout(); + } + + [RetryFact] + public async Task list_without_persistent_subscriptions_should_throw() { + var stream = Fixture.GetStreamName(); + + await Assert.ThrowsAsync( + async () => + await Fixture.Subscriptions.ListToStreamAsync(stream, userCredentials: TestCredentials.Root) + ); + } + + [RetryFact] + public async Task update_existing() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ); + + await Fixture.Subscriptions.UpdateToStreamAsync(stream, group, new(), userCredentials: TestCredentials.Root); + } + + [RetryFact] + public async Task update_existing_with_subscribers() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, Fixture.CreateTestEvents()); + await Fixture.Subscriptions.CreateToStreamAsync(stream, group, new(), userCredentials: TestCredentials.Root); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, userCredentials: TestCredentials.Root); + await using var enumerator = subscription.Messages.GetAsyncEnumerator(); + + await enumerator.MoveNextAsync(); + + await Fixture.Subscriptions.UpdateToStreamAsync(stream, group, new(), userCredentials: TestCredentials.Root); + + var ex = await Assert.ThrowsAsync( + async () => { + while (await enumerator.MoveNextAsync()) { } + } + ).WithTimeout(); + + Assert.Equal(stream, ex.StreamName); + Assert.Equal(group, ex.GroupName); + } + + [Regression.Fact(21, "20.x returns the wrong exception")] + public async Task update_non_existent() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + await Assert.ThrowsAsync( + () => Fixture.Subscriptions.UpdateToStreamAsync( + stream, + group, + new(), + userCredentials: TestCredentials.Root + ) + ); + } + + [RetryFact] + public async Task when_writing_and_subscribing_to_normal_events_manual_nack() { + var stream = Fixture.GetStreamName(); + var group = Fixture.GetGroupName(); + + const int bufferCount = 10; + const int eventWriteCount = bufferCount * 2; + + var events = Fixture.CreateTestEvents(eventWriteCount).ToArray(); + + await Fixture.Subscriptions.CreateToStreamAsync( + stream, + group, + new(startFrom: StreamPosition.Start, resolveLinkTos: true), + userCredentials: TestCredentials.Root + ); + + await using var subscription = Fixture.Subscriptions.SubscribeToStream(stream, group, bufferSize: bufferCount, userCredentials: TestCredentials.Root); + + foreach (var e in events) + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, [e]); + + await subscription.Messages.OfType() + .Take(1) + .ForEachAwaitAsync( + async message => + await subscription.Nack( + PersistentSubscriptionNakEventAction.Park, + "fail", + message.ResolvedEvent + ) + ) + .WithTimeout(); + } +} diff --git a/test/EventStore.Client.Tests/PositionTests.cs b/test/Kurrent.Client.Tests/PositionTests.cs similarity index 95% rename from test/EventStore.Client.Tests/PositionTests.cs rename to test/Kurrent.Client.Tests/PositionTests.cs index b68748af8..fc4401267 100644 --- a/test/EventStore.Client.Tests/PositionTests.cs +++ b/test/Kurrent.Client.Tests/PositionTests.cs @@ -1,11 +1,13 @@ using AutoFixture; +using EventStore.Client; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; +[Trait("Category", "Target:Misc")] public class PositionTests : ValueObjectTests { public PositionTests() : base(new ScenarioFixture()) { } - [Fact] + [RetryFact] public void IsComparable() => Assert.IsAssignableFrom>(_fixture.Create()); [Theory] @@ -16,7 +18,7 @@ public PositionTests() : base(new ScenarioFixture()) { } [AutoScenarioData(typeof(ScenarioFixture))] public void LiveIsGreaterThanAll(Position other) => Assert.True(Position.End > other); - [Fact] + [RetryFact] public void ToStringReturnsExpectedResult() { var sut = _fixture.Create(); Assert.Equal($"C:{sut.CommitPosition}/P:{sut.PreparePosition}", sut.ToString()); @@ -60,4 +62,4 @@ public void TryParse(string s, bool success, Position? expected) { class ScenarioFixture : Fixture { public ScenarioFixture() => Customize(composer => composer.FromFactory(value => new(value, value))); } -} \ No newline at end of file +} diff --git a/test/Kurrent.Client.Tests/ProjectionManagement/DisableProjectionTests.cs b/test/Kurrent.Client.Tests/ProjectionManagement/DisableProjectionTests.cs new file mode 100644 index 000000000..15405cdcc --- /dev/null +++ b/test/Kurrent.Client.Tests/ProjectionManagement/DisableProjectionTests.cs @@ -0,0 +1,22 @@ +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests.Projections; + +[Trait("Category", "Target:ProjectionManagement")] +public class DisableProjectionTests(ITestOutputHelper output, DisableProjectionTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [Fact] + public async Task disable_projection() { + var name = Names.First(); + await Fixture.Projections.DisableAsync(name, userCredentials: TestCredentials.Root); + var result = await Fixture.Projections.GetStatusAsync(name, userCredentials: TestCredentials.Root); + Assert.NotNull(result); + Assert.Contains(["Aborted/Stopped", "Stopped"], x => x == result!.Status); + } + + static readonly string[] Names = ["$streams", "$stream_by_category", "$by_category", "$by_event_type", "$by_correlation_id"]; + + public class CustomFixture : KurrentTemporaryFixture { + public CustomFixture() : base(x => x.RunProjections()) { } + } +} diff --git a/test/Kurrent.Client.Tests/ProjectionManagement/EnableProjectionTests.cs b/test/Kurrent.Client.Tests/ProjectionManagement/EnableProjectionTests.cs new file mode 100644 index 000000000..7261bfb9f --- /dev/null +++ b/test/Kurrent.Client.Tests/ProjectionManagement/EnableProjectionTests.cs @@ -0,0 +1,22 @@ +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests.Projections; + +[Trait("Category", "Target:ProjectionManagement")] +public class EnableProjectionTests(ITestOutputHelper output, EnableProjectionTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [Fact] + public async Task enable_projection() { + var name = Names.First(); + await Fixture.Projections.EnableAsync(name, userCredentials: TestCredentials.Root); + var result = await Fixture.Projections.GetStatusAsync(name, userCredentials: TestCredentials.Root); + Assert.NotNull(result); + Assert.Equal("Running", result.Status); + } + + static readonly string[] Names = ["$streams", "$stream_by_category", "$by_category", "$by_event_type", "$by_correlation_id"]; + + public class CustomFixture : KurrentTemporaryFixture { + public CustomFixture() : base(x => x.RunProjections()) { } + } +} diff --git a/test/Kurrent.Client.Tests/ProjectionManagement/GetProjectionResultTests.cs b/test/Kurrent.Client.Tests/ProjectionManagement/GetProjectionResultTests.cs new file mode 100644 index 000000000..2b2c8ef08 --- /dev/null +++ b/test/Kurrent.Client.Tests/ProjectionManagement/GetProjectionResultTests.cs @@ -0,0 +1,51 @@ +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests.Projections; + +[Trait("Category", "Target:ProjectionManagement")] +public class GetProjectionResultTests(ITestOutputHelper output, GetProjectionResultTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [Fact] + public async Task get_result() { + var name = Fixture.GetProjectionName(); + Result? result = null; + + var projection = $$""" + fromStream('{{name}}').when({ + "$init": function() { return { Count: 0 }; }, + "$any": function(s, e) { s.Count++; return s; } + }); + """; + + await Fixture.Projections.CreateContinuousAsync( + name, + projection, + userCredentials: TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync( + name, + StreamState.NoStream, + Fixture.CreateTestEvents() + ); + + await AssertEx.IsOrBecomesTrue( + async () => { + result = await Fixture.Projections.GetResultAsync(name, userCredentials: TestCredentials.Root); + return result.Count > 0; + } + ); + + Assert.NotNull(result); + Assert.Equal(1, result!.Count); + } + + record Result { + public int Count { get; set; } + } + + public class CustomFixture : KurrentTemporaryFixture { + public CustomFixture() : base(x => x.RunProjections()) { } + } +} diff --git a/test/Kurrent.Client.Tests/ProjectionManagement/GetProjectionStateTests.cs b/test/Kurrent.Client.Tests/ProjectionManagement/GetProjectionStateTests.cs new file mode 100644 index 000000000..f180813ff --- /dev/null +++ b/test/Kurrent.Client.Tests/ProjectionManagement/GetProjectionStateTests.cs @@ -0,0 +1,52 @@ +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests.Projections; + +[Trait("Category", "Target:ProjectionManagement")] +public class GetProjectionStateTests(ITestOutputHelper output, GetProjectionStateTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [Fact] + public async Task get_state() { + var name = Fixture.GetProjectionName(); + + var projection = $$""" + fromStream('{{name}}').when({ + "$init": function() { return { Count: 0 }; }, + "$any": function(s, e) { s.Count++; return s; } + }); + """; + + Result? result = null; + + await Fixture.Projections.CreateContinuousAsync( + name, + projection, + userCredentials: TestCredentials.Root + ); + + await Fixture.Streams.AppendToStreamAsync( + name, + StreamState.NoStream, + Fixture.CreateTestEvents() + ); + + await AssertEx.IsOrBecomesTrue( + async () => { + result = await Fixture.Projections.GetStateAsync(name, userCredentials: TestCredentials.Root); + return result.Count > 0; + } + ); + + Assert.NotNull(result); + Assert.Equal(1, result!.Count); + } + + record Result { + public int Count { get; set; } + } + + public class CustomFixture : KurrentTemporaryFixture { + public CustomFixture() : base(x => x.RunProjections()) { } + } +} diff --git a/test/Kurrent.Client.Tests/ProjectionManagement/GetProjectionStatusTests.cs b/test/Kurrent.Client.Tests/ProjectionManagement/GetProjectionStatusTests.cs new file mode 100644 index 000000000..41ed02932 --- /dev/null +++ b/test/Kurrent.Client.Tests/ProjectionManagement/GetProjectionStatusTests.cs @@ -0,0 +1,22 @@ +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests.Projections; + +[Trait("Category", "Target:ProjectionManagement")] +public class GetProjectionStatusTests(ITestOutputHelper output, GetProjectionStatusTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [Fact] + public async Task get_status() { + var name = Names.First(); + var result = await Fixture.Projections.GetStatusAsync(name, userCredentials: TestCredentials.Root); + + Assert.NotNull(result); + Assert.Equal(name, result.Name); + } + + static readonly string[] Names = ["$streams", "$stream_by_category", "$by_category", "$by_event_type", "$by_correlation_id"]; + + public class CustomFixture : KurrentTemporaryFixture { + public CustomFixture() : base(x => x.RunProjections()) { } + } +} diff --git a/test/Kurrent.Client.Tests/ProjectionManagement/ListAllProjectionsTests.cs b/test/Kurrent.Client.Tests/ProjectionManagement/ListAllProjectionsTests.cs new file mode 100644 index 000000000..18f717efc --- /dev/null +++ b/test/Kurrent.Client.Tests/ProjectionManagement/ListAllProjectionsTests.cs @@ -0,0 +1,36 @@ +// ReSharper disable InconsistentNaming + +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:ProjectionManagement")] +public class ListAllProjectionsTests(ITestOutputHelper output, ListAllProjectionsTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [Fact] + public async Task list_continuous_projections() { + var name = Fixture.GetProjectionName(); + + await Fixture.Projections.CreateContinuousAsync( + name, + "fromAll().when({$init: function (state, ev) {return {};}});", + userCredentials: TestCredentials.Root + ); + + var result = await Fixture.Projections.ListContinuousAsync(userCredentials: TestCredentials.Root) + .ToArrayAsync(); + + Assert.Equal( + result.Select(x => x.Name).OrderBy(x => x), + Names.Concat([name]).OrderBy(x => x) + ); + + Assert.True(result.All(x => x.Mode == "Continuous")); + } + + static readonly string[] Names = ["$streams", "$stream_by_category", "$by_category", "$by_event_type", "$by_correlation_id"]; + + public class CustomFixture : KurrentTemporaryFixture { + public CustomFixture() : base(x => x.RunProjections()) { } + } +} diff --git a/test/Kurrent.Client.Tests/ProjectionManagement/ListContinuousProjectionsTests.cs b/test/Kurrent.Client.Tests/ProjectionManagement/ListContinuousProjectionsTests.cs new file mode 100644 index 000000000..774ad5a0f --- /dev/null +++ b/test/Kurrent.Client.Tests/ProjectionManagement/ListContinuousProjectionsTests.cs @@ -0,0 +1,36 @@ +// ReSharper disable InconsistentNaming + +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:ProjectionManagement")] +public class ListContinuousProjectionsTests(ITestOutputHelper output, ListContinuousProjectionsTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [Fact] + public async Task list_continuous_projections() { + var name = Fixture.GetProjectionName(); + + await Fixture.Projections.CreateContinuousAsync( + name, + "fromAll().when({$init: function (state, ev) {return {};}});", + userCredentials: TestCredentials.Root + ); + + var result = await Fixture.Projections.ListContinuousAsync(userCredentials: TestCredentials.Root) + .ToArrayAsync(); + + Assert.Equal( + result.Select(x => x.Name).OrderBy(x => x), + Names.Concat([name]).OrderBy(x => x) + ); + + Assert.True(result.All(x => x.Mode == "Continuous")); + } + + static readonly string[] Names = ["$streams", "$stream_by_category", "$by_category", "$by_event_type", "$by_correlation_id"]; + + public class CustomFixture : KurrentTemporaryFixture { + public CustomFixture() : base(x => x.RunProjections()) { } + } +} diff --git a/test/Kurrent.Client.Tests/ProjectionManagement/ListOneTimeProjectionsTests.cs b/test/Kurrent.Client.Tests/ProjectionManagement/ListOneTimeProjectionsTests.cs new file mode 100644 index 000000000..d664d24fa --- /dev/null +++ b/test/Kurrent.Client.Tests/ProjectionManagement/ListOneTimeProjectionsTests.cs @@ -0,0 +1,22 @@ +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests.Projections; + +[Trait("Category", "Target:ProjectionManagement")] +public class ListOneTimeProjectionsTests(ITestOutputHelper output, ListOneTimeProjectionsTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [Fact] + public async Task list_one_time_projections() { + await Fixture.Projections.CreateOneTimeAsync("fromAll().when({$init: function (state, ev) {return {};}});", userCredentials: TestCredentials.Root); + + var result = await Fixture.Projections.ListOneTimeAsync(userCredentials: TestCredentials.Root) + .ToArrayAsync(); + + var details = Assert.Single(result); + Assert.Equal("OneTime", details.Mode); + } + + public class CustomFixture : KurrentTemporaryFixture { + public CustomFixture() : base(x => x.RunProjections()) { } + } +} diff --git a/test/Kurrent.Client.Tests/ProjectionManagement/ProjectionManagementTests.cs b/test/Kurrent.Client.Tests/ProjectionManagement/ProjectionManagementTests.cs new file mode 100644 index 000000000..fd8d9b42a --- /dev/null +++ b/test/Kurrent.Client.Tests/ProjectionManagement/ProjectionManagementTests.cs @@ -0,0 +1,54 @@ +// ReSharper disable InconsistentNaming +// ReSharper disable ClassNeverInstantiated.Local + +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:ProjectionManagement")] +public class ProjectionManagementTests(ITestOutputHelper output, ProjectionManagementTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [Fact] + public async Task status_is_aborted() { + var name = Names.First(); + await Fixture.Projections.AbortAsync(name, userCredentials: TestCredentials.Root); + var result = await Fixture.Projections.GetStatusAsync(name, userCredentials: TestCredentials.Root); + Assert.NotNull(result); + Assert.Contains(["Aborted/Stopped", "Stopped"], x => x == result.Status); + } + + [Fact] + public async Task one_time() => + await Fixture.Projections.CreateOneTimeAsync("fromAll().when({$init: function (state, ev) {return {};}});", userCredentials: TestCredentials.Root); + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task continuous(bool trackEmittedStreams) { + var name = Fixture.GetProjectionName(); + + await Fixture.Projections.CreateContinuousAsync( + name, + "fromAll().when({$init: function (state, ev) {return {};}});", + trackEmittedStreams, + userCredentials: TestCredentials.Root + ); + } + + [Fact] + public async Task transient() { + var name = Fixture.GetProjectionName(); + + await Fixture.Projections.CreateTransientAsync( + name, + "fromAll().when({$init: function (state, ev) {return {};}});", + userCredentials: TestCredentials.Root + ); + } + + static readonly string[] Names = ["$streams", "$stream_by_category", "$by_category", "$by_event_type", "$by_correlation_id"]; + + public class CustomFixture : KurrentTemporaryFixture { + public CustomFixture() : base(x => x.RunProjections()) { } + } +} diff --git a/test/Kurrent.Client.Tests/ProjectionManagement/ResetProjectionTests.cs b/test/Kurrent.Client.Tests/ProjectionManagement/ResetProjectionTests.cs new file mode 100644 index 000000000..71d5f8fcc --- /dev/null +++ b/test/Kurrent.Client.Tests/ProjectionManagement/ResetProjectionTests.cs @@ -0,0 +1,23 @@ +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests.Projections; + +[Trait("Category", "Target:ProjectionManagement")] +public class ResetProjectionTests(ITestOutputHelper output, ResetProjectionTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [Fact] + public async Task reset_projection() { + var name = Names.First(); + await Fixture.Projections.ResetAsync(name, userCredentials: TestCredentials.Root); + var result = await Fixture.Projections.GetStatusAsync(name, userCredentials: TestCredentials.Root); + + Assert.NotNull(result); + Assert.Equal("Running", result.Status); + } + + static readonly string[] Names = ["$streams", "$stream_by_category", "$by_category", "$by_event_type", "$by_correlation_id"]; + + public class CustomFixture : KurrentTemporaryFixture { + public CustomFixture() : base(x => x.RunProjections()) { } + } +} diff --git a/test/Kurrent.Client.Tests/ProjectionManagement/RestartSubsystemTests.cs b/test/Kurrent.Client.Tests/ProjectionManagement/RestartSubsystemTests.cs new file mode 100644 index 000000000..6431fbee5 --- /dev/null +++ b/test/Kurrent.Client.Tests/ProjectionManagement/RestartSubsystemTests.cs @@ -0,0 +1,20 @@ +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests.Projections; + +[Trait("Category", "Target:ProjectionManagement")] +public class RestartSubsystemTests(ITestOutputHelper output, RestartSubsystemTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [Fact] + public async Task restart_subsystem_does_not_throw() => + await Fixture.Projections.RestartSubsystemAsync(userCredentials: TestCredentials.Root); + + [Fact] + public async Task restart_subsystem_throws_when_given_no_credentials() => + await Assert.ThrowsAsync(() => Fixture.Projections.RestartSubsystemAsync(userCredentials: TestCredentials.TestUser1)); + + public class CustomFixture : KurrentTemporaryFixture { + public CustomFixture() : base(x => x.RunProjections()) { } + } +} diff --git a/test/Kurrent.Client.Tests/ProjectionManagement/UpdateProjectionTests.cs b/test/Kurrent.Client.Tests/ProjectionManagement/UpdateProjectionTests.cs new file mode 100644 index 000000000..1af8e880b --- /dev/null +++ b/test/Kurrent.Client.Tests/ProjectionManagement/UpdateProjectionTests.cs @@ -0,0 +1,31 @@ +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests.Projections; + +[Trait("Category", "Target:ProjectionManagement")] +public class UpdateProjectionTests(ITestOutputHelper output, UpdateProjectionTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [Theory] + [InlineData(true)] + [InlineData(false)] + [InlineData(null)] + public async Task update_projection(bool? emitEnabled) { + var name = Fixture.GetProjectionName(); + await Fixture.Projections.CreateContinuousAsync( + name, + "fromAll().when({$init: function (state, ev) {return {};}});", + userCredentials: TestCredentials.Root + ); + + await Fixture.Projections.UpdateAsync( + name, + "fromAll().when({$init: function (s, e) {return {};}});", + emitEnabled, + userCredentials: TestCredentials.Root + ); + } + + public class CustomFixture : KurrentTemporaryFixture { + public CustomFixture() : base(x => x.RunProjections()) { } + } +} diff --git a/test/EventStore.Client.Tests/RegularFilterExpressionTests.cs b/test/Kurrent.Client.Tests/RegularFilterExpressionTests.cs similarity index 80% rename from test/EventStore.Client.Tests/RegularFilterExpressionTests.cs rename to test/Kurrent.Client.Tests/RegularFilterExpressionTests.cs index 481e5cb46..4fe4f6650 100644 --- a/test/EventStore.Client.Tests/RegularFilterExpressionTests.cs +++ b/test/Kurrent.Client.Tests/RegularFilterExpressionTests.cs @@ -1,12 +1,14 @@ using System.Text.RegularExpressions; using AutoFixture; +using EventStore.Client; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; +[Trait("Category", "Target:Misc")] public class RegularFilterExpressionTests : ValueObjectTests { public RegularFilterExpressionTests() : base(new ScenarioFixture()) { } class ScenarioFixture : Fixture { public ScenarioFixture() => Customize(composer => composer.FromFactory(value => new(value))); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Security/all_stream_with_no_acl_security.cs b/test/Kurrent.Client.Tests/Security/AllStreamWithNoAclSecurityTests.cs similarity index 88% rename from test/EventStore.Client.Streams.Tests/Security/all_stream_with_no_acl_security.cs rename to test/Kurrent.Client.Tests/Security/AllStreamWithNoAclSecurityTests.cs index 215e0f05d..e33f707ac 100644 --- a/test/EventStore.Client.Streams.Tests/Security/all_stream_with_no_acl_security.cs +++ b/test/Kurrent.Client.Tests/Security/AllStreamWithNoAclSecurityTests.cs @@ -1,7 +1,12 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; -[Trait("Category", "Security")] -public class all_stream_with_no_acl_security(ITestOutputHelper output, all_stream_with_no_acl_security.CustomFixture fixture) : EventStoreTests(output, fixture) { +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Security")] +public class AllStreamWithNoAclSecurityTests(ITestOutputHelper output, AllStreamWithNoAclSecurityTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { [Fact] public async Task write_to_all_is_never_allowed() { await Assert.ThrowsAsync(() => Fixture.AppendStream(SecurityFixture.AllStream)); @@ -59,4 +64,4 @@ protected override async Task Given() { await Streams.SetStreamMetadataAsync(AllStream, StreamState.Any, new(), userCredentials: TestCredentials.Root); } } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Security/delete_stream_security.cs b/test/Kurrent.Client.Tests/Security/DeleteStreamSecurityTests.cs similarity index 86% rename from test/EventStore.Client.Streams.Tests/Security/delete_stream_security.cs rename to test/Kurrent.Client.Tests/Security/DeleteStreamSecurityTests.cs index 61e6253ce..69b31609c 100644 --- a/test/EventStore.Client.Streams.Tests/Security/delete_stream_security.cs +++ b/test/Kurrent.Client.Tests/Security/DeleteStreamSecurityTests.cs @@ -1,7 +1,11 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; -[Trait("Category", "Security")] -public class delete_stream_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Security")] +public class DeleteStreamSecurityTests(ITestOutputHelper output, SecurityFixture fixture) : KurrentTemporaryTests(output, fixture) { [Fact] public async Task delete_of_all_is_never_allowed() { await Assert.ThrowsAsync(() => Fixture.DeleteStream(SecurityFixture.AllStream)); @@ -113,7 +117,7 @@ public async Task deleting_normal_all_stream_with_admin_user_is_allowed() { public async Task deleting_system_no_acl_stream_with_no_user_is_not_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new() + metadataPermanent: new() ); await Assert.ThrowsAsync(() => Fixture.DeleteStream(streamId)); @@ -123,7 +127,7 @@ public async Task deleting_system_no_acl_stream_with_no_user_is_not_allowed() { public async Task deleting_system_no_acl_stream_with_existing_user_is_not_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new() + metadataPermanent: new() ); await Assert.ThrowsAsync(() => Fixture.DeleteStream(streamId, TestCredentials.TestUser1)); @@ -133,7 +137,7 @@ public async Task deleting_system_no_acl_stream_with_existing_user_is_not_allowe public async Task deleting_system_no_acl_stream_with_admin_user_is_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new() + metadataPermanent: new() ); await Fixture.DeleteStream(streamId, TestCredentials.TestAdmin); @@ -143,7 +147,7 @@ public async Task deleting_system_no_acl_stream_with_admin_user_is_allowed() { public async Task deleting_system_user_stream_with_no_user_is_not_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new(acl: new(deleteRole: TestCredentials.TestUser1.Username)) + metadataPermanent: new(acl: new(deleteRole: TestCredentials.TestUser1.Username)) ); await Assert.ThrowsAsync(() => Fixture.DeleteStream(streamId)); @@ -153,7 +157,7 @@ public async Task deleting_system_user_stream_with_no_user_is_not_allowed() { public async Task deleting_system_user_stream_with_not_authorized_user_is_not_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new(acl: new(deleteRole: TestCredentials.TestUser1.Username)) + metadataPermanent: new(acl: new(deleteRole: TestCredentials.TestUser1.Username)) ); await Assert.ThrowsAsync(() => Fixture.DeleteStream(streamId, TestCredentials.TestUser2)); @@ -163,7 +167,7 @@ public async Task deleting_system_user_stream_with_not_authorized_user_is_not_al public async Task deleting_system_user_stream_with_authorized_user_is_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new(acl: new(deleteRole: TestCredentials.TestUser1.Username)) + metadataPermanent: new(acl: new(deleteRole: TestCredentials.TestUser1.Username)) ); await Fixture.DeleteStream(streamId, TestCredentials.TestUser1); @@ -173,7 +177,7 @@ public async Task deleting_system_user_stream_with_authorized_user_is_allowed() public async Task deleting_system_user_stream_with_admin_user_is_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new(acl: new(deleteRole: TestCredentials.TestUser1.Username)) + metadataPermanent: new(acl: new(deleteRole: TestCredentials.TestUser1.Username)) ); await Fixture.DeleteStream(streamId, TestCredentials.TestAdmin); @@ -183,7 +187,7 @@ public async Task deleting_system_user_stream_with_admin_user_is_allowed() { public async Task deleting_system_admin_stream_with_no_user_is_not_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new(acl: new(deleteRole: SystemRoles.Admins)) + metadataPermanent: new(acl: new(deleteRole: SystemRoles.Admins)) ); await Assert.ThrowsAsync(() => Fixture.DeleteStream(streamId)); @@ -193,7 +197,7 @@ public async Task deleting_system_admin_stream_with_no_user_is_not_allowed() { public async Task deleting_system_admin_stream_with_existing_user_is_not_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new(acl: new(deleteRole: SystemRoles.Admins)) + metadataPermanent: new(acl: new(deleteRole: SystemRoles.Admins)) ); await Assert.ThrowsAsync(() => Fixture.DeleteStream(streamId, TestCredentials.TestUser1)); @@ -203,7 +207,7 @@ public async Task deleting_system_admin_stream_with_existing_user_is_not_allowed public async Task deleting_system_admin_stream_with_admin_user_is_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new(acl: new(deleteRole: SystemRoles.Admins)) + metadataPermanent: new(acl: new(deleteRole: SystemRoles.Admins)) ); await Fixture.DeleteStream(streamId, TestCredentials.TestAdmin); @@ -213,7 +217,7 @@ public async Task deleting_system_admin_stream_with_admin_user_is_allowed() { public async Task deleting_system_all_stream_with_no_user_is_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new(acl: new(deleteRole: SystemRoles.All)) + metadataPermanent: new(acl: new(deleteRole: SystemRoles.All)) ); await Fixture.DeleteStream(streamId); @@ -223,7 +227,7 @@ public async Task deleting_system_all_stream_with_no_user_is_allowed() { public async Task deleting_system_all_stream_with_existing_user_is_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new(acl: new(deleteRole: SystemRoles.All)) + metadataPermanent: new(acl: new(deleteRole: SystemRoles.All)) ); await Fixture.DeleteStream(streamId, TestCredentials.TestUser1); @@ -233,9 +237,9 @@ public async Task deleting_system_all_stream_with_existing_user_is_allowed() { public async Task deleting_system_all_stream_with_admin_user_is_allowed() { var streamId = await Fixture.CreateStreamWithMeta( streamId: $"${Fixture.GetStreamName()}", - metadata: new(acl: new(deleteRole: SystemRoles.All)) + metadataPermanent: new(acl: new(deleteRole: SystemRoles.All)) ); await Fixture.DeleteStream(streamId, TestCredentials.TestAdmin); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Security/multiple_role_security.cs b/test/Kurrent.Client.Tests/Security/MultipleRoleSecurityTests.cs similarity index 80% rename from test/EventStore.Client.Streams.Tests/Security/multiple_role_security.cs rename to test/Kurrent.Client.Tests/Security/MultipleRoleSecurityTests.cs index 3195c22df..f38d3fd27 100644 --- a/test/EventStore.Client.Streams.Tests/Security/multiple_role_security.cs +++ b/test/Kurrent.Client.Tests/Security/MultipleRoleSecurityTests.cs @@ -1,7 +1,12 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; -[Trait("Category", "Security")] -public class multiple_role_security(ITestOutputHelper output, multiple_role_security.CustomFixture fixture) : EventStoreTests(output, fixture) { +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Security")] +public class MultipleRoleSecurityTests(ITestOutputHelper output, MultipleRoleSecurityTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { [Fact] public async Task multiple_roles_are_handled_correctly() { await Assert.ThrowsAsync(() => Fixture.ReadEvent("usr-stream")); @@ -20,7 +25,7 @@ public async Task multiple_roles_are_handled_correctly() { } [AnonymousAccess.Fact] - public async Task multiple_roles_are_handled_correctly_without_authentication() => + public async Task multiple_roles_are_handled_correctly_without_authentication() => await Fixture.DeleteStream("usr-stream1"); public class CustomFixture : SecurityFixture { @@ -36,4 +41,4 @@ protected override async Task When() { await Streams.SetSystemSettingsAsync(settings, userCredentials: TestCredentials.TestAdmin); } } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security_for_all.cs b/test/Kurrent.Client.Tests/Security/OverridenSystemStreamSecurityForAllTests.cs similarity index 84% rename from test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security_for_all.cs rename to test/Kurrent.Client.Tests/Security/OverridenSystemStreamSecurityForAllTests.cs index 2364717bb..ebc66f3c9 100644 --- a/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security_for_all.cs +++ b/test/Kurrent.Client.Tests/Security/OverridenSystemStreamSecurityForAllTests.cs @@ -1,7 +1,12 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; -[Trait("Category", "Security")] -public class overriden_system_stream_security_for_all(ITestOutputHelper output, overriden_system_stream_security_for_all.CustomFixture fixture) : EventStoreTests(output, fixture) { +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Security")] +public class OverridenSystemStreamSecurityForAllTests(ITestOutputHelper output, OverridenSystemStreamSecurityForAllTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { [Fact] public async Task operations_on_system_stream_succeeds_for_user() { var stream = $"${Fixture.GetStreamName()}"; diff --git a/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security.cs b/test/Kurrent.Client.Tests/Security/OverridenSystemStreamSecurityTests.cs similarity index 90% rename from test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security.cs rename to test/Kurrent.Client.Tests/Security/OverridenSystemStreamSecurityTests.cs index fcdaec541..eded40e7e 100644 --- a/test/EventStore.Client.Streams.Tests/Security/overriden_system_stream_security.cs +++ b/test/Kurrent.Client.Tests/Security/OverridenSystemStreamSecurityTests.cs @@ -1,7 +1,11 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; -[Trait("Category", "Security")] -public class overriden_system_stream_security(ITestOutputHelper output, overriden_system_stream_security.CustomFixture fixture) : EventStoreTests(output, fixture) { +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Security")] +public class OverridenSystemStreamSecurityTests(ITestOutputHelper output, OverridenSystemStreamSecurityTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { [Fact] public async Task operations_on_system_stream_succeed_for_authorized_user() { var stream = $"${Fixture.GetStreamName()}"; diff --git a/test/EventStore.Client.Streams.Tests/Security/overriden_user_stream_security.cs b/test/Kurrent.Client.Tests/Security/OverridenUserStreamSecurityTests.cs similarity index 90% rename from test/EventStore.Client.Streams.Tests/Security/overriden_user_stream_security.cs rename to test/Kurrent.Client.Tests/Security/OverridenUserStreamSecurityTests.cs index 287d5a64f..445bf564b 100644 --- a/test/EventStore.Client.Streams.Tests/Security/overriden_user_stream_security.cs +++ b/test/Kurrent.Client.Tests/Security/OverridenUserStreamSecurityTests.cs @@ -1,7 +1,11 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; -[Trait("Category", "Security")] -public class overriden_user_stream_security(ITestOutputHelper output, overriden_user_stream_security.CustomFixture fixture) : EventStoreTests(output, fixture) { +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Security")] +public class OverridenUserStreamSecurityTests(ITestOutputHelper output, OverridenUserStreamSecurityTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { [Fact] public async Task operations_on_user_stream_succeeds_for_authorized_user() { var stream = Fixture.GetStreamName(); diff --git a/test/EventStore.Client.Streams.Tests/Security/read_all_security.cs b/test/Kurrent.Client.Tests/Security/ReadAllSecurityTests.cs similarity index 80% rename from test/EventStore.Client.Streams.Tests/Security/read_all_security.cs rename to test/Kurrent.Client.Tests/Security/ReadAllSecurityTests.cs index 01089db2e..fcbf0980f 100644 --- a/test/EventStore.Client.Streams.Tests/Security/read_all_security.cs +++ b/test/Kurrent.Client.Tests/Security/ReadAllSecurityTests.cs @@ -1,7 +1,11 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; -[Trait("Category", "Security")] -public class read_all_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Security")] +public class ReadAllSecurityTests(ITestOutputHelper output, SecurityFixture fixture) : KurrentTemporaryTests(output, fixture) { [Fact] public async Task reading_all_with_not_existing_credentials_is_not_authenticated() { await Assert.ThrowsAsync(() => Fixture.ReadAllForward(TestCredentials.TestBadUser)); @@ -31,4 +35,4 @@ public async Task reading_all_with_admin_credentials_succeeds() { await Fixture.ReadAllForward(TestCredentials.TestAdmin); await Fixture.ReadAllBackward(TestCredentials.TestAdmin); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Security/read_stream_meta_security.cs b/test/Kurrent.Client.Tests/Security/ReadStreamMetaSecurityTests.cs similarity index 72% rename from test/EventStore.Client.Streams.Tests/Security/read_stream_meta_security.cs rename to test/Kurrent.Client.Tests/Security/ReadStreamMetaSecurityTests.cs index b3a7e7afa..4bdb20689 100644 --- a/test/EventStore.Client.Streams.Tests/Security/read_stream_meta_security.cs +++ b/test/Kurrent.Client.Tests/Security/ReadStreamMetaSecurityTests.cs @@ -1,12 +1,14 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; -[Trait("Category", "Security")] -public class read_stream_meta_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Security")] +public class ReadStreamMetaSecurityTests(ITestOutputHelper output, SecurityFixture fixture) : KurrentTemporaryTests(output, fixture) { [Fact] public async Task reading_stream_meta_with_not_existing_credentials_is_not_authenticated() => - await Assert.ThrowsAsync( - () => Fixture.ReadMeta(SecurityFixture.MetaReadStream, TestCredentials.TestBadUser) - ); + await Assert.ThrowsAsync(() => Fixture.ReadMeta(SecurityFixture.MetaReadStream, TestCredentials.TestBadUser)); [Fact] public async Task reading_stream_meta_with_no_credentials_is_denied() => @@ -14,9 +16,7 @@ public async Task reading_stream_meta_with_no_credentials_is_denied() => [Fact] public async Task reading_stream_meta_with_not_authorized_user_credentials_is_denied() => - await Assert.ThrowsAsync( - () => Fixture.ReadMeta(SecurityFixture.MetaReadStream, TestCredentials.TestUser2) - ); + await Assert.ThrowsAsync(() => Fixture.ReadMeta(SecurityFixture.MetaReadStream, TestCredentials.TestUser2)); [Fact] public async Task reading_stream_meta_with_authorized_user_credentials_succeeds() => @@ -31,9 +31,7 @@ public async Task reading_stream_meta_with_admin_user_credentials_succeeds() => [Fact] public async Task reading_no_acl_stream_meta_is_not_authenticated_when_not_existing_credentials_are_passed() => - await Assert.ThrowsAsync( - () => Fixture.ReadMeta(SecurityFixture.NoAclStream, TestCredentials.TestBadUser) - ); + await Assert.ThrowsAsync(() => Fixture.ReadMeta(SecurityFixture.NoAclStream, TestCredentials.TestBadUser)); [Fact] public async Task reading_no_acl_stream_meta_succeeds_when_any_existing_user_credentials_are_passed() { @@ -52,9 +50,7 @@ public async Task reading_all_access_normal_stream_meta_succeeds_when_no_credent [Fact] public async Task reading_all_access_normal_stream_meta_is_not_authenticated_when_not_existing_credentials_are_passed() => - await Assert.ThrowsAsync( - () => Fixture.ReadMeta(SecurityFixture.NormalAllStream, TestCredentials.TestBadUser) - ); + await Assert.ThrowsAsync(() => Fixture.ReadMeta(SecurityFixture.NormalAllStream, TestCredentials.TestBadUser)); [Fact] public async Task @@ -66,4 +62,4 @@ public async Task [Fact] public async Task reading_all_access_normal_stream_meta_succeeds_when_admin_user_credentials_are_passed() => await Fixture.ReadMeta(SecurityFixture.NormalAllStream, TestCredentials.TestAdmin); -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Security/read_stream_security.cs b/test/Kurrent.Client.Tests/Security/ReadStreamSecurityTests.cs similarity index 95% rename from test/EventStore.Client.Streams.Tests/Security/read_stream_security.cs rename to test/Kurrent.Client.Tests/Security/ReadStreamSecurityTests.cs index 206627128..7c3795a44 100644 --- a/test/EventStore.Client.Streams.Tests/Security/read_stream_security.cs +++ b/test/Kurrent.Client.Tests/Security/ReadStreamSecurityTests.cs @@ -1,7 +1,11 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; -[Trait("Category", "Security")] -public class read_stream_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Security")] +public class ReadStreamSecurityTests(ITestOutputHelper output, SecurityFixture fixture) : KurrentTemporaryTests(output, fixture) { [Fact] public async Task reading_stream_with_not_existing_credentials_is_not_authenticated() { await Assert.ThrowsAsync(() => Fixture.ReadEvent(SecurityFixture.ReadStream, TestCredentials.TestBadUser)); @@ -26,7 +30,7 @@ public async Task reading_stream_with_not_authorized_user_credentials_is_denied( [Fact] public async Task reading_stream_with_authorized_user_credentials_succeeds() { await Fixture.AppendStream(SecurityFixture.ReadStream, TestCredentials.TestUser1); - + await Fixture.ReadEvent(SecurityFixture.ReadStream, TestCredentials.TestUser1); await Fixture.ReadStreamForward(SecurityFixture.ReadStream, TestCredentials.TestUser1); await Fixture.ReadStreamBackward(SecurityFixture.ReadStream, TestCredentials.TestUser1); @@ -110,4 +114,4 @@ public async Task reading_all_access_normal_stream_succeeds_when_admin_user_cred await Fixture.ReadStreamForward(SecurityFixture.NormalAllStream, TestCredentials.TestAdmin); await Fixture.ReadStreamBackward(SecurityFixture.NormalAllStream, TestCredentials.TestAdmin); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Security/SecurityFixture.cs b/test/Kurrent.Client.Tests/Security/SecurityFixture.cs similarity index 97% rename from test/EventStore.Client.Streams.Tests/Security/SecurityFixture.cs rename to test/Kurrent.Client.Tests/Security/SecurityFixture.cs index 2ffc0b73c..366284a11 100644 --- a/test/EventStore.Client.Streams.Tests/Security/SecurityFixture.cs +++ b/test/Kurrent.Client.Tests/Security/SecurityFixture.cs @@ -1,8 +1,9 @@ using System.Runtime.CompilerServices; +using EventStore.Client; +using Kurrent.Client; +using Kurrent.Client.Tests.TestNode; -namespace EventStore.Client.Streams.Tests; - -public class SecurityFixture : EventStoreFixture { +public class SecurityFixture : KurrentTemporaryFixture { public const string NoAclStream = nameof(NoAclStream); public const string ReadStream = nameof(ReadStream); public const string WriteStream = nameof(WriteStream); @@ -41,7 +42,7 @@ await Users.CreateUserWithRetry( TestCredentials.TestAdmin.Password!, TestCredentials.Root ).WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); - + await Given(); await When(); }; @@ -245,6 +246,7 @@ public Task WriteMeta(string streamId, UserCredentials? userCreden public async Task SubscribeToStream(string streamId, UserCredentials? userCredentials = default) { await using var subscription = Streams.SubscribeToStream(streamId, FromStream.Start, userCredentials: userCredentials); + await subscription .Messages.OfType().AnyAsync().AsTask() .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); @@ -253,16 +255,17 @@ await subscription public async Task SubscribeToAll(UserCredentials? userCredentials = default) { await using var subscription = Streams.SubscribeToAll(FromAll.Start, userCredentials: userCredentials); + await subscription .Messages.OfType().AnyAsync().AsTask() .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); } - - public async Task CreateStreamWithMeta(StreamMetadata metadata, [CallerMemberName] string streamId = "") { + + public async Task CreateStreamWithMeta(StreamMetadata metadataPermanent, [CallerMemberName] string streamId = "") { await Streams.SetStreamMetadataAsync( streamId, StreamState.NoStream, - metadata, + metadataPermanent, userCredentials: TestCredentials.TestAdmin ) .WithTimeout(TimeSpan.FromMilliseconds(TimeoutMs)); diff --git a/test/EventStore.Client.Streams.Tests/Security/stream_security_inheritance.cs b/test/Kurrent.Client.Tests/Security/StreamSecurityInheritanceTests.cs similarity index 94% rename from test/EventStore.Client.Streams.Tests/Security/stream_security_inheritance.cs rename to test/Kurrent.Client.Tests/Security/StreamSecurityInheritanceTests.cs index 1e1221e16..cb6d0b177 100644 --- a/test/EventStore.Client.Streams.Tests/Security/stream_security_inheritance.cs +++ b/test/Kurrent.Client.Tests/Security/StreamSecurityInheritanceTests.cs @@ -1,8 +1,13 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; -[Trait("Category", "Security")] -public class stream_security_inheritance(ITestOutputHelper output, stream_security_inheritance.CustomFixture fixture) : EventStoreTests(output, fixture) { - [Fact] +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Security")] +public class StreamSecurityInheritanceTests(ITestOutputHelper output, StreamSecurityInheritanceTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { + [RetryFact] public async Task acl_inheritance_is_working_properly_on_user_streams() { await Assert.ThrowsAsync(() => Fixture.AppendStream("user-no-acl")); await Fixture.AppendStream("user-no-acl", TestCredentials.TestUser1); @@ -54,7 +59,7 @@ public async Task acl_inheritance_is_working_properly_on_user_streams_when_not_a await Fixture.ReadEvent("user-no-acl"); } - [Fact] + [RetryFact] public async Task acl_inheritance_is_working_properly_on_system_streams() { await Assert.ThrowsAsync(() => Fixture.AppendStream("$sys-no-acl")); await Fixture.AppendStream("$sys-no-acl", TestCredentials.TestUser1); @@ -181,4 +186,4 @@ await Streams.SetStreamMetadataAsync( ); } } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Security/subscribe_to_all_security.cs b/test/Kurrent.Client.Tests/Security/SubscribeToAllSecurityTests.cs similarity index 73% rename from test/EventStore.Client.Streams.Tests/Security/subscribe_to_all_security.cs rename to test/Kurrent.Client.Tests/Security/SubscribeToAllSecurityTests.cs index 48b62a52d..ba3cea9bc 100644 --- a/test/EventStore.Client.Streams.Tests/Security/subscribe_to_all_security.cs +++ b/test/Kurrent.Client.Tests/Security/SubscribeToAllSecurityTests.cs @@ -1,7 +1,11 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; -[Trait("Category", "Security")] -public class subscribe_to_all_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Security")] +public class SubscribeToAllSecurityTests(ITestOutputHelper output, SecurityFixture fixture) : KurrentTemporaryTests(output, fixture) { [Fact] public async Task subscribing_to_all_with_not_existing_credentials_is_not_authenticated() => await Assert.ThrowsAsync(() => Fixture.SubscribeToAll(TestCredentials.TestBadUser)); @@ -18,4 +22,4 @@ public async Task subscribing_to_all_with_not_authorized_user_credentials_is_den [Fact] public async Task subscribing_to_all_with_admin_user_credentials_succeeds() => await Fixture.SubscribeToAll(TestCredentials.TestAdmin); -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Security/subscribe_to_stream_security.cs b/test/Kurrent.Client.Tests/Security/SubscribeToStreamSecurityTests.cs similarity index 77% rename from test/EventStore.Client.Streams.Tests/Security/subscribe_to_stream_security.cs rename to test/Kurrent.Client.Tests/Security/SubscribeToStreamSecurityTests.cs index 0af3f8da9..e1226122b 100644 --- a/test/EventStore.Client.Streams.Tests/Security/subscribe_to_stream_security.cs +++ b/test/Kurrent.Client.Tests/Security/SubscribeToStreamSecurityTests.cs @@ -1,13 +1,15 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; -[Trait("Category", "Security")] -public class subscribe_to_stream_security(ITestOutputHelper output, SecurityFixture fixture) - : EventStoreTests(output, fixture) { +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Security")] +public class SubscribeToStreamSecurityTests(ITestOutputHelper output, SecurityFixture fixture) + : KurrentTemporaryTests(output, fixture) { [Fact] public async Task subscribing_to_stream_with_not_existing_credentials_is_not_authenticated() => - await Assert.ThrowsAsync( - () => Fixture.SubscribeToStream(SecurityFixture.ReadStream, TestCredentials.TestBadUser) - ); + await Assert.ThrowsAsync(() => Fixture.SubscribeToStream(SecurityFixture.ReadStream, TestCredentials.TestBadUser)); [Fact] public async Task subscribing_to_stream_with_no_credentials_is_denied() => @@ -15,9 +17,7 @@ public async Task subscribing_to_stream_with_no_credentials_is_denied() => [Fact] public async Task subscribing_to_stream_with_not_authorized_user_credentials_is_denied() => - await Assert.ThrowsAsync( - () => Fixture.SubscribeToStream(SecurityFixture.ReadStream, TestCredentials.TestUser2) - ); + await Assert.ThrowsAsync(() => Fixture.SubscribeToStream(SecurityFixture.ReadStream, TestCredentials.TestUser2)); [Fact] public async Task reading_stream_with_authorized_user_credentials_succeeds() { @@ -39,9 +39,7 @@ public async Task subscribing_to_no_acl_stream_succeeds_when_no_credentials_are_ [Fact] public async Task subscribing_to_no_acl_stream_is_not_authenticated_when_not_existing_credentials_are_passed() => - await Assert.ThrowsAsync( - () => Fixture.SubscribeToStream(SecurityFixture.NoAclStream, TestCredentials.TestBadUser) - ); + await Assert.ThrowsAsync(() => Fixture.SubscribeToStream(SecurityFixture.NoAclStream, TestCredentials.TestBadUser)); [Fact] public async Task subscribing_to_no_acl_stream_succeeds_when_any_existing_user_credentials_are_passed() { @@ -65,9 +63,7 @@ public async Task subscribing_to_all_access_normal_stream_succeeds_when_no_crede [Fact] public async Task subscribing_to_all_access_normal_stream_is_not_authenticated_when_not_existing_credentials_are_passed() => - await Assert.ThrowsAsync( - () => Fixture.SubscribeToStream(SecurityFixture.NormalAllStream, TestCredentials.TestBadUser) - ); + await Assert.ThrowsAsync(() => Fixture.SubscribeToStream(SecurityFixture.NormalAllStream, TestCredentials.TestBadUser)); [Fact] public async Task subscribing_to_all_access_normal_stream_succeeds_when_any_existing_user_credentials_are_passed() { diff --git a/test/EventStore.Client.Streams.Tests/Security/system_stream_security.cs b/test/Kurrent.Client.Tests/Security/SystemStreamSecurityTests.cs similarity index 94% rename from test/EventStore.Client.Streams.Tests/Security/system_stream_security.cs rename to test/Kurrent.Client.Tests/Security/SystemStreamSecurityTests.cs index c4e001b4a..720ae8ec1 100644 --- a/test/EventStore.Client.Streams.Tests/Security/system_stream_security.cs +++ b/test/Kurrent.Client.Tests/Security/SystemStreamSecurityTests.cs @@ -1,7 +1,11 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; -[Trait("Category", "Security")] -public class system_stream_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Security")] +public class SystemStreamSecurityTests(ITestOutputHelper output, SecurityFixture fixture) : KurrentTemporaryTests(output, fixture) { [Fact] public async Task operations_on_system_stream_with_no_acl_set_fail_for_non_admin() { await Assert.ThrowsAsync(() => Fixture.ReadEvent("$system-no-acl", TestCredentials.TestUser1)); @@ -40,7 +44,9 @@ public async Task operations_on_system_stream_with_acl_set_to_usual_user_fail_fo await Assert.ThrowsAsync(() => Fixture.AppendStream(SecurityFixture.SystemAclStream, TestCredentials.TestUser2)); await Assert.ThrowsAsync(() => Fixture.ReadMeta(SecurityFixture.SystemAclStream, TestCredentials.TestUser2)); - await Assert.ThrowsAsync(() => Fixture.WriteMeta(SecurityFixture.SystemAclStream, TestCredentials.TestUser2, TestCredentials.TestUser1.Username)); + await Assert.ThrowsAsync( + () => Fixture.WriteMeta(SecurityFixture.SystemAclStream, TestCredentials.TestUser2, TestCredentials.TestUser1.Username) + ); await Assert.ThrowsAsync(() => Fixture.SubscribeToStream(SecurityFixture.SystemAclStream, TestCredentials.TestUser2)); } diff --git a/test/EventStore.Client.Streams.Tests/Security/write_stream_meta_security.cs b/test/Kurrent.Client.Tests/Security/WriteStreamMetaSecurityTests.cs similarity index 85% rename from test/EventStore.Client.Streams.Tests/Security/write_stream_meta_security.cs rename to test/Kurrent.Client.Tests/Security/WriteStreamMetaSecurityTests.cs index 9b003795c..942a155cc 100644 --- a/test/EventStore.Client.Streams.Tests/Security/write_stream_meta_security.cs +++ b/test/Kurrent.Client.Tests/Security/WriteStreamMetaSecurityTests.cs @@ -1,7 +1,11 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; -[Trait("Category", "Security")] -public class write_stream_meta_security(ITestOutputHelper output, SecurityFixture fixture) : EventStoreTests(output, fixture) { +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Security")] +public class WriteStreamMetaSecurityTests(ITestOutputHelper output, SecurityFixture fixture) : KurrentTemporaryTests(output, fixture) { [Fact] public async Task writing_meta_with_not_existing_credentials_is_not_authenticated() => await Assert.ThrowsAsync( @@ -19,7 +23,8 @@ public async Task writing_meta_to_stream_with_no_credentials_is_denied() => [Fact] public async Task writing_meta_to_stream_with_not_authorized_user_credentials_is_denied() => - await Assert.ThrowsAsync(() => + await Assert.ThrowsAsync( + () => Fixture.WriteMeta( SecurityFixture.MetaWriteStream, TestCredentials.TestUser2, @@ -66,7 +71,9 @@ public async Task writing_meta_to_all_access_normal_stream_succeeds_when_no_cred [Fact] public async Task writing_meta_to_all_access_normal_stream_is_not_authenticated_when_not_existing_credentials_are_passed() => - await Assert.ThrowsAsync(() => Fixture.WriteMeta(SecurityFixture.NormalAllStream, TestCredentials.TestBadUser, SystemRoles.All)); + await Assert.ThrowsAsync( + () => Fixture.WriteMeta(SecurityFixture.NormalAllStream, TestCredentials.TestBadUser, SystemRoles.All) + ); [Fact] public async Task @@ -78,4 +85,4 @@ public async Task [Fact] public async Task writing_meta_to_all_access_normal_stream_succeeds_when_admin_user_credentials_are_passed() => await Fixture.WriteMeta(SecurityFixture.NormalAllStream, TestCredentials.TestAdmin, SystemRoles.All); -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Security/write_stream_security.cs b/test/Kurrent.Client.Tests/Security/WriteStreamSecurityTests.cs similarity index 91% rename from test/EventStore.Client.Streams.Tests/Security/write_stream_security.cs rename to test/Kurrent.Client.Tests/Security/WriteStreamSecurityTests.cs index d002d37c9..67ef35bc5 100644 --- a/test/EventStore.Client.Streams.Tests/Security/write_stream_security.cs +++ b/test/Kurrent.Client.Tests/Security/WriteStreamSecurityTests.cs @@ -1,8 +1,10 @@ -namespace EventStore.Client.Streams.Tests; +using EventStore.Client; -[Trait("Category", "Security")] -public class write_stream_security : IClassFixture { - public write_stream_security(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Security")] +public class WriteStreamSecurityTests : IClassFixture { + public WriteStreamSecurityTests(ITestOutputHelper output, SecurityFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); SecurityFixture Fixture { get; } @@ -67,4 +69,4 @@ public async Task writing_to_all_access_normal_stream_succeeds_when_any_existing [Fact] public async Task writing_to_all_access_normal_stream_succeeds_when_any_admin_user_credentials_are_passed() => await Fixture.AppendStream(SecurityFixture.NormalAllStream, TestCredentials.TestAdmin); -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/SharingProviderTests.cs b/test/Kurrent.Client.Tests/SharingProviderTests.cs similarity index 95% rename from test/EventStore.Client.Tests/SharingProviderTests.cs rename to test/Kurrent.Client.Tests/SharingProviderTests.cs index ddb4c9d5f..3c55cfdda 100644 --- a/test/EventStore.Client.Tests/SharingProviderTests.cs +++ b/test/Kurrent.Client.Tests/SharingProviderTests.cs @@ -1,9 +1,12 @@ -#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously +using EventStore.Client; -namespace EventStore.Client.Tests; +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Misc")] public class SharingProviderTests { - [Fact] + [RetryFact] public async Task CanGetCurrent() { using var sut = new SharingProvider( async (x, _) => x + 1, @@ -14,7 +17,7 @@ public async Task CanGetCurrent() { Assert.Equal(6, await sut.CurrentAsync); } - [Fact] + [RetryFact] public async Task CanReset() { var count = 0; using var sut = new SharingProvider( @@ -28,7 +31,7 @@ public async Task CanReset() { Assert.Equal(1, await sut.CurrentAsync); } - [Fact] + [RetryFact] public async Task CanReturnBroken() { Action? onBroken = null; var count = 0; @@ -50,7 +53,7 @@ public async Task CanReturnBroken() { Assert.Equal(2, await sut.CurrentAsync); } - [Fact] + [RetryFact] public async Task CanReturnSameBoxTwice() { Action? onBroken = null; var count = 0; @@ -74,7 +77,7 @@ public async Task CanReturnSameBoxTwice() { Assert.Equal(1, await sut.CurrentAsync); } - [Fact] + [RetryFact] public async Task CanReturnPendingBox() { var trigger = new SemaphoreSlim(0); Action? onBroken = null; @@ -113,7 +116,7 @@ public async Task CanReturnPendingBox() { Assert.Equal(1, count); } - [Fact] + [RetryFact] public async Task FactoryCanThrow() { using var sut = new SharingProvider( (x, _) => throw new($"input {x}"), @@ -130,7 +133,7 @@ public async Task FactoryCanThrow() { // safe to call onBroken before the factory has returned, but it doesn't // do anything because the box is not populated yet. // the factory has to indicate failure by throwing. - [Fact] + [RetryFact] public async Task FactoryCanCallOnBrokenSynchronously() { using var sut = new SharingProvider( async (x, onBroken) => { @@ -147,7 +150,7 @@ public async Task FactoryCanCallOnBrokenSynchronously() { Assert.Equal(0, await sut.CurrentAsync); } - [Fact] + [RetryFact] public async Task FactoryCanCallOnBrokenSynchronouslyAndThrow() { using var sut = new SharingProvider( async (x, onBroken) => { @@ -167,7 +170,7 @@ public async Task FactoryCanCallOnBrokenSynchronouslyAndThrow() { Assert.Equal("input 0", ex.Message); } - [Fact] + [RetryFact] public async Task StopsAfterBeingDisposed() { Action? onBroken = null; var count = 0; @@ -193,7 +196,7 @@ public async Task StopsAfterBeingDisposed() { Assert.Equal(1, count); } - [Fact] + [RetryFact] public async Task ExampleUsage() { // factory waits to be signalled by completeConstruction being released // sometimes the factory succeeds, sometimes it throws. @@ -263,4 +266,4 @@ async Task Factory(int input, Action onBroken) { await constructionCompleted.WaitAsync(); Assert.Equal(0, await sut.CurrentAsync); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/StreamPositionTests.cs b/test/Kurrent.Client.Tests/StreamPositionTests.cs similarity index 93% rename from test/EventStore.Client.Tests/StreamPositionTests.cs rename to test/Kurrent.Client.Tests/StreamPositionTests.cs index 22578b548..06a4ad0ce 100644 --- a/test/EventStore.Client.Tests/StreamPositionTests.cs +++ b/test/Kurrent.Client.Tests/StreamPositionTests.cs @@ -1,21 +1,23 @@ using AutoFixture; +using EventStore.Client; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; +[Trait("Category", "Target:Misc")] public class StreamPositionTests : ValueObjectTests { public StreamPositionTests() : base(new ScenarioFixture()) { } - [Fact] + [RetryFact] public void IsComparable() => Assert.IsAssignableFrom>(_fixture.Create()); - [Fact] + [RetryFact] public void AdditionOperator() { var sut = StreamPosition.Start; Assert.Equal(new(1), sut + 1); Assert.Equal(new(1), 1 + sut); } - [Fact] + [RetryFact] public void NextReturnsExpectedResult() { var sut = StreamPosition.Start; Assert.Equal(sut + 1, sut.Next()); @@ -33,7 +35,7 @@ public void AdditionOutOfBoundsThrows(StreamPosition StreamPosition, ulong opera Assert.Throws(() => operand + StreamPosition); } - [Fact] + [RetryFact] public void SubtractionOperator() { var sut = new StreamPosition(1); Assert.Equal(new(0), sut - 1); @@ -64,17 +66,17 @@ public void ArgumentOutOfRange(ulong value) { Assert.Equal(nameof(value), ex.ParamName); } - [Fact] + [RetryFact] public void FromStreamPositionEndThrows() => Assert.Throws(() => StreamRevision.FromStreamPosition(StreamPosition.End)); - [Fact] + [RetryFact] public void FromStreamPositionReturnsExpectedResult() { var result = StreamPosition.FromStreamRevision(new(0)); Assert.Equal(new(0), result); } - [Fact] + [RetryFact] public void ExplicitConversionToUInt64ReturnsExpectedResult() { const ulong value = 0UL; @@ -82,7 +84,7 @@ public void ExplicitConversionToUInt64ReturnsExpectedResult() { Assert.Equal(value, actual); } - [Fact] + [RetryFact] public void ImplicitConversionToUInt64ReturnsExpectedResult() { const ulong value = 0UL; @@ -90,7 +92,7 @@ public void ImplicitConversionToUInt64ReturnsExpectedResult() { Assert.Equal(value, actual); } - [Fact] + [RetryFact] public void ExplicitConversionToStreamPositionReturnsExpectedResult() { const ulong value = 0UL; @@ -99,7 +101,7 @@ public void ExplicitConversionToStreamPositionReturnsExpectedResult() { Assert.Equal(expected, actual); } - [Fact] + [RetryFact] public void ImplicitConversionToStreamPositionReturnsExpectedResult() { const ulong value = 0UL; @@ -109,14 +111,14 @@ public void ImplicitConversionToStreamPositionReturnsExpectedResult() { Assert.Equal(expected, actual); } - [Fact] + [RetryFact] public void ToStringExpectedResult() { var expected = 0UL.ToString(); Assert.Equal(expected, new StreamPosition(0UL).ToString()); } - [Fact] + [RetryFact] public void ToUInt64ExpectedResult() { var expected = 0UL; @@ -126,4 +128,4 @@ public void ToUInt64ExpectedResult() { class ScenarioFixture : Fixture { public ScenarioFixture() => Customize(composer => composer.FromFactory(value => new(value))); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/StreamRevisionTests.cs b/test/Kurrent.Client.Tests/StreamRevisionTests.cs similarity index 93% rename from test/EventStore.Client.Tests/StreamRevisionTests.cs rename to test/Kurrent.Client.Tests/StreamRevisionTests.cs index e42039946..eb1d5c534 100644 --- a/test/EventStore.Client.Tests/StreamRevisionTests.cs +++ b/test/Kurrent.Client.Tests/StreamRevisionTests.cs @@ -1,21 +1,23 @@ using AutoFixture; +using EventStore.Client; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; +[Trait("Category", "Target:Misc")] public class StreamRevisionTests : ValueObjectTests { public StreamRevisionTests() : base(new ScenarioFixture()) { } - [Fact] + [RetryFact] public void IsComparable() => Assert.IsAssignableFrom>(_fixture.Create()); - [Fact] + [RetryFact] public void AdditionOperator() { var sut = new StreamRevision(0); Assert.Equal(new(1), sut + 1); Assert.Equal(new(1), 1 + sut); } - [Fact] + [RetryFact] public void NextReturnsExpectedResult() { var sut = new StreamRevision(0); Assert.Equal(sut + 1, sut.Next()); @@ -32,7 +34,7 @@ public void AdditionOutOfBoundsThrows(StreamRevision streamRevision, ulong opera Assert.Throws(() => operand + streamRevision); } - [Fact] + [RetryFact] public void SubtractionOperator() { var sut = new StreamRevision(1); Assert.Equal(new(0), sut - 1); @@ -63,17 +65,17 @@ public void ArgumentOutOfRange(ulong value) { Assert.Equal(nameof(value), ex.ParamName); } - [Fact] + [RetryFact] public void FromStreamPositionEndThrows() => Assert.Throws(() => StreamRevision.FromStreamPosition(StreamPosition.End)); - [Fact] + [RetryFact] public void FromStreamPositionReturnsExpectedResult() { var result = StreamRevision.FromStreamPosition(StreamPosition.Start); Assert.Equal(new(0), result); } - [Fact] + [RetryFact] public void ExplicitConversionToUInt64ReturnsExpectedResult() { const ulong value = 0UL; @@ -82,7 +84,7 @@ public void ExplicitConversionToUInt64ReturnsExpectedResult() { Assert.Equal(value, actual); } - [Fact] + [RetryFact] public void ImplicitConversionToUInt64ReturnsExpectedResult() { const ulong value = 0UL; @@ -91,7 +93,7 @@ public void ImplicitConversionToUInt64ReturnsExpectedResult() { Assert.Equal(value, actual); } - [Fact] + [RetryFact] public void ExplicitConversionToStreamRevisionReturnsExpectedResult() { const ulong value = 0UL; @@ -101,7 +103,7 @@ public void ExplicitConversionToStreamRevisionReturnsExpectedResult() { Assert.Equal(expected, actual); } - [Fact] + [RetryFact] public void ImplicitConversionToStreamRevisionReturnsExpectedResult() { const ulong value = 0UL; @@ -111,14 +113,14 @@ public void ImplicitConversionToStreamRevisionReturnsExpectedResult() { Assert.Equal(expected, actual); } - [Fact] + [RetryFact] public void ToStringExpectedResult() { var expected = 0UL.ToString(); Assert.Equal(expected, new StreamRevision(0UL).ToString()); } - [Fact] + [RetryFact] public void ToUInt64ExpectedResult() { var expected = 0UL; @@ -128,4 +130,4 @@ public void ToUInt64ExpectedResult() { class ScenarioFixture : Fixture { public ScenarioFixture() => Customize(composer => composer.FromFactory(value => new(value))); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/StreamStateTests.cs b/test/Kurrent.Client.Tests/StreamStateTests.cs similarity index 77% rename from test/EventStore.Client.Tests/StreamStateTests.cs rename to test/Kurrent.Client.Tests/StreamStateTests.cs index b4d0424c6..1faf56214 100644 --- a/test/EventStore.Client.Tests/StreamStateTests.cs +++ b/test/Kurrent.Client.Tests/StreamStateTests.cs @@ -1,15 +1,17 @@ using System.Reflection; using AutoFixture; +using EventStore.Client; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; +[Trait("Category", "Target:Misc")] public class StreamStateTests : ValueObjectTests { public StreamStateTests() : base(new ScenarioFixture()) { } public static IEnumerable ArgumentOutOfRangeTestCases() { - yield return new object?[] { 0 }; - yield return new object?[] { int.MaxValue }; - yield return new object?[] { -3 }; + yield return [0]; + yield return [int.MaxValue]; + yield return [-3]; } [Theory] @@ -19,23 +21,23 @@ public void ArgumentOutOfRange(int value) { Assert.Equal(nameof(value), ex.ParamName); } - [Fact] + [RetryFact] public void ExplicitConversionExpectedResult() { const int expected = 1; var actual = (int)new StreamState(expected); Assert.Equal(expected, actual); } - [Fact] + [RetryFact] public void ImplicitConversionExpectedResult() { const int expected = 1; Assert.Equal(expected, new StreamState(expected)); } public static IEnumerable ToStringTestCases() { - yield return new object?[] { StreamState.Any, nameof(StreamState.Any) }; - yield return new object?[] { StreamState.NoStream, nameof(StreamState.NoStream) }; - yield return new object?[] { StreamState.StreamExists, nameof(StreamState.StreamExists) }; + yield return [StreamState.Any, nameof(StreamState.Any)]; + yield return [StreamState.NoStream, nameof(StreamState.NoStream)]; + yield return [StreamState.StreamExists, nameof(StreamState.StreamExists)]; } [Theory] @@ -54,4 +56,4 @@ class ScenarioFixture : Fixture { public ScenarioFixture() => Customize(composer => composer.FromFactory(() => Instances[Interlocked.Increment(ref RefCount) % Instances.Length])); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Append/append_to_stream.cs b/test/Kurrent.Client.Tests/Streams/AppendTests.cs similarity index 55% rename from test/EventStore.Client.Streams.Tests/Append/append_to_stream.cs rename to test/Kurrent.Client.Tests/Streams/AppendTests.cs index 6cd5b813d..f6442219e 100644 --- a/test/EventStore.Client.Streams.Tests/Append/append_to_stream.cs +++ b/test/Kurrent.Client.Tests/Streams/AppendTests.cs @@ -1,19 +1,13 @@ -using System.Text; +using EventStore.Client; using Grpc.Core; +using Humanizer; -namespace EventStore.Client.Streams.Tests.Append; +namespace Kurrent.Client.Tests.Streams; -[Trait("Category", "Target:Stream")] +[Trait("Category", "Target:Streams")] [Trait("Category", "Operation:Append")] -public class append_to_stream(ITestOutputHelper output, EventStoreFixture fixture) - : EventStoreTests(output, fixture) { - public static IEnumerable ExpectedVersionCreateStreamTestCases() { - yield return new object?[] { StreamState.Any }; - yield return new object?[] { StreamState.NoStream }; - } - - [Theory] - [MemberData(nameof(ExpectedVersionCreateStreamTestCases))] +public class AppendTests(ITestOutputHelper output, KurrentPermanentFixture fixture) : KurrentPermanentTests(output, fixture) { + [Theory, ExpectedVersionCreateStreamTestCases] public async Task appending_zero_events(StreamState expectedStreamState) { var stream = $"{Fixture.GetStreamName()}_{expectedStreamState}"; @@ -33,8 +27,7 @@ await Fixture.Streams .ShouldThrowAsync(ex => ex.Stream.ShouldBe(stream)); } - [Theory] - [MemberData(nameof(ExpectedVersionCreateStreamTestCases))] + [Theory, ExpectedVersionCreateStreamTestCases] public async Task appending_zero_events_again(StreamState expectedStreamState) { var stream = $"{Fixture.GetStreamName()}_{expectedStreamState}"; @@ -54,8 +47,7 @@ await Fixture.Streams .ShouldThrowAsync(ex => ex.Stream.ShouldBe(stream)); } - [Theory] - [MemberData(nameof(ExpectedVersionCreateStreamTestCases))] + [Theory, ExpectedVersionCreateStreamTestCases] public async Task create_stream_expected_version_on_first_write_if_does_not_exist(StreamState expectedStreamState) { var stream = $"{Fixture.GetStreamName()}_{expectedStreamState}"; @@ -73,7 +65,7 @@ public async Task create_stream_expected_version_on_first_write_if_does_not_exis Assert.Equal(1, count); } - [Fact] + [RetryFact] public async Task multiple_idempotent_writes() { var stream = Fixture.GetStreamName(); var events = Fixture.CreateTestEvents(4).ToArray(); @@ -85,7 +77,7 @@ public async Task multiple_idempotent_writes() { Assert.Equal(new(3), writeResult.NextExpectedStreamRevision); } - [Fact] + [RetryFact] public async Task multiple_idempotent_writes_with_same_id_bug_case() { var stream = Fixture.GetStreamName(); @@ -97,7 +89,7 @@ public async Task multiple_idempotent_writes_with_same_id_bug_case() { Assert.Equal(new(5), writeResult.NextExpectedStreamRevision); } - [Fact] + [RetryFact] public async Task in_case_where_multiple_writes_of_multiple_events_with_the_same_ids_using_expected_version_any_then_next_expected_version_is_unreliable() { var stream = Fixture.GetStreamName(); @@ -114,7 +106,7 @@ public async Task Assert.Equal(new(0), writeResult.NextExpectedStreamRevision); } - [Fact] + [RetryFact] public async Task in_case_where_multiple_writes_of_multiple_events_with_the_same_ids_using_expected_version_nostream_then_next_expected_version_is_correct() { var stream = Fixture.GetStreamName(); @@ -132,7 +124,7 @@ public async Task Assert.Equal(streamRevision, writeResult.NextExpectedStreamRevision); } - [Fact] + [RetryFact] public async Task writing_with_correct_expected_version_to_deleted_stream_throws_stream_deleted() { var stream = Fixture.GetStreamName(); @@ -143,7 +135,7 @@ await Fixture.Streams .ShouldThrowAsync(); } - [Fact] + [RetryFact] public async Task returns_log_position_when_writing() { var stream = Fixture.GetStreamName(); @@ -157,7 +149,7 @@ public async Task returns_log_position_when_writing() { Assert.True(0 < result.LogPosition.CommitPosition); } - [Fact] + [RetryFact] public async Task writing_with_any_expected_version_to_deleted_stream_throws_stream_deleted() { var stream = Fixture.GetStreamName(); await Fixture.Streams.TombstoneAsync(stream, StreamState.NoStream); @@ -167,7 +159,7 @@ await Fixture.Streams .ShouldThrowAsync(); } - [Fact] + [RetryFact] public async Task writing_with_invalid_expected_version_to_deleted_stream_throws_stream_deleted() { var stream = Fixture.GetStreamName(); @@ -178,7 +170,7 @@ await Fixture.Streams .ShouldThrowAsync(); } - [Fact] + [RetryFact] public async Task append_with_correct_expected_version_to_existing_stream() { var stream = Fixture.GetStreamName(); @@ -197,7 +189,7 @@ public async Task append_with_correct_expected_version_to_existing_stream() { Assert.Equal(new(1), writeResult.NextExpectedStreamRevision); } - [Fact] + [RetryFact] public async Task append_with_any_expected_version_to_existing_stream() { var stream = Fixture.GetStreamName(); @@ -218,7 +210,7 @@ public async Task append_with_any_expected_version_to_existing_stream() { Assert.Equal(new(1), writeResult.NextExpectedStreamRevision); } - [Fact] + [RetryFact] public async Task appending_with_wrong_expected_version_to_existing_stream_throws_wrong_expected_version() { var stream = Fixture.GetStreamName(); @@ -232,7 +224,7 @@ public async Task appending_with_wrong_expected_version_to_existing_stream_throw ex.ExpectedStreamRevision.ShouldBe(new(999)); } - [Fact] + [RetryFact] public async Task appending_with_wrong_expected_version_to_existing_stream_returns_wrong_expected_version() { var stream = Fixture.GetStreamName(); @@ -248,7 +240,7 @@ public async Task appending_with_wrong_expected_version_to_existing_stream_retur Assert.Equal(new(1), wrongExpectedVersionResult.NextExpectedStreamRevision); } - [Fact] + [RetryFact] public async Task append_with_stream_exists_expected_version_to_existing_stream() { var stream = Fixture.GetStreamName(); @@ -261,7 +253,7 @@ await Fixture.Streams.AppendToStreamAsync( ); } - [Fact] + [RetryFact] public async Task append_with_stream_exists_expected_version_to_stream_with_multiple_events() { var stream = Fixture.GetStreamName(); @@ -275,7 +267,7 @@ await Fixture.Streams.AppendToStreamAsync( ); } - [Fact] + [RetryFact] public async Task append_with_stream_exists_expected_version_if_metadata_stream_exists() { var stream = Fixture.GetStreamName(); @@ -292,7 +284,7 @@ await Fixture.Streams.AppendToStreamAsync( ); } - [Fact] + [RetryFact] public async Task appending_with_stream_exists_expected_version_and_stream_does_not_exist_throws_wrong_expected_version() { var stream = Fixture.GetStreamName(); @@ -304,7 +296,7 @@ public async Task ex.ActualStreamRevision.ShouldBe(StreamRevision.None); } - [Fact] + [RetryFact] public async Task appending_with_stream_exists_expected_version_and_stream_does_not_exist_returns_wrong_expected_version() { var stream = Fixture.GetStreamName(); @@ -321,7 +313,7 @@ public async Task Assert.Equal(StreamRevision.None, wrongExpectedVersionResult.NextExpectedStreamRevision); } - [Fact] + [RetryFact] public async Task appending_with_stream_exists_expected_version_to_hard_deleted_stream_throws_stream_deleted() { var stream = Fixture.GetStreamName(); @@ -332,7 +324,7 @@ await Fixture.Streams .ShouldThrowAsync(); } - [Fact] + [RetryFact] public async Task appending_with_stream_exists_expected_version_to_deleted_stream_throws_stream_deleted() { var stream = Fixture.GetStreamName(); @@ -345,7 +337,7 @@ await Fixture.Streams .ShouldThrowAsync(); } - [Fact] + [RetryFact] public async Task can_append_multiple_events_at_once() { var stream = Fixture.GetStreamName(); @@ -358,7 +350,7 @@ public async Task can_append_multiple_events_at_once() { Assert.Equal(new(99), writeResult.NextExpectedStreamRevision); } - [Fact] + [RetryFact] public async Task returns_failure_status_when_conditionally_appending_with_version_mismatch() { var stream = Fixture.GetStreamName(); @@ -374,7 +366,7 @@ public async Task returns_failure_status_when_conditionally_appending_with_versi ); } - [Fact] + [RetryFact] public async Task returns_success_status_when_conditionally_appending_with_matching_version() { var stream = Fixture.GetStreamName(); @@ -390,7 +382,7 @@ public async Task returns_success_status_when_conditionally_appending_with_match ); } - [Fact] + [RetryFact] public async Task returns_failure_status_when_conditionally_appending_to_a_deleted_stream() { var stream = Fixture.GetStreamName(); @@ -407,7 +399,7 @@ public async Task returns_failure_status_when_conditionally_appending_to_a_delet Assert.Equal(ConditionalWriteResult.StreamDeleted, result); } - [Fact] + [RetryFact] public async Task expected_version_no_stream() { var result = await Fixture.Streams.AppendToStreamAsync( Fixture.GetStreamName(), @@ -418,7 +410,7 @@ public async Task expected_version_no_stream() { Assert.Equal(new(0), result!.NextExpectedStreamRevision); } - [Fact] + [RetryFact] public async Task expected_version_no_stream_returns_position() { var result = await Fixture.Streams.AppendToStreamAsync( Fixture.GetStreamName(), @@ -429,7 +421,7 @@ public async Task expected_version_no_stream_returns_position() { Assert.True(result.LogPosition > Position.Start); } - [Fact] + [RetryFact] public async Task with_timeout_any_stream_revision_fails_when_operation_expired() { var stream = Fixture.GetStreamName(); @@ -443,7 +435,7 @@ public async Task with_timeout_any_stream_revision_fails_when_operation_expired( ex.StatusCode.ShouldBe(StatusCode.DeadlineExceeded); } - [Fact] + [RetryFact] public async Task with_timeout_stream_revision_fails_when_operation_expired() { var stream = Fixture.GetStreamName(); @@ -459,7 +451,7 @@ public async Task with_timeout_stream_revision_fails_when_operation_expired() { ex.StatusCode.ShouldBe(StatusCode.DeadlineExceeded); } - [Fact] + [RetryFact] public async Task when_events_enumerator_throws_the_write_does_not_succeed() { var streamName = Fixture.GetStreamName(); @@ -477,4 +469,317 @@ await Fixture.Streams state.ShouldBe(ReadState.StreamNotFound); } + + [RetryFact] + public async Task succeeds_when_size_is_less_than_max_append_size() { + // Arrange + var maxAppendSize = (uint)100.Kilobytes().Bytes; + var stream = Fixture.GetStreamName(); + + // Act + var (events, size) = Fixture.CreateTestEventsUpToMaxSize(maxAppendSize - 1); + + // Assert + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + } + + [RetryFact] + public async Task fails_when_size_exceeds_max_append_size() { + // Arrange + var maxAppendSize = (uint)100.Kilobytes().Bytes; + var stream = Fixture.GetStreamName(); + var eventsAppendSize = maxAppendSize * 2; + + // Act + var (events, size) = Fixture.CreateTestEventsUpToMaxSize(eventsAppendSize); + + // Assert + size.ShouldBeGreaterThan(maxAppendSize); + + var ex = await Fixture.Streams + .AppendToStreamAsync(stream, StreamState.NoStream, events) + .ShouldThrowAsync(); + + ex.MaxAppendSize.ShouldBe(maxAppendSize); + } + + [RetryFact] + public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0em1_idempotent() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(6).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(1)); + + var count = await Fixture.Streams + .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); + + Assert.Equal(events.Length, count); + } + + [RetryFact] + public async Task sequence_0em1_1e0_2e1_3e2_4e3_4e4_0any_idempotent() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(6).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Take(1)); + + var count = await Fixture.Streams + .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); + + Assert.Equal(events.Length, count); + } + + [RetryFact] + public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e5_non_idempotent() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(6).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(5), events.Take(1)); + + var count = await Fixture.Streams + .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 2).CountAsync(); + + Assert.Equal(events.Length + 1, count); + } + + [RetryFact] + public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e6_throws_wev() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(6).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + + await Assert.ThrowsAsync(() => Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(6), events.Take(1))); + } + + [RetryFact] + public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e6_returns_wev() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(6).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + + var writeResult = await Fixture.Streams.AppendToStreamAsync( + stream, + new StreamRevision(6), + events.Take(1), + options => options.ThrowOnAppendFailure = false + ); + + Assert.IsType(writeResult); + } + + [RetryFact] + public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e4_throws_wev() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(6).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + + await Assert.ThrowsAsync(() => Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(4), events.Take(1))); + } + + [RetryFact] + public async Task sequence_0em1_1e0_2e1_3e2_4e3_5e4_0e4_returns_wev() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(6).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + + var writeResult = await Fixture.Streams.AppendToStreamAsync( + stream, + new StreamRevision(4), + events.Take(1), + options => options.ThrowOnAppendFailure = false + ); + + Assert.IsType(writeResult); + } + + [RetryFact] + public async Task sequence_0em1_0e0_non_idempotent() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents().ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(0), events.Take(1)); + + var count = await Fixture.Streams + .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 2).CountAsync(); + + Assert.Equal(events.Length + 1, count); + } + + [RetryFact] + public async Task sequence_0em1_0any_idempotent() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents().ToArray(); + + await Task.Delay(TimeSpan.FromSeconds(30)); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Take(1)); + + var count = await Fixture.Streams + .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); + + Assert.Equal(events.Length, count); + } + + [RetryFact] + public async Task sequence_0em1_0em1_idempotent() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents().ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(1)); + + var count = await Fixture.Streams + .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); + + Assert.Equal(events.Length, count); + } + + [RetryFact] + public async Task sequence_0em1_1e0_2e1_1any_1any_idempotent() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(3).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Skip(1).Take(1)); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Skip(1).Take(1)); + + var count = await Fixture.Streams + .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); + + Assert.Equal(events.Length, count); + } + + [RetryFact] + public async Task sequence_S_0em1_1em1_E_S_0em1_E_idempotent() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(2).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(1)); + + var count = await Fixture.Streams + .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); + + Assert.Equal(events.Length, count); + } + + [RetryFact] + public async Task sequence_S_0em1_1em1_E_S_0any_E_idempotent() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(2).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Take(1)); + + var count = await Fixture.Streams + .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); + + Assert.Equal(events.Length, count); + } + + [RetryFact] + public async Task sequence_S_0em1_1em1_E_S_1e0_E_idempotent() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(2).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + + await Fixture.Streams.AppendToStreamAsync(stream, new StreamRevision(0), events.Skip(1)); + + var count = await Fixture.Streams + .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); + + Assert.Equal(events.Length, count); + } + + [RetryFact] + public async Task sequence_S_0em1_1em1_E_S_1any_E_idempotent() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(2).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events); + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, events.Skip(1).Take(1)); + + var count = await Fixture.Streams + .ReadStreamAsync(Direction.Forwards, stream, StreamPosition.Start, events.Length + 1).CountAsync(); + + Assert.Equal(events.Length, count); + } + + [RetryFact] + public async Task sequence_S_0em1_1em1_E_S_0em1_1em1_2em1_E_idempotancy_fail_throws() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(3).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(2)); + + await Assert.ThrowsAsync( + () => Fixture.Streams.AppendToStreamAsync( + stream, + StreamState.NoStream, + events + ) + ); + } + + [RetryFact] + public async Task sequence_S_0em1_1em1_E_S_0em1_1em1_2em1_E_idempotancy_fail_returns() { + var stream = Fixture.GetStreamName(); + + var events = Fixture.CreateTestEvents(3).ToArray(); + + await Fixture.Streams.AppendToStreamAsync(stream, StreamState.NoStream, events.Take(2)); + + var writeResult = await Fixture.Streams.AppendToStreamAsync( + stream, + StreamState.NoStream, + events, + options => options.ThrowOnAppendFailure = false + ); + + Assert.IsType(writeResult); + } + + // [Fact] + // public async Task sending_and_receiving_large_messages_over_the_hard_limit() { + // uint maxAppendSize = 16 * 1024 * 1024 - 10000; + // var streamName = Fixture.GetStreamName(); + // var largeEvent = Fixture.CreateTestEvents() + // .Select(e => new EventData(e.EventId, "-", new byte[maxAppendSize + 1])); + // + // var ex = await Assert.ThrowsAsync(() => Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, largeEvent)); + // + // Assert.Equal(StatusCode.ResourceExhausted, ex.StatusCode); + // } + + class ExpectedVersionCreateStreamTestCases : TestCaseGenerator { + protected override IEnumerable Data() { + yield return [StreamState.Any]; + yield return [StreamState.NoStream]; + } + } } diff --git a/test/EventStore.Client.Streams.Tests/Bugs/Obsolete/Issue_104.cs b/test/Kurrent.Client.Tests/Streams/Bugs/Obsolete/Issue104.cs similarity index 86% rename from test/EventStore.Client.Streams.Tests/Bugs/Obsolete/Issue_104.cs rename to test/Kurrent.Client.Tests/Streams/Bugs/Obsolete/Issue104.cs index 922414820..4fe12ecbe 100644 --- a/test/EventStore.Client.Streams.Tests/Bugs/Obsolete/Issue_104.cs +++ b/test/Kurrent.Client.Tests/Streams/Bugs/Obsolete/Issue104.cs @@ -1,8 +1,11 @@ -namespace EventStore.Client.Streams.Tests.Bugs.Obsolete; +using EventStore.Client; +namespace Kurrent.Client.Tests.Bugs.Obsolete; + +[Trait("Category", "Target:Streams")] [Trait("Category", "Bug")] [Obsolete("Tests will be removed in future release when older subscriptions APIs are removed from the client")] -public class Issue_104(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { +public class Issue104(ITestOutputHelper output, KurrentPermanentFixture fixture) : KurrentPermanentTests(output, fixture) { [Fact] public async Task subscription_does_not_send_checkpoint_reached_after_disposal() { var streamName = Fixture.GetStreamName(); diff --git a/test/EventStore.Client.Streams.Tests/Bugs/Obsolete/Issue_2544.cs b/test/Kurrent.Client.Tests/Streams/Bugs/Obsolete/Issue2544.cs similarity index 81% rename from test/EventStore.Client.Streams.Tests/Bugs/Obsolete/Issue_2544.cs rename to test/Kurrent.Client.Tests/Streams/Bugs/Obsolete/Issue2544.cs index 3d65b01ec..a1add87e2 100644 --- a/test/EventStore.Client.Streams.Tests/Bugs/Obsolete/Issue_2544.cs +++ b/test/Kurrent.Client.Tests/Streams/Bugs/Obsolete/Issue2544.cs @@ -1,30 +1,32 @@ -#pragma warning disable 1998 +// ReSharper disable InconsistentNaming -namespace EventStore.Client.Streams.Tests.Bugs.Obsolete; +using EventStore.Client; +namespace Kurrent.Client.Tests.Bugs.Obsolete; + +[Trait("Category", "Target:Streams")] [Trait("Category", "Bug")] [Obsolete("Tests will be removed in future release when older subscriptions APIs are removed from the client")] -public class Issue_2544 : IClassFixture { - public Issue_2544(ITestOutputHelper output, EventStoreFixture fixture) { +public class Issue2544 : IClassFixture { + public Issue2544(ITestOutputHelper output, KurrentPermanentFixture fixture) { Fixture = fixture.With(x => x.CaptureTestRun(output)); - - _seen = Enumerable.Range(0, 1 + Batches * BatchSize) + + Seen = Enumerable.Range(0, 1 + Batches * BatchSize) .Select(i => new StreamPosition((ulong)i)) .ToDictionary(r => r, _ => false); - _completed = new(); + Completed = new(); } - EventStoreFixture Fixture { get; } + KurrentPermanentFixture Fixture { get; } const int BatchSize = 18; const int Batches = 4; - - readonly TaskCompletionSource _completed; - readonly Dictionary _seen; - public static IEnumerable TestCases() => - Enumerable.Range(0, 5).Select(i => new object[] { i }); + readonly TaskCompletionSource Completed; + readonly Dictionary Seen; + + public static IEnumerable TestCases() => Enumerable.Range(0, 5).Select(i => new object[] { i }); [Theory] [MemberData(nameof(TestCases))] @@ -46,7 +48,7 @@ await Fixture.Streams await AppendEvents(streamName); - await _completed.Task.WithTimeout(); + await Completed.Task.WithTimeout(); } [Theory] @@ -68,7 +70,7 @@ await Fixture.Streams await AppendEvents(streamName); - await _completed.Task.WithTimeout(); + await Completed.Task.WithTimeout(); } [Theory] @@ -91,7 +93,7 @@ await Fixture.Streams await AppendEvents(streamName); - await _completed.Task.WithTimeout(); + await Completed.Task.WithTimeout(); } async Task AppendEvents(string streamName) { @@ -108,8 +110,7 @@ async Task AppendEvents(string streamName) { ); expectedRevision = result.NextExpectedStreamRevision; - } - else { + } else { var result = await Fixture.Streams.AppendToStreamAsync( streamName, expectedRevision, @@ -143,7 +144,7 @@ Func> resubscribe return; } - _completed.TrySetException(ex); + Completed.TrySetException(ex); } Task EventAppeared(ResolvedEvent e, string streamName, out FromStream startFrom) { @@ -160,12 +161,12 @@ Task EventAppeared(ResolvedEvent e, string streamName) { if (e.OriginalStreamId != streamName) return Task.CompletedTask; - if (_seen[e.Event.EventNumber]) + if (Seen[e.Event.EventNumber]) throw new($"Event {e.Event.EventNumber} was already seen"); - _seen[e.Event.EventNumber] = true; + Seen[e.Event.EventNumber] = true; if (e.Event.EventType == "completed") - _completed.TrySetResult(true); + Completed.TrySetResult(true); return Task.CompletedTask; } diff --git a/test/EventStore.Client.Streams.Tests/Delete/deleting_stream.cs b/test/Kurrent.Client.Tests/Streams/DeleteTests.cs similarity index 72% rename from test/EventStore.Client.Streams.Tests/Delete/deleting_stream.cs rename to test/Kurrent.Client.Tests/Streams/DeleteTests.cs index 552a8a4b9..c09e3fdbe 100644 --- a/test/EventStore.Client.Streams.Tests/Delete/deleting_stream.cs +++ b/test/Kurrent.Client.Tests/Streams/DeleteTests.cs @@ -1,16 +1,12 @@ +using EventStore.Client; using Grpc.Core; -namespace EventStore.Client.Streams.Tests.Delete; +namespace Kurrent.Client.Tests.Streams; +[Trait("Category", "Target:Streams")] [Trait("Category", "Operation:Delete")] -public class deleting_stream(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { - public static IEnumerable ExpectedStreamStateCases() { - yield return new object?[] { StreamState.Any, nameof(StreamState.Any) }; - yield return new object?[] { StreamState.NoStream, nameof(StreamState.NoStream) }; - } - - [Theory] - [MemberData(nameof(ExpectedStreamStateCases))] +public class DeleteTests(ITestOutputHelper output, KurrentPermanentFixture fixture) : KurrentPermanentTests(output, fixture) { + [Theory, ExpectedStreamStateCases] public async Task hard_deleting_a_stream_that_does_not_exist_with_expected_version_does_not_throw(StreamState expectedVersion, string name) { var stream = $"{Fixture.GetStreamName()}_{name}"; @@ -78,14 +74,11 @@ public async Task hard_deleting_a_deleted_stream_should_throw() { await Assert.ThrowsAsync(() => Fixture.Streams.TombstoneAsync(stream, StreamState.NoStream)); } - - + [Fact] public async Task with_timeout_any_stream_revision_delete_fails_when_operation_expired() { - var stream = Fixture.GetStreamName(); - var rpcException = await Assert.ThrowsAsync( - () => Fixture.Streams.DeleteAsync(stream, StreamState.Any, TimeSpan.Zero) - ); + var stream = Fixture.GetStreamName(); + var rpcException = await Assert.ThrowsAsync(() => Fixture.Streams.DeleteAsync(stream, StreamState.Any, TimeSpan.Zero)); Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); } @@ -94,19 +87,15 @@ public async Task with_timeout_any_stream_revision_delete_fails_when_operation_e public async Task with_timeout_stream_revision_delete_fails_when_operation_expired() { var stream = Fixture.GetStreamName(); - var rpcException = await Assert.ThrowsAsync( - () => Fixture.Streams.DeleteAsync(stream, new StreamRevision(0), TimeSpan.Zero) - ); + var rpcException = await Assert.ThrowsAsync(() => Fixture.Streams.DeleteAsync(stream, new StreamRevision(0), TimeSpan.Zero)); Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); } [Fact] public async Task with_timeout_any_stream_revision_tombstoning_fails_when_operation_expired() { - var stream = Fixture.GetStreamName(); - var rpcException = await Assert.ThrowsAsync( - () => Fixture.Streams.TombstoneAsync(stream, StreamState.Any, TimeSpan.Zero) - ); + var stream = Fixture.GetStreamName(); + var rpcException = await Assert.ThrowsAsync(() => Fixture.Streams.TombstoneAsync(stream, StreamState.Any, TimeSpan.Zero)); Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); } @@ -115,10 +104,15 @@ public async Task with_timeout_any_stream_revision_tombstoning_fails_when_operat public async Task with_timeout_stream_revision_tombstoning_fails_when_operation_expired() { var stream = Fixture.GetStreamName(); - var rpcException = await Assert.ThrowsAsync( - () => Fixture.Streams.TombstoneAsync(stream, new StreamRevision(0), TimeSpan.Zero) - ); + var rpcException = await Assert.ThrowsAsync(() => Fixture.Streams.TombstoneAsync(stream, new StreamRevision(0), TimeSpan.Zero)); Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); } -} \ No newline at end of file + + class ExpectedStreamStateCases : TestCaseGenerator { + protected override IEnumerable Data() { + yield return [StreamState.Any, nameof(StreamState.Any)]; + yield return [StreamState.NoStream, nameof(StreamState.NoStream)]; + } + } +} diff --git a/test/EventStore.Client.Streams.Tests/Read/EventBinaryData.cs b/test/Kurrent.Client.Tests/Streams/Read/EventBinaryData.cs similarity index 81% rename from test/EventStore.Client.Streams.Tests/Read/EventBinaryData.cs rename to test/Kurrent.Client.Tests/Streams/Read/EventBinaryData.cs index 923a40cd1..09f8ce6ae 100644 --- a/test/EventStore.Client.Streams.Tests/Read/EventBinaryData.cs +++ b/test/Kurrent.Client.Tests/Streams/Read/EventBinaryData.cs @@ -1,33 +1,35 @@ -namespace EventStore.Client.Streams.Tests.Read; +using EventStore.Client; + +namespace Kurrent.Client.Tests; public readonly record struct EventBinaryData(Uuid Id, byte[] Data, byte[] Metadata) { - public bool Equals(EventBinaryData other) => - Id.Equals(other.Id) - && Data.SequenceEqual(other.Data) + public bool Equals(EventBinaryData other) => + Id.Equals(other.Id) + && Data.SequenceEqual(other.Data) && Metadata.SequenceEqual(other.Metadata); public override int GetHashCode() => System.HashCode.Combine(Id, Data, Metadata); } public static class EventBinaryDataConverters { - public static EventBinaryData ToBinaryData(this EventData source) => + public static EventBinaryData ToBinaryData(this EventData source) => new(source.EventId, source.Data.ToArray(), source.Metadata.ToArray()); - public static EventBinaryData ToBinaryData(this EventRecord source) => + public static EventBinaryData ToBinaryData(this EventRecord source) => new(source.EventId, source.Data.ToArray(), source.Metadata.ToArray()); - public static EventBinaryData ToBinaryData(this ResolvedEvent source) => + public static EventBinaryData ToBinaryData(this ResolvedEvent source) => source.Event.ToBinaryData(); - - public static EventBinaryData[] ToBinaryData(this IEnumerable source) => + + public static EventBinaryData[] ToBinaryData(this IEnumerable source) => source.Select(x => x.ToBinaryData()).ToArray(); - - public static EventBinaryData[] ToBinaryData(this IEnumerable source) => + + public static EventBinaryData[] ToBinaryData(this IEnumerable source) => source.Select(x => x.ToBinaryData()).ToArray(); - - public static EventBinaryData[] ToBinaryData(this IEnumerable source) => + + public static EventBinaryData[] ToBinaryData(this IEnumerable source) => source.Select(x => x.ToBinaryData()).ToArray(); public static ValueTask ToBinaryData(this IAsyncEnumerable source) => source.DefaultIfEmpty().Select(x => x.ToBinaryData()).ToArrayAsync(); -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Read/EventDataComparer.cs b/test/Kurrent.Client.Tests/Streams/Read/EventDataComparer.cs similarity index 90% rename from test/EventStore.Client.Streams.Tests/Read/EventDataComparer.cs rename to test/Kurrent.Client.Tests/Streams/Read/EventDataComparer.cs index cd9c6f41a..86113e285 100644 --- a/test/EventStore.Client.Streams.Tests/Read/EventDataComparer.cs +++ b/test/Kurrent.Client.Tests/Streams/Read/EventDataComparer.cs @@ -1,4 +1,6 @@ -namespace EventStore.Client.Streams.Tests.Read; +using EventStore.Client; + +namespace Kurrent.Client.Tests; static class EventDataComparer { public static bool Equal(EventData expected, EventRecord actual) { @@ -18,4 +20,4 @@ public static bool Equal(EventData[] expected, EventRecord[] actual) { return !expected.Where((t, i) => !Equal(t, actual[i])).Any(); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Read/read_all_events_backward.cs b/test/Kurrent.Client.Tests/Streams/Read/ReadAllEventsBackwardTests.cs similarity index 85% rename from test/EventStore.Client.Streams.Tests/Read/read_all_events_backward.cs rename to test/Kurrent.Client.Tests/Streams/Read/ReadAllEventsBackwardTests.cs index b07f199ef..a5850e906 100644 --- a/test/EventStore.Client.Streams.Tests/Read/read_all_events_backward.cs +++ b/test/Kurrent.Client.Tests/Streams/Read/ReadAllEventsBackwardTests.cs @@ -1,12 +1,16 @@ +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; using Grpc.Core; -namespace EventStore.Client.Streams.Tests.Read; +namespace Kurrent.Client.Tests; +[Trait("Category", "Target:Streams")] [Trait("Category", "Target:All")] [Trait("Category", "Operation:Read")] [Trait("Category", "Operation:Read:Backwards")] [Trait("Category", "Database:Dedicated")] -public class read_all_events_backward(ITestOutputHelper output, ReadAllEventsFixture fixture) : EventStoreTests(output, fixture) { +public class ReadAllEventsBackwardTests(ITestOutputHelper output, ReadAllEventsFixture fixture) + : KurrentTemporaryTests(output, fixture) { [Fact] public async Task return_empty_if_reading_from_start() { var result = await Fixture.Streams.ReadAllAsync(Direction.Backwards, Position.Start, 1).CountAsync(); @@ -28,7 +32,7 @@ public async Task return_events_in_reversed_order_compared_to_written() { .ReadAllAsync(Direction.Backwards, Position.End) .Where(x => x.OriginalStreamId == Fixture.ExpectedStreamName) .ToBinaryData(); - + result.ShouldBe(Fixture.ExpectedEventsReversed); } @@ -37,7 +41,7 @@ public async Task return_single_event() { var result = await Fixture.Streams .ReadAllAsync(Direction.Backwards, Position.End, 1) .ToArrayAsync(); - + result.ShouldHaveSingleItem(); } @@ -51,36 +55,36 @@ public async Task max_count_is_respected() { result.Length.ShouldBe(maxCount); } - + [Fact] public async Task stream_found() { var count = await Fixture.Streams .ReadAllAsync(Direction.Backwards, Position.End) .Where(x => x.OriginalStreamId == Fixture.ExpectedStreamName) .CountAsync(); - + count.ShouldBe(Fixture.ExpectedEvents.Length); } - + [Fact] public async Task with_timeout_fails_when_operation_expired() { var ex = await Fixture.Streams .ReadAllAsync(Direction.Backwards, Position.Start, 1, false, TimeSpan.Zero) .ToArrayAsync() .AsTask().ShouldThrowAsync(); - + ex.StatusCode.ShouldBe(StatusCode.DeadlineExceeded); } - + [Fact] public async Task filter_events_by_type() { var result = await Fixture.Streams - .ReadAllAsync(Direction.Backwards, Position.End, EventTypeFilter.Prefix(EventStoreFixture.AnotherTestEventTypePrefix)) + .ReadAllAsync(Direction.Backwards, Position.End, EventTypeFilter.Prefix(KurrentTemporaryFixture.AnotherTestEventTypePrefix)) .ToListAsync(); - - result.ForEach(x => x.Event.EventType.ShouldStartWith(EventStoreFixture.AnotherTestEventTypePrefix)); + + result.ForEach(x => x.Event.EventType.ShouldStartWith(KurrentTemporaryFixture.AnotherTestEventTypePrefix)); } - + [Fact(Skip = "Not Implemented")] public Task be_able_to_read_all_one_by_one_until_end_of_stream() => throw new NotImplementedException(); diff --git a/test/EventStore.Client.Streams.Tests/Read/ReadAllEventsFixture.cs b/test/Kurrent.Client.Tests/Streams/Read/ReadAllEventsFixture.cs similarity index 80% rename from test/EventStore.Client.Streams.Tests/Read/ReadAllEventsFixture.cs rename to test/Kurrent.Client.Tests/Streams/Read/ReadAllEventsFixture.cs index 197c8a481..f3d2562e1 100644 --- a/test/EventStore.Client.Streams.Tests/Read/ReadAllEventsFixture.cs +++ b/test/Kurrent.Client.Tests/Streams/Read/ReadAllEventsFixture.cs @@ -1,6 +1,13 @@ -namespace EventStore.Client.Streams.Tests.Read; +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; -public class ReadAllEventsFixture : EventStoreFixture { +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Streams")] +[Trait("Category", "Target:All")] +[Trait("Category", "Operation:Read")] +[Trait("Category", "Database:Dedicated")] +public class ReadAllEventsFixture : KurrentTemporaryFixture { public ReadAllEventsFixture() { OnSetup = async () => { _ = await Streams.SetStreamMetadataAsync( @@ -36,4 +43,4 @@ public ReadAllEventsFixture() { public EventBinaryData ExpectedFirstEvent { get; private set; } public EventBinaryData ExpectedLastEvent { get; private set; } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Read/read_all_events_forward.cs b/test/Kurrent.Client.Tests/Streams/Read/ReadAllEventsForwardTests.cs similarity index 90% rename from test/EventStore.Client.Streams.Tests/Read/read_all_events_forward.cs rename to test/Kurrent.Client.Tests/Streams/Read/ReadAllEventsForwardTests.cs index fed9629ad..f1c4ec2bd 100644 --- a/test/EventStore.Client.Streams.Tests/Read/read_all_events_forward.cs +++ b/test/Kurrent.Client.Tests/Streams/Read/ReadAllEventsForwardTests.cs @@ -1,12 +1,15 @@ using System.Text; +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; -namespace EventStore.Client.Streams.Tests.Read; +namespace Kurrent.Client.Tests; +[Trait("Category", "Target:Streams")] [Trait("Category", "Target:All")] [Trait("Category", "Operation:Read")] [Trait("Category", "Operation:Read:Forwards")] [Trait("Category", "Database:Dedicated")] -public class read_all_events_forward(ITestOutputHelper output, ReadAllEventsFixture fixture) : EventStoreTests(output, fixture) { +public class ReadAllEventsForwardTests(ITestOutputHelper output, ReadAllEventsFixture fixture) : KurrentTemporaryTests(output, fixture) { [Fact] public async Task return_empty_if_reading_from_end() { var result = await Fixture.Streams.ReadAllAsync(Direction.Forwards, Position.End, 1).CountAsync(); @@ -27,7 +30,7 @@ public async Task return_events_in_correct_order_compared_to_written() { .ReadAllAsync(Direction.Forwards, Position.Start) .Where(x => x.OriginalStreamId == Fixture.ExpectedStreamName) .ToBinaryData(); - + result.ShouldBe(Fixture.ExpectedEvents); } @@ -36,7 +39,7 @@ public async Task return_single_event() { var result = await Fixture.Streams .ReadAllAsync(Direction.Forwards, Position.Start, 1) .ToArrayAsync(); - + result.ShouldHaveSingleItem(); } @@ -59,22 +62,22 @@ public async Task reads_all_events_by_default() { Assert.True(count >= Fixture.ExpectedEvents.Length); } - + [Fact] public async Task stream_found() { var count = await Fixture.Streams .ReadAllAsync(Direction.Forwards, Position.Start) .Where(x => x.OriginalStreamId == Fixture.ExpectedStreamName) .CountAsync(); - + count.ShouldBe(Fixture.ExpectedEvents.Length); } - + [Fact] public async Task with_linkto_passed_max_count_one_event_is_read() { const string deletedStream = nameof(deletedStream); const string linkedStream = nameof(linkedStream); - + await Fixture.Streams.AppendToStreamAsync(deletedStream, StreamState.Any, Fixture.CreateTestEvents()); await Fixture.Streams.SetStreamMetadataAsync( deletedStream, @@ -105,10 +108,10 @@ await Fixture.Streams.AppendToStreamAsync( resolveLinkTos: true ) .ToArrayAsync(); - + Assert.Single(events); } - + [Fact] public async Task enumeration_all_referencing_messages_twice_does_not_throw() { var result = Fixture.Streams.ReadAllAsync( @@ -138,16 +141,16 @@ await Assert.ThrowsAsync( await result.Messages.ToArrayAsync() ); } - + [Fact] public async Task filter_events_by_type() { var result = await Fixture.Streams - .ReadAllAsync(Direction.Forwards, Position.Start, EventTypeFilter.Prefix(EventStoreFixture.AnotherTestEventTypePrefix)) + .ReadAllAsync(Direction.Forwards, Position.Start, EventTypeFilter.Prefix(KurrentTemporaryFixture.AnotherTestEventTypePrefix)) .ToListAsync(); - - result.ForEach(x => x.Event.EventType.ShouldStartWith(EventStoreFixture.AnotherTestEventTypePrefix)); + + result.ForEach(x => x.Event.EventType.ShouldStartWith(KurrentTemporaryFixture.AnotherTestEventTypePrefix)); } - + [Fact(Skip = "Not Implemented")] public Task be_able_to_read_all_one_by_one_until_end_of_stream() => throw new NotImplementedException(); diff --git a/test/EventStore.Client.Streams.Tests/Read/read_stream_backward.cs b/test/Kurrent.Client.Tests/Streams/Read/ReadStreamBackwardTests.cs similarity index 95% rename from test/EventStore.Client.Streams.Tests/Read/read_stream_backward.cs rename to test/Kurrent.Client.Tests/Streams/Read/ReadStreamBackwardTests.cs index ec32888e8..04e8c441b 100644 --- a/test/EventStore.Client.Streams.Tests/Read/read_stream_backward.cs +++ b/test/Kurrent.Client.Tests/Streams/Read/ReadStreamBackwardTests.cs @@ -1,11 +1,15 @@ +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; using Grpc.Core; -namespace EventStore.Client.Streams.Tests.Read; +namespace Kurrent.Client.Tests; -[Trait("Category", "Target:Stream")] +[Trait("Category", "Target:Streams")] +[Trait("Category", "Target:Streams")] [Trait("Category", "Operation:Read")] [Trait("Category", "Operation:Read:Backwards")] -public class read_stream_backward(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { +public class ReadStreamBackwardTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { [Theory] [InlineData(0)] public async Task count_le_equal_zero_throws(long maxCount) { @@ -165,7 +169,7 @@ await Fixture.Streams.AppendToStreamAsync( [Fact] public async Task populates_log_position_of_event() { - if (EventStoreTestServer.Version.Major < 22) + if (KurrentTemporaryTestNode.Version.Major < 22) return; var stream = Fixture.GetStreamName(); @@ -181,7 +185,7 @@ public async Task populates_log_position_of_event() { Assert.Equal(writeResult.LogPosition.PreparePosition, writeResult.LogPosition.CommitPosition); Assert.Equal(writeResult.LogPosition, actual.First().Position); } - + [Fact] public async Task with_timeout_fails_when_operation_expired() { var stream = Fixture.GetStreamName(); @@ -203,7 +207,7 @@ public async Task with_timeout_fails_when_operation_expired() { Assert.Equal(StatusCode.DeadlineExceeded, rpcException.StatusCode); } - + [Fact] public async Task enumeration_referencing_messages_twice_does_not_throw() { var result = Fixture.Streams.ReadStreamAsync( @@ -235,7 +239,7 @@ await Assert.ThrowsAsync( await result.Messages.ToArrayAsync() ); } - + [Fact] public async Task stream_not_found() { var result = await Fixture.Streams.ReadStreamAsync( @@ -250,7 +254,7 @@ public async Task stream_not_found() { [Fact] public async Task stream_found() { const int eventCount = 32; - + var events = Fixture.CreateTestEvents(eventCount).ToArray(); var streamName = Fixture.GetStreamName(); @@ -274,4 +278,4 @@ public async Task stream_found() { if (Fixture.EventStoreHasLastStreamPosition) Assert.Equal(new StreamMessage.LastStreamPosition(new(31)), result[^1]); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Read/read_stream_events_linked_to_deleted_stream.cs b/test/Kurrent.Client.Tests/Streams/Read/ReadStreamEventsLinkedToDeletedStreamTests.cs similarity index 67% rename from test/EventStore.Client.Streams.Tests/Read/read_stream_events_linked_to_deleted_stream.cs rename to test/Kurrent.Client.Tests/Streams/Read/ReadStreamEventsLinkedToDeletedStreamTests.cs index ba11b75f0..b1a803c71 100644 --- a/test/EventStore.Client.Streams.Tests/Read/read_stream_events_linked_to_deleted_stream.cs +++ b/test/Kurrent.Client.Tests/Streams/Read/ReadStreamEventsLinkedToDeletedStreamTests.cs @@ -1,13 +1,19 @@ using System.Text; +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; -namespace EventStore.Client.Streams.Tests.Read; +// ReSharper disable ClassNeverInstantiated.Global -[Trait("Category", "Target:Stream")] -public abstract class read_stream_events_linked_to_deleted_stream(ReadEventsLinkedToDeletedStreamFixture fixture) { +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Streams")] +[Trait("Category", "Target:Streams")] +public abstract class ReadStreamEventsLinkedToDeletedStreamTests(ReadEventsLinkedToDeletedStreamFixture fixture) { ReadEventsLinkedToDeletedStreamFixture Fixture { get; } = fixture; [Fact] - public void one_event_is_read() => Assert.Single(Fixture.Events ?? Array.Empty()); + public void one_event_is_read() => Assert.Single(Fixture.Events ?? []); [Fact] public void the_linked_event_is_not_resolved() => Assert.Null(Fixture.Events![0].Event); @@ -17,32 +23,30 @@ public abstract class read_stream_events_linked_to_deleted_stream(ReadEventsLink [Fact] public void the_event_is_not_resolved() => Assert.False(Fixture.Events![0].IsResolved); - + + [UsedImplicitly] [Trait("Category", "Operation:Read")] [Trait("Category", "Operation:Read:Forwards")] - public class @forwards(forwards.CustomFixture fixture) - : read_stream_events_linked_to_deleted_stream(fixture), IClassFixture { - + public class Forwards(Forwards.CustomFixture fixture) : ReadStreamEventsLinkedToDeletedStreamTests(fixture), IClassFixture { public class CustomFixture() : ReadEventsLinkedToDeletedStreamFixture(Direction.Forwards); } - + + [UsedImplicitly] [Trait("Category", "Operation:Read")] [Trait("Category", "Operation:Read:Backwards")] - public class @backwards(backwards.CustomFixture fixture) - : read_stream_events_linked_to_deleted_stream(fixture), IClassFixture { - + public class Backwards(Backwards.CustomFixture fixture) : ReadStreamEventsLinkedToDeletedStreamTests(fixture), IClassFixture { public class CustomFixture() : ReadEventsLinkedToDeletedStreamFixture(Direction.Backwards); } } -public abstract class ReadEventsLinkedToDeletedStreamFixture : EventStoreFixture { +public abstract class ReadEventsLinkedToDeletedStreamFixture : KurrentTemporaryFixture { const string DeletedStream = nameof(DeletedStream); const string LinkedStream = nameof(LinkedStream); protected ReadEventsLinkedToDeletedStreamFixture(Direction direction) { OnSetup = async () => { await Streams.AppendToStreamAsync(DeletedStream, StreamState.Any, CreateTestEvents()); - + await Streams.AppendToStreamAsync( LinkedStream, StreamState.Any, @@ -58,7 +62,7 @@ await Streams.AppendToStreamAsync( ); await Streams.DeleteAsync(DeletedStream, StreamState.Any); - + Events = await Streams.ReadStreamAsync( direction, LinkedStream, @@ -70,4 +74,4 @@ await Streams.AppendToStreamAsync( } public ResolvedEvent[]? Events { get; private set; } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Read/read_stream_forward.cs b/test/Kurrent.Client.Tests/Streams/Read/ReadStreamForwardTests.cs similarity index 95% rename from test/EventStore.Client.Streams.Tests/Read/read_stream_forward.cs rename to test/Kurrent.Client.Tests/Streams/Read/ReadStreamForwardTests.cs index 14c08a79c..1e8d5db5b 100644 --- a/test/EventStore.Client.Streams.Tests/Read/read_stream_forward.cs +++ b/test/Kurrent.Client.Tests/Streams/Read/ReadStreamForwardTests.cs @@ -1,9 +1,12 @@ -namespace EventStore.Client.Streams.Tests.Read; +using EventStore.Client; -[Trait("Category", "Target:Stream")] +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Streams")] +[Trait("Category", "Target:Streams")] [Trait("Category", "Operation:Read")] [Trait("Category", "Operation:Read:Forwards")] -public class read_stream_forward(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { +public class ReadStreamForwardTests(ITestOutputHelper output, KurrentPermanentFixture fixture) : KurrentPermanentTests(output, fixture) { [Theory] [InlineData(0)] public async Task count_le_equal_zero_throws(long maxCount) { @@ -159,7 +162,7 @@ await Fixture.Streams.AppendToStreamAsync( [Fact] public async Task populates_log_position_of_event() { - if (EventStoreTestServer.Version.Major < 22) + if (KurrentPermanentTestNode.Version.Major < 22) return; var stream = Fixture.GetStreamName(); @@ -191,7 +194,7 @@ public async Task stream_not_found() { [Fact] public async Task stream_found() { const int eventCount = 64; - + var events = Fixture.CreateTestEvents(eventCount).ToArray(); var streamName = Fixture.GetStreamName(); @@ -226,7 +229,7 @@ public async Task stream_found() { [Fact] public async Task stream_found_truncated() { const int eventCount = 64; - + var events = Fixture.CreateTestEvents(eventCount).ToArray(); var streamName = Fixture.GetStreamName(); @@ -263,4 +266,4 @@ await Fixture.Streams.SetStreamMetadataAsync( result[^1] ); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Read/read_stream_when_having_max_count_set_for_stream.cs b/test/Kurrent.Client.Tests/Streams/Read/ReadStreamWhenHavingMaxCountSetForStreamTests.cs similarity index 91% rename from test/EventStore.Client.Streams.Tests/Read/read_stream_when_having_max_count_set_for_stream.cs rename to test/Kurrent.Client.Tests/Streams/Read/ReadStreamWhenHavingMaxCountSetForStreamTests.cs index 0142ebd9a..1e22b5eb1 100644 --- a/test/EventStore.Client.Streams.Tests/Read/read_stream_when_having_max_count_set_for_stream.cs +++ b/test/Kurrent.Client.Tests/Streams/Read/ReadStreamWhenHavingMaxCountSetForStreamTests.cs @@ -1,8 +1,14 @@ -namespace EventStore.Client.Streams.Tests.Read; +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; +using Kurrent.Client.Tests; -[Trait("Category", "Target:Stream")] +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Streams")] +[Trait("Category", "Target:Streams")] [Trait("Category", "Operation:Read")] -public class read_stream_when_having_max_count_set_for_stream (ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { +public class ReadStreamWhenHavingMaxCountSetForStreamTests(ITestOutputHelper output, KurrentTemporaryFixture fixture) + : KurrentTemporaryTests(output, fixture) { [Fact] public async Task read_stream_forwards_respects_max_count() { var stream = Fixture.GetStreamName(); @@ -118,4 +124,4 @@ public async Task after_setting_more_strict_max_count_read_stream_backwards_read Assert.Equal(2, actual.Length); Assert.True(EventDataComparer.Equal(expected.Skip(3).Reverse().ToArray(), actual)); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Delete/soft_deleted_stream.cs b/test/Kurrent.Client.Tests/Streams/SoftDeleteTests.cs similarity index 94% rename from test/EventStore.Client.Streams.Tests/Delete/soft_deleted_stream.cs rename to test/Kurrent.Client.Tests/Streams/SoftDeleteTests.cs index 25877d2ee..3e8cf2617 100644 --- a/test/EventStore.Client.Streams.Tests/Delete/soft_deleted_stream.cs +++ b/test/Kurrent.Client.Tests/Streams/SoftDeleteTests.cs @@ -1,12 +1,14 @@ using System.Text.Json; +using EventStore.Client; -namespace EventStore.Client.Streams.Tests.Delete; +namespace Kurrent.Client.Tests.Streams; +[Trait("Category", "Target:Streams")] [Trait("Category", "Operation:Delete")] -public class deleted_stream(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { +public class SoftDeleteTests(ITestOutputHelper output, KurrentPermanentFixture fixture) : KurrentPermanentTests(output, fixture) { static JsonDocument CustomMetadata { get; } - static deleted_stream() { + static SoftDeleteTests() { var customMetadata = new Dictionary { ["key1"] = true, ["key2"] = 17, @@ -15,7 +17,7 @@ static deleted_stream() { CustomMetadata = JsonDocument.Parse(JsonSerializer.Serialize(customMetadata)); } - + [Fact] public async Task reading_throws() { var stream = Fixture.GetStreamName(); @@ -36,13 +38,7 @@ await Assert.ThrowsAsync( ); } - public static IEnumerable RecreatingTestCases() { - yield return new object?[] { StreamState.Any, nameof(StreamState.Any) }; - yield return new object?[] { StreamState.NoStream, nameof(StreamState.NoStream) }; - } - - [Theory] - [MemberData(nameof(RecreatingTestCases))] + [Theory, RecreatingTestCases] public async Task recreated_with_any_expected_version(StreamState expectedState, string name) { var stream = $"{Fixture.GetStreamName()}_{name}"; @@ -124,7 +120,7 @@ public async Task recreated_with_expected_version() { [Fact] public async Task recreated_preserves_metadata_except_truncate_before() { - const int count = 2; + const int count = 2; var stream = Fixture.GetStreamName(); @@ -213,9 +209,7 @@ await Fixture.Streams.AppendToStreamAsync( Assert.Equal(SystemStreams.MetastreamOf(stream), ex.Stream); - await Assert.ThrowsAsync( - () => Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, Fixture.CreateTestEvents()) - ); + await Assert.ThrowsAsync(() => Fixture.Streams.AppendToStreamAsync(stream, StreamState.Any, Fixture.CreateTestEvents())); } [Fact] @@ -366,7 +360,7 @@ await Assert.ThrowsAsync( [Fact] public async Task recreated_on_non_empty_when_metadata_set() { - const int count = 2; + const int count = 2; var stream = Fixture.GetStreamName(); @@ -420,4 +414,11 @@ public async Task recreated_on_non_empty_when_metadata_set() { Assert.Equal(expected, metadataResult.Metadata); } -} \ No newline at end of file + + class RecreatingTestCases : TestCaseGenerator { + protected override IEnumerable Data() { + yield return [StreamState.Any, nameof(StreamState.Any)]; + yield return [StreamState.NoStream, nameof(StreamState.NoStream)]; + } + } +} diff --git a/test/EventStore.Client.Streams.Tests/Metadata/stream_metadata.cs b/test/Kurrent.Client.Tests/Streams/StreamMetadataTests.cs similarity index 92% rename from test/EventStore.Client.Streams.Tests/Metadata/stream_metadata.cs rename to test/Kurrent.Client.Tests/Streams/StreamMetadataTests.cs index 706d5e2b6..a02083f6c 100644 --- a/test/EventStore.Client.Streams.Tests/Metadata/stream_metadata.cs +++ b/test/Kurrent.Client.Tests/Streams/StreamMetadataTests.cs @@ -1,10 +1,12 @@ using System.Text.Json; +using EventStore.Client; using Grpc.Core; -namespace EventStore.Client.Streams.Tests.Metadata; +namespace Kurrent.Client.Tests.Streams; -[Trait("Category", "Metadata")] -public class stream_metadata(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests(output, fixture) { +[Trait("Category", "Target:Streams")] +[Trait("Category", "Operation:Metadata")] +public class StreamMetadataTests(ITestOutputHelper output, KurrentPermanentFixture fixture) : KurrentPermanentTests(output, fixture) { [Fact] public async Task getting_for_an_existing_stream_and_no_metadata_exists() { var stream = Fixture.GetStreamName(); @@ -150,7 +152,7 @@ public async Task latest_metadata_returned_stream_revision_any() { Assert.Equal(expected.CacheControl, actual.Metadata.CacheControl); Assert.Equal(expected.Acl, actual.Metadata.Acl); } - + [Fact] public async Task with_timeout_set_with_any_stream_revision_fails_when_operation_expired() { var stream = Fixture.GetStreamName(); @@ -186,9 +188,7 @@ public async Task with_timeout_set_with_stream_revision_fails_when_operation_exp [Fact] public async Task with_timeout_get_fails_when_operation_expired() { - var stream = Fixture.GetStreamName(); - var rpcException = await Assert.ThrowsAsync( - () => Fixture.Streams.GetStreamMetadataAsync(stream, TimeSpan.Zero) - ); + var stream = Fixture.GetStreamName(); + var rpcException = await Assert.ThrowsAsync(() => Fixture.Streams.GetStreamMetadataAsync(stream, TimeSpan.Zero)); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionFilter.cs b/test/Kurrent.Client.Tests/Streams/SubscriptionFilter.cs similarity index 91% rename from test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionFilter.cs rename to test/Kurrent.Client.Tests/Streams/SubscriptionFilter.cs index e670b69c9..91621aba9 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionFilter.cs +++ b/test/Kurrent.Client.Tests/Streams/SubscriptionFilter.cs @@ -1,8 +1,12 @@ -namespace EventStore.Client.Streams.Tests.Subscriptions; +// ReSharper disable InconsistentNaming + +using EventStore.Client; + +namespace Kurrent.Client.Tests.Streams; public record SubscriptionFilter(string Name, Func Create, Func PrepareEvent) { public override string ToString() => Name; - + static readonly SubscriptionFilter StreamNamePrefix = new(nameof(StreamNamePrefix), StreamFilter.Prefix, (_, evt) => evt); static readonly SubscriptionFilter StreamNameRegex = new(nameof(StreamNameRegex), f => StreamFilter.RegularExpression(f), (_, evt) => evt); static readonly SubscriptionFilter EventTypePrefix = new(nameof(EventTypePrefix), EventTypeFilter.Prefix, (term, evt) => new(evt.EventId, term, evt.Data, evt.Metadata, evt.ContentType)); @@ -15,10 +19,10 @@ static SubscriptionFilter() { EventTypePrefix, EventTypeRegex }; - + TestCases = All.Select(x => new object[] { x }); } public static SubscriptionFilter[] All { get; } public static IEnumerable TestCases { get; } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/Obsolete/subscribe_to_all_obsolete.cs b/test/Kurrent.Client.Tests/Streams/Subscriptions/Obsolete/SubscribeToAllObsoleteTests.cs similarity index 93% rename from test/EventStore.Client.Streams.Tests/Subscriptions/Obsolete/subscribe_to_all_obsolete.cs rename to test/Kurrent.Client.Tests/Streams/Subscriptions/Obsolete/SubscribeToAllObsoleteTests.cs index af4b5ac43..b42cf782e 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/Obsolete/subscribe_to_all_obsolete.cs +++ b/test/Kurrent.Client.Tests/Streams/Subscriptions/Obsolete/SubscribeToAllObsoleteTests.cs @@ -1,9 +1,14 @@ -namespace EventStore.Client.Streams.Tests.Subscriptions.Obsolete; +using EventStore.Client; +using Kurrent.Client.Tests.Streams; +using Kurrent.Client.Tests.TestNode; -[Trait("Category", "Subscriptions")] -[Trait("Category", "Target:All")] +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Streams")] +[Trait("Category", "Operation:Subscriptions")] [Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class subscribe_to_all_obsolete(ITestOutputHelper output, SubscriptionsFixture fixture) : EventStoreTests(output, fixture) { +public class SubscribeToAllObsoleteTests(ITestOutputHelper output, SubscribeToAllObsoleteTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { [Fact] public async Task receives_all_events_from_start() { var receivedAllEvents = new TaskCompletionSource(); @@ -11,9 +16,9 @@ public async Task receives_all_events_from_start() { var seedEvents = Fixture.CreateTestEvents(10).ToArray(); var pageSize = seedEvents.Length / 2; - + var availableEvents = new HashSet(seedEvents.Select(x => x.EventId)); - + foreach (var evt in seedEvents.Take(pageSize)) await Fixture.Streams.AppendToStreamAsync($"stream-{evt.EventId.ToGuid():N}", StreamState.NoStream, new[] { evt }); @@ -34,33 +39,33 @@ 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_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(); @@ -79,24 +84,24 @@ public async Task receives_all_events_from_end() { subscription.Dispose(); var result = await subscriptionDropped.Task.WithTimeout(); result.ShouldBe(SubscriptionDroppedResult.Disposed()); - + return; Task OnReceived(StreamSubscription sub, ResolvedEvent re, CancellationToken ct) { availableEvents.RemoveWhere(x => x == re.OriginalEvent.EventId); - + if (availableEvents.Count == 0) { receivedAllEvents.TrySetResult(true); Fixture.Log.Information("Received all {TotalEventsCount} expected events", seedEvents.Length); } - + return Task.CompletedTask; } void OnDropped(StreamSubscription sub, SubscriptionDroppedReason reason, Exception? ex) => subscriptionDropped.SetResult(new(reason, ex)); } - + [Fact] public async Task receives_all_events_from_position() { var receivedAllEvents = new TaskCompletionSource(); @@ -104,16 +109,16 @@ public async Task receives_all_events_from_position() { var seedEvents = Fixture.CreateTestEvents(10).ToArray(); var pageSize = seedEvents.Length / 2; - + // only the second half of the events will be received var availableEvents = new HashSet(seedEvents.Skip(pageSize).Select(x => x.EventId)); - + IWriteResult writeResult = new SuccessResult(); foreach (var evt in seedEvents.Take(pageSize)) writeResult = await Fixture.Streams.AppendToStreamAsync($"stream-{evt.EventId.ToGuid():N}", StreamState.NoStream, new[] { evt }); var position = FromAll.After(writeResult.LogPosition); - + using var subscription = await Fixture.Streams .SubscribeToAllAsync(position, OnReceived, false, OnDropped) .WithTimeout(); @@ -131,24 +136,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_with_resolved_links() { var streamName = Fixture.GetStreamName(); @@ -158,13 +163,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 .SubscribeToAllAsync(FromAll.Start, OnReceived, true, OnDropped) .WithTimeout(); - + await receivedAllEvents.Task.WithTimeout(); // if the subscription dropped before time, raise the reason why @@ -175,63 +180,63 @@ 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) { - var hasResolvedLink = re.OriginalEvent.EventStreamId.StartsWith($"$et-{EventStoreFixture.TestEventType}"); + var hasResolvedLink = re.OriginalEvent.EventStreamId.StartsWith($"$et-{KurrentTemporaryFixture.TestEventType}"); if (availableEvents.RemoveWhere(x => x == re.Event.EventId && hasResolvedLink) == 0) { Fixture.Log.Debug("Received unexpected event {EventId} from stream {StreamId}", re.Event.EventId, re.OriginalEvent.EventStreamId); return Task.CompletedTask; } - + if (availableEvents.Count == 0) { receivedAllEvents.TrySetResult(true); Fixture.Log.Information("Received all {TotalEventsCount} expected events", seedEvents.Length); } - + return Task.CompletedTask; } void OnDropped(StreamSubscription sub, SubscriptionDroppedReason reason, Exception? ex) => subscriptionDropped.SetResult(new(reason, ex)); } - + [Theory] - [MemberData(nameof(SubscriptionFilter.TestCases), MemberType= typeof(SubscriptionFilter))] + [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(); @@ -239,17 +244,17 @@ public async Task receives_all_filtered_events_from_start(SubscriptionFilter fil // 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(); @@ -266,8 +271,7 @@ Task OnReceived(StreamSubscription sub, ResolvedEvent re, CancellationToken ct) receivedAllEvents.TrySetException( new InvalidOperationException($"Received unexpected event {re.OriginalEvent.EventId} from stream {re.OriginalEvent.EventStreamId}") ); - } - else { + } else { Fixture.Log.Verbose("Received expected event {EventId} from {StreamId}.", re.OriginalEvent.EventId, re.OriginalEvent.EventStreamId); } @@ -290,45 +294,48 @@ void OnDropped(StreamSubscription sub, SubscriptionDroppedReason reason, Excepti 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 + position, + seedEvents.Length - availableEvents.Count, + seedEvents.Length ); + checkpointReached.TrySetResult(true); return Task.CompletedTask; } } - + [Theory] - [MemberData(nameof(SubscriptionFilter.TestCases), MemberType= typeof(SubscriptionFilter))] + [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(); @@ -336,20 +343,20 @@ public async Task receives_all_filtered_events_from_end(SubscriptionFilter filte // 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) { @@ -363,8 +370,7 @@ Task OnReceived(StreamSubscription sub, ResolvedEvent re, CancellationToken ct) receivedAllEvents.TrySetException( new InvalidOperationException($"Received unexpected event {re.OriginalEvent.EventId} from stream {re.OriginalEvent.EventStreamId}") ); - } - else { + } else { Fixture.Log.Verbose("Received expected event {EventId} from {StreamId}", re.OriginalEvent.EventId, re.OriginalEvent.EventStreamId); } @@ -387,48 +393,51 @@ void OnDropped(StreamSubscription sub, SubscriptionDroppedReason reason, Excepti Task CheckpointReached(StreamSubscription sub, Position position, CancellationToken ct) { Fixture.Log.Verbose( "Checkpoint reached {Position}. Received {ReceivedEventsCount}/{TotalEventsCount} events", - position, pageSize - availableEvents.Count, pageSize + position, + pageSize - availableEvents.Count, + pageSize ); + checkpointReached.TrySetResult(true); return Task.CompletedTask; } } [Theory] - [MemberData(nameof(SubscriptionFilter.TestCases), MemberType= typeof(SubscriptionFilter))] + [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(); @@ -436,20 +445,20 @@ public async Task receives_all_filtered_events_from_position(SubscriptionFilter // 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) { @@ -463,8 +472,7 @@ Task OnReceived(StreamSubscription sub, ResolvedEvent re, CancellationToken ct) receivedAllEvents.TrySetException( new InvalidOperationException($"Received unexpected event {re.OriginalEvent.EventId} from stream {re.OriginalEvent.EventStreamId}") ); - } - else { + } else { Fixture.Log.Verbose("Received expected event {EventId} from {StreamId}", re.OriginalEvent.EventId, re.OriginalEvent.EventStreamId); } @@ -487,13 +495,16 @@ void OnDropped(StreamSubscription sub, SubscriptionDroppedReason reason, Excepti Task CheckpointReached(StreamSubscription sub, Position position, CancellationToken ct) { Fixture.Log.Verbose( "Checkpoint reached {Position}. Received {ReceivedEventsCount}/{TotalEventsCount} events", - position, pageSize - availableEvents.Count, pageSize + 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(); @@ -503,17 +514,15 @@ public async Task receives_all_filtered_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); - var options = new SubscriptionFilterOptions( - StreamFilter.Prefix($"$et-{EventStoreFixture.TestEventType}") - ); - + var options = new SubscriptionFilterOptions(StreamFilter.Prefix($"$et-{KurrentTemporaryFixture.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 @@ -524,32 +533,32 @@ public async Task receives_all_filtered_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) { - var hasResolvedLink = re.OriginalEvent.EventStreamId.StartsWith($"$et-{EventStoreFixture.TestEventType}"); + var hasResolvedLink = re.OriginalEvent.EventStreamId.StartsWith($"$et-{KurrentTemporaryFixture.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, @@ -562,7 +571,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(); @@ -574,7 +583,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, @@ -589,4 +598,19 @@ public async Task drops_when_subscriber_error() { var result = await subscriptionDropped.Task.WithTimeout(); result.ShouldBe(expectedResult); } + + public class CustomFixture : KurrentTemporaryFixture { + public CustomFixture() : 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)); + }; + } + } } diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/Obsolete/subscribe_to_stream_obsolete.cs b/test/Kurrent.Client.Tests/Streams/Subscriptions/Obsolete/SubscribeToStreamObsoleteTests.cs similarity index 91% rename from test/EventStore.Client.Streams.Tests/Subscriptions/Obsolete/subscribe_to_stream_obsolete.cs rename to test/Kurrent.Client.Tests/Streams/Subscriptions/Obsolete/SubscribeToStreamObsoleteTests.cs index 4e05b293b..2a2c3f10f 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/Obsolete/subscribe_to_stream_obsolete.cs +++ b/test/Kurrent.Client.Tests/Streams/Subscriptions/Obsolete/SubscribeToStreamObsoleteTests.cs @@ -1,9 +1,13 @@ -namespace EventStore.Client.Streams.Tests.Subscriptions.Obsolete; +using EventStore.Client; +using Kurrent.Client.Tests.TestNode; -[Trait("Category", "Subscriptions")] -[Trait("Category", "Target:Stream")] +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:Streams")] +[Trait("Category", "Operation:Subscriptions")] [Obsolete("Will be removed in future release when older subscriptions APIs are removed from the client")] -public class subscribe_to_stream_obsolete(ITestOutputHelper output, SubscriptionsFixture fixture) : EventStoreTests(output, fixture) { +public class SubscribeToStreamObsoleteTests(ITestOutputHelper output, SubscribeToStreamObsoleteTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { [Fact] public async Task receives_all_events_from_start() { var streamName = Fixture.GetStreamName(); @@ -266,7 +270,7 @@ public async Task receives_all_events_with_resolved_links() { await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, seedEvents); using var subscription = await Fixture.Streams - .SubscribeToStreamAsync($"$et-{EventStoreFixture.TestEventType}", FromStream.Start, OnReceived, true, OnDropped) + .SubscribeToStreamAsync($"$et-{KurrentTemporaryFixture.TestEventType}", FromStream.Start, OnReceived, true, OnDropped) .WithTimeout(); await receivedAllEvents.Task.WithTimeout(); @@ -283,7 +287,7 @@ public async Task receives_all_events_with_resolved_links() { return; Task OnReceived(StreamSubscription sub, ResolvedEvent re, CancellationToken ct) { - var hasResolvedLink = re.OriginalEvent.EventStreamId.StartsWith($"$et-{EventStoreFixture.TestEventType}"); + var hasResolvedLink = re.OriginalEvent.EventStreamId.StartsWith($"$et-{KurrentTemporaryFixture.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; @@ -300,4 +304,19 @@ Task OnReceived(StreamSubscription sub, ResolvedEvent re, CancellationToken ct) void OnDropped(StreamSubscription sub, SubscriptionDroppedReason reason, Exception? ex) => subscriptionDropped.SetResult(new(reason, ex)); } + + public class CustomFixture : KurrentTemporaryFixture { + public CustomFixture() : 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)); + }; + } + } } diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs b/test/Kurrent.Client.Tests/Streams/Subscriptions/SubscribeToAllTests.cs similarity index 93% rename from test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs rename to test/Kurrent.Client.Tests/Streams/Subscriptions/SubscribeToAllTests.cs index 2e9879a4a..33d63b280 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_all.cs +++ b/test/Kurrent.Client.Tests/Streams/Subscriptions/SubscribeToAllTests.cs @@ -1,9 +1,13 @@ -namespace EventStore.Client.Streams.Tests.Subscriptions; +using EventStore.Client; +using Kurrent.Client.Tests.Streams; +using Kurrent.Client.Tests.TestNode; + +namespace Kurrent.Client.Tests; [Trait("Category", "Subscriptions")] -[Trait("Category", "Target:All")] -public class subscribe_to_all(ITestOutputHelper output, SubscriptionsFixture fixture) - : EventStoreTests(output, fixture) { +[Trait("Category", "Target:Streams")] +public class SubscribeToAllTests(ITestOutputHelper output, SubscribeToAllTests.CustomFixture fixture) + : KurrentTemporaryTests(output, fixture) { [Fact] public async Task receives_all_events_from_start() { var seedEvents = Fixture.CreateTestEvents(10).ToArray(); @@ -445,9 +449,7 @@ public async Task receives_all_filtered_events_with_resolved_links() { await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, seedEvents); - var filterOptions = new SubscriptionFilterOptions( - StreamFilter.Prefix($"$et-{EventStoreFixture.TestEventType}") - ); + var filterOptions = new SubscriptionFilterOptions(StreamFilter.Prefix($"$et-{KurrentPermanentFixture.TestEventType}")); await using var subscription = Fixture.Streams.SubscribeToAll(FromAll.Start, true, filterOptions: filterOptions); @@ -465,7 +467,7 @@ public async Task receives_all_filtered_events_with_resolved_links() { async Task Subscribe() { while (await enumerator.MoveNextAsync()) { if (enumerator.Current is not StreamMessage.Event(var resolvedEvent) || - !resolvedEvent.OriginalEvent.EventStreamId.StartsWith($"$et-{EventStoreFixture.TestEventType}")) { + !resolvedEvent.OriginalEvent.EventStreamId.StartsWith($"$et-{KurrentPermanentFixture.TestEventType}")) { continue; } @@ -477,4 +479,19 @@ async Task Subscribe() { } } } + + public class CustomFixture : KurrentTemporaryFixture { + public CustomFixture() : 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)); + }; + } + } } diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs b/test/Kurrent.Client.Tests/Streams/Subscriptions/SubscribeToStreamTests.cs similarity index 80% rename from test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs rename to test/Kurrent.Client.Tests/Streams/Subscriptions/SubscribeToStreamTests.cs index d38391e8f..304144e9b 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/subscribe_to_stream.cs +++ b/test/Kurrent.Client.Tests/Streams/Subscriptions/SubscribeToStreamTests.cs @@ -1,10 +1,12 @@ -namespace EventStore.Client.Streams.Tests.Subscriptions; +using EventStore.Client; + +namespace Kurrent.Client.Tests.Streams; [Trait("Category", "Subscriptions")] -[Trait("Category", "Target:Stream")] -public class subscribe_to_stream(ITestOutputHelper output, SubscriptionsFixture fixture) - : EventStoreTests(output, fixture) { - [Fact] +[Trait("Category", "Target:Streams")] +public class SubscribeToStreamTests(ITestOutputHelper output, SubscribeToStreamTests.CustomFixture fixture) + : KurrentPermanentTests(output, fixture) { + [RetryFact] public async Task receives_all_events_from_start() { var streamName = Fixture.GetStreamName(); @@ -43,7 +45,7 @@ async Task Subscribe() { } } - [Fact] + [RetryFact] public async Task receives_all_events_from_position() { var streamName = Fixture.GetStreamName(); @@ -91,7 +93,7 @@ async Task Subscribe() { } } - [Fact] + [RetryFact] public async Task receives_all_events_from_non_existing_stream() { var streamName = Fixture.GetStreamName(); @@ -127,7 +129,7 @@ async Task Subscribe() { } } - [Fact] + [RetryFact] public async Task allow_multiple_subscriptions_to_same_stream() { var streamName = Fixture.GetStreamName(); @@ -170,7 +172,7 @@ async Task Subscribe(IAsyncEnumerator subscription) { } } - [Fact] + [RetryFact] public async Task drops_when_stream_tombstoned() { var streamName = Fixture.GetStreamName(); @@ -193,41 +195,18 @@ public async Task drops_when_stream_tombstoned() { ex.ShouldBeOfType().Stream.ShouldBe(streamName); } - [Fact] - public async Task receives_all_events_with_resolved_links() { - var streamName = Fixture.GetStreamName(); - - var seedEvents = Fixture.CreateTestEvents(3).ToArray(); - var availableEvents = new HashSet(seedEvents.Select(x => x.EventId)); - - await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, seedEvents); - - await using var subscription = - Fixture.Streams.SubscribeToStream($"$et-{EventStoreFixture.TestEventType}", FromStream.Start, true); - - await using var enumerator = subscription.Messages.GetAsyncEnumerator(); - - Assert.True(await enumerator.MoveNextAsync()); - - Assert.IsType(enumerator.Current); - - await Subscribe().WithTimeout(); - - return; - - async Task Subscribe() { - while (await enumerator.MoveNextAsync()) { - if (enumerator.Current is not StreamMessage.Event(var resolvedEvent) || - !resolvedEvent.OriginalEvent.EventStreamId.StartsWith($"$et-{EventStoreFixture.TestEventType}")) { - continue; - } - - availableEvents.Remove(resolvedEvent.Event.EventId); - - if (availableEvents.Count == 0) { - return; - } - } + public class CustomFixture : KurrentPermanentFixture { + public CustomFixture() { + OnSetup = async () => { + await Streams.SetStreamMetadataAsync( + SystemStreams.AllStream, + StreamState.Any, + new(acl: new(SystemRoles.All)), + userCredentials: TestCredentials.Root + ); + + await Streams.AppendToStreamAsync($"SubscriptionsFixture-Noise-{Guid.NewGuid():N}", StreamState.NoStream, CreateTestEvents(10)); + }; } } } diff --git a/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionDroppedResult.cs b/test/Kurrent.Client.Tests/Streams/Subscriptions/SubscriptionDroppedResult.cs similarity index 87% rename from test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionDroppedResult.cs rename to test/Kurrent.Client.Tests/Streams/Subscriptions/SubscriptionDroppedResult.cs index 40df3eb52..6157c6cb5 100644 --- a/test/EventStore.Client.Streams.Tests/Subscriptions/SubscriptionDroppedResult.cs +++ b/test/Kurrent.Client.Tests/Streams/Subscriptions/SubscriptionDroppedResult.cs @@ -1,4 +1,6 @@ -namespace EventStore.Client.Streams.Tests.Subscriptions; +using EventStore.Client; + +namespace Kurrent.Client.Tests; public record SubscriptionDroppedResult(SubscriptionDroppedReason Reason, Exception? Error) { public Task Throw() => Task.FromException(Error!); @@ -6,11 +8,11 @@ public record SubscriptionDroppedResult(SubscriptionDroppedReason Reason, Except public static SubscriptionDroppedResult ServerError(Exception? error = null) => new(SubscriptionDroppedReason.ServerError, error ?? new Exception("Server error")); - public static SubscriptionDroppedResult SubscriberError(Exception? error = null) => + public static SubscriptionDroppedResult SubscriberError(Exception? error = null) => new(SubscriptionDroppedReason.SubscriberError, error ?? new Exception("Subscriber error")); - public static SubscriptionDroppedResult Disposed(Exception? error = null) => + 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/Kurrent.Client.Tests/UserManagement/ChangePasswordTests.cs b/test/Kurrent.Client.Tests/UserManagement/ChangePasswordTests.cs new file mode 100644 index 000000000..f393e24da --- /dev/null +++ b/test/Kurrent.Client.Tests/UserManagement/ChangePasswordTests.cs @@ -0,0 +1,69 @@ +using EventStore.Client; + +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:UserManagement")] +public class ChangePasswordTests(ITestOutputHelper output, KurrentPermanentFixture fixture) + : KurrentPermanentTests(output, fixture) { + [Theory, ChangePasswordNullInputCases] + public async Task changing_user_password_with_null_input_throws(string loginName, string currentPassword, string newPassword, string paramName) { + var ex = await Fixture.Users + .ChangePasswordAsync(loginName, currentPassword, newPassword, userCredentials: TestCredentials.Root) + .ShouldThrowAsync(); + + ex.ParamName.ShouldBe(paramName); + } + + [Theory, ChangePasswordEmptyInputCases] + public async Task changing_user_password_with_empty_input_throws(string loginName, string currentPassword, string newPassword, string paramName) { + var ex = await Fixture.Users + .ChangePasswordAsync(loginName, currentPassword, newPassword, userCredentials: TestCredentials.Root) + .ShouldThrowAsync(); + + ex.ParamName.ShouldBe(paramName); + } + + [Theory(Skip = "This can't be right")] + [ClassData(typeof(InvalidCredentialsTestCases))] + public async Task changing_user_password_with_user_with_insufficient_credentials_throws(string loginName, UserCredentials userCredentials) { + await Fixture.Users.CreateUserAsync(loginName, "Full Name", Array.Empty(), "password", userCredentials: TestCredentials.Root); + + await Fixture.Users + .ChangePasswordAsync(loginName, "password", "newPassword", userCredentials: userCredentials) + .ShouldThrowAsync(); + } + + [Fact] + public async Task changing_user_password_when_the_current_password_is_wrong_throws() { + var user = await Fixture.CreateTestUser(); + + await Fixture.Users + .ChangePasswordAsync(user.LoginName, "wrong-password", "new-password", userCredentials: TestCredentials.Root) + .ShouldThrowAsync(); + } + + [Fact] + public async Task changing_user_password_with_correct_credentials() { + var user = await Fixture.CreateTestUser(); + + await Fixture.Users + .ChangePasswordAsync(user.LoginName, user.Password, "new-password", userCredentials: TestCredentials.Root) + .ShouldNotThrowAsync(); + } + + class ChangePasswordNullInputCases : TestCaseGenerator { + protected override IEnumerable Data() { + yield return [null!, Faker.Internet.Password(), Faker.Internet.Password(), "loginName"]; + yield return [Faker.Person.UserName, null!, Faker.Internet.Password(), "currentPassword"]; + yield return [Faker.Person.UserName, Faker.Internet.Password(), null!, "newPassword"]; + } + } + + class ChangePasswordEmptyInputCases : TestCaseGenerator { + protected override IEnumerable Data() { + yield return [string.Empty, Faker.Internet.Password(), Faker.Internet.Password(), "loginName"]; + yield return [Faker.Person.UserName, string.Empty, Faker.Internet.Password(), "currentPassword"]; + yield return [Faker.Person.UserName, Faker.Internet.Password(), string.Empty, "newPassword"]; + } + } +} diff --git a/test/Kurrent.Client.Tests/UserManagement/CreateUserTests.cs b/test/Kurrent.Client.Tests/UserManagement/CreateUserTests.cs new file mode 100644 index 000000000..3096e58e5 --- /dev/null +++ b/test/Kurrent.Client.Tests/UserManagement/CreateUserTests.cs @@ -0,0 +1,93 @@ +using EventStore.Client; + +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:UserManagement")] +public class CreateUserTests(ITestOutputHelper output, CreateUserTests.CustomFixture fixture) + : KurrentPermanentTests(output, fixture) { + [Theory, CreateUserNullInputCases] + public async Task creating_user_with_null_input_throws(string loginName, string fullName, string[] groups, string password, string paramName) { + var ex = await Fixture.Users + .CreateUserAsync(loginName, fullName, groups, password, userCredentials: TestCredentials.Root) + .ShouldThrowAsync(); + + ex.ParamName.ShouldBe(paramName); + } + + [Theory, CreateUserEmptyInputCases] + public async Task creating_user_with_empty_input_throws(string loginName, string fullName, string[] groups, string password, string paramName) { + var ex = await Fixture.Users + .CreateUserAsync(loginName, fullName, groups, password, userCredentials: TestCredentials.Root) + .ShouldThrowAsync(); + + ex.ParamName.ShouldBe(paramName); + } + + [Fact] + public async Task creating_user_with_password_containing_ascii_chars() { + var user = Fakers.Users.Generate(); + + await Fixture.Users + .CreateUserAsync(user.LoginName, user.FullName, user.Groups, user.Password, userCredentials: TestCredentials.Root) + .ShouldNotThrowAsync(); + } + + [Theory] + [ClassData(typeof(InvalidCredentialsTestCases))] + public async Task creating_user_with_insufficient_credentials_throws(InvalidCredentialsTestCase testCase) => + await Fixture.Users + .CreateUserAsync( + testCase.User.LoginName, + testCase.User.FullName, + testCase.User.Groups, + testCase.User.Password, + userCredentials: testCase.User.Credentials + ) + .ShouldThrowAsync(testCase.ExpectedException); + + [Fact] + public async Task creating_user_can_be_read() { + var user = Fakers.Users.Generate(); + + await Fixture.Users + .CreateUserAsync( + user.LoginName, + user.FullName, + user.Groups, + user.Password, + userCredentials: TestCredentials.Root + ) + .ShouldNotThrowAsync(); + + var actual = await Fixture.Users.GetUserAsync(user.LoginName, userCredentials: TestCredentials.Root); + + var expected = new UserDetails( + user.Details.LoginName, + user.Details.FullName, + user.Details.Groups, + user.Details.Disabled, + actual.DateLastUpdated + ); + + actual.ShouldBeEquivalentTo(expected); + } + + class CreateUserNullInputCases : TestCaseGenerator { + protected override IEnumerable Data() { + yield return [null!, Faker.Person.UserName, Faker.Lorem.Words(), Faker.Internet.Password(), "loginName"]; + yield return [Faker.Person.UserName, null!, Faker.Lorem.Words(), Faker.Internet.Password(), "fullName"]; + yield return [Faker.Person.UserName, Faker.Person.FullName, null!, Faker.Internet.Password(), "groups"]; + yield return [Faker.Person.UserName, Faker.Person.FullName, Faker.Lorem.Words(), null!, "password"]; + } + } + + class CreateUserEmptyInputCases : TestCaseGenerator { + protected override IEnumerable Data() { + yield return [string.Empty, Faker.Person.UserName, Faker.Lorem.Words(), Faker.Internet.Password(), "loginName"]; + yield return [Faker.Person.UserName, string.Empty, Faker.Lorem.Words(), Faker.Internet.Password(), "fullName"]; + yield return [Faker.Person.UserName, Faker.Person.FullName, Faker.Lorem.Words(), string.Empty, "password"]; + } + } + + public class CustomFixture() : KurrentPermanentFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/EventStore.Client.UserManagement.Tests/deleting_a_user.cs b/test/Kurrent.Client.Tests/UserManagement/DeleteUserTests.cs similarity index 83% rename from test/EventStore.Client.UserManagement.Tests/deleting_a_user.cs rename to test/Kurrent.Client.Tests/UserManagement/DeleteUserTests.cs index 9f5948fb6..e8e4e4a9d 100644 --- a/test/EventStore.Client.UserManagement.Tests/deleting_a_user.cs +++ b/test/Kurrent.Client.Tests/UserManagement/DeleteUserTests.cs @@ -1,11 +1,10 @@ -namespace EventStore.Client.Tests; +using EventStore.Client; -public class deleting_a_user : IClassFixture { - public deleting_a_user(ITestOutputHelper output, InsecureClientTestFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); - - InsecureClientTestFixture Fixture { get; } +namespace Kurrent.Client.Tests; +[Trait("Category", "Target:UserManagement")] +public class DeleteUserTests(ITestOutputHelper output, DeleteUserTests.CustomFixture fixture) + : KurrentPermanentTests(output, fixture) { [Fact] public async Task with_null_input_throws() { var ex = await Fixture.Users @@ -65,4 +64,6 @@ public async Task a_second_time_throws() { ex.LoginName.ShouldBe(user.LoginName); } -} \ No newline at end of file + + public class CustomFixture() : KurrentPermanentFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/EventStore.Client.UserManagement.Tests/disabling_a_user.cs b/test/Kurrent.Client.Tests/UserManagement/DisableUserTests.cs similarity index 82% rename from test/EventStore.Client.UserManagement.Tests/disabling_a_user.cs rename to test/Kurrent.Client.Tests/UserManagement/DisableUserTests.cs index c72ab0295..d4be66f86 100644 --- a/test/EventStore.Client.UserManagement.Tests/disabling_a_user.cs +++ b/test/Kurrent.Client.Tests/UserManagement/DisableUserTests.cs @@ -1,10 +1,8 @@ -namespace EventStore.Client.Tests; - -public class disabling_a_user : IClassFixture { - public disabling_a_user(ITestOutputHelper output, InsecureClientTestFixture fixture) => Fixture = fixture.With(x => x.CaptureTestRun(output)); - - InsecureClientTestFixture Fixture { get; } +namespace Kurrent.Client.Tests; +[Trait("Category", "Target:UserManagement")] +public class DisableUserTests(ITestOutputHelper output, DisableUserTests.CustomFixture fixture) + : KurrentPermanentTests(output, fixture) { [Fact] public async Task with_null_input_throws() { var ex = await Fixture.Users @@ -61,4 +59,6 @@ await Fixture.Users .DisableUserAsync(user.LoginName, userCredentials: TestCredentials.Root) .ShouldNotThrowAsync(); } -} \ No newline at end of file + + public class CustomFixture() : KurrentPermanentFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/EventStore.Client.UserManagement.Tests/enabling_a_user.cs b/test/Kurrent.Client.Tests/UserManagement/EnableUserTests.cs similarity index 81% rename from test/EventStore.Client.UserManagement.Tests/enabling_a_user.cs rename to test/Kurrent.Client.Tests/UserManagement/EnableUserTests.cs index 79755e891..7392a0dbe 100644 --- a/test/EventStore.Client.UserManagement.Tests/enabling_a_user.cs +++ b/test/Kurrent.Client.Tests/UserManagement/EnableUserTests.cs @@ -1,11 +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)); - - InsecureClientTestFixture Fixture { get; } +namespace Kurrent.Client.Tests; +[Trait("Category", "Target:UserManagement")] +public class EnableUserTests(ITestOutputHelper output, EnableUserTests.CustomFixture fixture) + : KurrentPermanentTests(output, fixture) { [Fact] public async Task with_null_input_throws() { var ex = await Fixture.Users @@ -23,7 +20,7 @@ public async Task with_empty_input_throws() { ex.ParamName.ShouldBe("loginName"); } - + [Theory] [ClassData(typeof(InvalidCredentialsTestCases))] public async Task with_user_with_insufficient_credentials_throws(InvalidCredentialsTestCase testCase) { @@ -43,9 +40,9 @@ await Fixture.Users [Fact] public async Task that_was_disabled() { var user = await Fixture.CreateTestUser(); - + await Fixture.Users.DisableUserAsync(user.LoginName, userCredentials: TestCredentials.Root); - + await Fixture.Users .EnableUserAsync(user.LoginName, userCredentials: TestCredentials.Root) .ShouldNotThrowAsync(); @@ -54,9 +51,11 @@ await Fixture.Users [Fact] public async Task that_is_enabled() { var user = await Fixture.CreateTestUser(); - + await Fixture.Users .EnableUserAsync(user.LoginName, userCredentials: TestCredentials.Root) .ShouldNotThrowAsync(); } -} \ No newline at end of file + + public class CustomFixture() : KurrentPermanentFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/Kurrent.Client.Tests/UserManagement/GetCurrentUserTests.cs b/test/Kurrent.Client.Tests/UserManagement/GetCurrentUserTests.cs new file mode 100644 index 000000000..bb91c1a64 --- /dev/null +++ b/test/Kurrent.Client.Tests/UserManagement/GetCurrentUserTests.cs @@ -0,0 +1,12 @@ +using EventStore.Client; + +namespace Kurrent.Client.Tests; + +[Trait("Category", "Target:UserManagement")] +public class GetCurrentUserTests(ITestOutputHelper output, KurrentPermanentFixture fixture) : KurrentPermanentTests(output, fixture) { + [Fact] + public async Task returns_the_current_user() { + var user = await Fixture.Users.GetCurrentUserAsync(TestCredentials.Root); + user.LoginName.ShouldBe(TestCredentials.Root.Username); + } +} diff --git a/test/EventStore.Client.UserManagement.Tests/listing_users.cs b/test/Kurrent.Client.Tests/UserManagement/ListUserTests.cs similarity index 81% rename from test/EventStore.Client.UserManagement.Tests/listing_users.cs rename to test/Kurrent.Client.Tests/UserManagement/ListUserTests.cs index 4760e7898..8cf4d1ad1 100644 --- a/test/EventStore.Client.UserManagement.Tests/listing_users.cs +++ b/test/Kurrent.Client.Tests/UserManagement/ListUserTests.cs @@ -1,11 +1,9 @@ -namespace EventStore.Client.Tests; +using EventStore.Client; -public class listing_users : IClassFixture { - public listing_users(ITestOutputHelper output, EventStoreFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); +namespace Kurrent.Client.Tests; - EventStoreFixture Fixture { get; } - +[Trait("Category", "Target:UserManagement")] +public class ListUserTests(ITestOutputHelper output, KurrentPermanentFixture fixture) : KurrentPermanentTests(output, fixture) { [Fact] public async Task returns_all_created_users() { var seed = await Fixture.CreateTestUsers(); @@ -39,4 +37,4 @@ public async Task returns_all_system_users() { expected.ShouldBeSubsetOf(actual); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.UserManagement.Tests/resetting_user_password.cs b/test/Kurrent.Client.Tests/UserManagement/ResettingUserPasswordTests.cs similarity index 86% rename from test/EventStore.Client.UserManagement.Tests/resetting_user_password.cs rename to test/Kurrent.Client.Tests/UserManagement/ResettingUserPasswordTests.cs index 549e7119b..39b0bf718 100644 --- a/test/EventStore.Client.UserManagement.Tests/resetting_user_password.cs +++ b/test/Kurrent.Client.Tests/UserManagement/ResettingUserPasswordTests.cs @@ -1,16 +1,15 @@ -namespace EventStore.Client.Tests; +using EventStore.Client; -public class resetting_user_password : IClassFixture { - public resetting_user_password(ITestOutputHelper output, InsecureClientTestFixture fixture) => - Fixture = fixture.With(x => x.CaptureTestRun(output)); +namespace Kurrent.Client.Tests; - InsecureClientTestFixture Fixture { get; } - +[Trait("Category", "Target:UserManagement")] +public class ResettingUserPasswordTests(ITestOutputHelper output, ResettingUserPasswordTests.CustomFixture fixture) + : KurrentPermanentTests(output, fixture) { public static IEnumerable NullInputCases() { yield return Fakers.Users.Generate().WithResult(x => new object?[] { null, x.Password, "loginName" }); yield return Fakers.Users.Generate().WithResult(x => new object?[] { x.LoginName, null, "newPassword" }); } - + [Theory] [MemberData(nameof(NullInputCases))] public async Task with_null_input_throws(string loginName, string newPassword, string paramName) { @@ -20,7 +19,7 @@ public async Task with_null_input_throws(string loginName, string newPassword, s ex.ParamName.ShouldBe(paramName); } - + public static IEnumerable EmptyInputCases() { yield return Fakers.Users.Generate().WithResult(x => new object?[] { string.Empty, x.Password, "loginName" }); yield return Fakers.Users.Generate().WithResult(x => new object?[] { x.LoginName, string.Empty, "newPassword" }); @@ -77,4 +76,6 @@ await Fixture.Users .ResetPasswordAsync(user.LoginName, "new-password", userCredentials: user.Credentials) .ShouldThrowAsync(); } -} \ No newline at end of file + + public class CustomFixture() : KurrentPermanentFixture(x => x.WithoutDefaultCredentials()); +} diff --git a/test/EventStore.Client.UserManagement.Tests/UserCredentialsTests.cs b/test/Kurrent.Client.Tests/UserManagement/UserCredentialsTests.cs similarity index 92% rename from test/EventStore.Client.UserManagement.Tests/UserCredentialsTests.cs rename to test/Kurrent.Client.Tests/UserManagement/UserCredentialsTests.cs index c8eb0a570..e4ffbe456 100644 --- a/test/EventStore.Client.UserManagement.Tests/UserCredentialsTests.cs +++ b/test/Kurrent.Client.Tests/UserManagement/UserCredentialsTests.cs @@ -1,9 +1,11 @@ using System.Net.Http.Headers; using System.Text; +using EventStore.Client; using static System.Convert; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; +[Trait("Category", "Target:UserManagement")] public class UserCredentialsTests { const string JwtToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9." + "eyJzdWIiOiI5OSIsIm5hbWUiOiJKb2huIFdpY2siLCJpYXQiOjE1MTYyMzkwMjJ9." @@ -39,4 +41,4 @@ public void from_bearer_token() { credentials.Password.ShouldBeNull(); credentials.ToString().ShouldBe($"Bearer {JwtToken}"); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/UuidTests.cs b/test/Kurrent.Client.Tests/UuidTests.cs similarity index 90% rename from test/EventStore.Client.Tests/UuidTests.cs rename to test/Kurrent.Client.Tests/UuidTests.cs index 35d833096..96550b734 100644 --- a/test/EventStore.Client.Tests/UuidTests.cs +++ b/test/Kurrent.Client.Tests/UuidTests.cs @@ -1,11 +1,13 @@ using AutoFixture; +using EventStore.Client; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; +[Trait("Category", "Target:Misc")] public class UuidTests : ValueObjectTests { public UuidTests() : base(new ScenarioFixture()) { } - [Fact] + [RetryFact] public void ToGuidReturnsExpectedResult() { var guid = Guid.NewGuid(); var sut = Uuid.FromGuid(guid); @@ -13,21 +15,21 @@ public void ToGuidReturnsExpectedResult() { Assert.Equal(sut.ToGuid(), guid); } - [Fact] + [RetryFact] public void ToStringProducesExpectedResult() { var sut = Uuid.NewUuid(); Assert.Equal(sut.ToGuid().ToString(), sut.ToString()); } - [Fact] + [RetryFact] public void ToFormattedStringProducesExpectedResult() { var sut = Uuid.NewUuid(); Assert.Equal(sut.ToGuid().ToString("n"), sut.ToString("n")); } - [Fact] + [RetryFact] public void ToDtoReturnsExpectedResult() { var msb = GetRandomInt64(); var lsb = GetRandomInt64(); @@ -41,7 +43,7 @@ public void ToDtoReturnsExpectedResult() { Assert.Equal(msb, result.Structured.MostSignificantBits); } - [Fact] + [RetryFact] public void ParseReturnsExpectedResult() { var guid = Guid.NewGuid(); @@ -50,7 +52,7 @@ public void ParseReturnsExpectedResult() { Assert.Equal(Uuid.FromGuid(guid), sut); } - [Fact] + [RetryFact] public void FromInt64ReturnsExpectedResult() { var guid = Guid.Parse("65678f9b-d139-4786-8305-b9166922b378"); var sut = Uuid.FromInt64(7306966819824813958L, -9005588373953137800L); @@ -70,4 +72,4 @@ static long GetRandomInt64() { class ScenarioFixture : Fixture { public ScenarioFixture() => Customize(composer => composer.FromFactory(Uuid.FromGuid)); } -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/ValueObjectTests.cs b/test/Kurrent.Client.Tests/ValueObjectTests.cs similarity index 79% rename from test/EventStore.Client.Tests/ValueObjectTests.cs rename to test/Kurrent.Client.Tests/ValueObjectTests.cs index cce2526f7..08d09606d 100644 --- a/test/EventStore.Client.Tests/ValueObjectTests.cs +++ b/test/Kurrent.Client.Tests/ValueObjectTests.cs @@ -1,15 +1,16 @@ using AutoFixture; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; +[Trait("Category", "Target:Misc")] public abstract class ValueObjectTests { protected readonly Fixture _fixture; protected ValueObjectTests(Fixture fixture) => _fixture = fixture; - [Fact] + [RetryFact] public void ValueObjectIsWellBehaved() => _fixture.Create().Verify(typeof(T)); - [Fact] + [RetryFact] public void ValueObjectIsEquatable() => Assert.IsAssignableFrom>(_fixture.Create()); -} \ No newline at end of file +} diff --git a/test/EventStore.Client.Tests/X509CertificatesTests.cs b/test/Kurrent.Client.Tests/X509CertificatesTests.cs similarity index 72% rename from test/EventStore.Client.Tests/X509CertificatesTests.cs rename to test/Kurrent.Client.Tests/X509CertificatesTests.cs index dd32aabb0..04dce9b7a 100644 --- a/test/EventStore.Client.Tests/X509CertificatesTests.cs +++ b/test/Kurrent.Client.Tests/X509CertificatesTests.cs @@ -1,32 +1,42 @@ using System.Security.Cryptography.X509Certificates; +using EventStore.Client; -namespace EventStore.Client.Tests; +namespace Kurrent.Client.Tests; +[Trait("Category", "Target:Misc")] public class X509CertificatesTests { - [Fact] + [RetryFact] public void create_from_pem_file() { const string certPemFilePath = "certs/ca/ca.crt"; const string keyPemFilePath = "certs/ca/ca.key"; var rsa = X509Certificates.CreateFromPemFile(certPemFilePath, keyPemFilePath); +#if NET9_0_OR_GREATER + var cert = X509CertificateLoader.LoadCertificateFromFile(certPemFilePath); +#else var cert = new X509Certificate2(certPemFilePath); +#endif rsa.Issuer.ShouldBe(cert.Issuer); rsa.SerialNumber.ShouldBe(cert.SerialNumber); } - [Fact] + [RetryFact] public void create_from_pem_file_() { const string certPemFilePath = "certs/user-admin/user-admin.crt"; const string keyPemFilePath = "certs/user-admin/user-admin.key"; var rsa = X509Certificates.CreateFromPemFile(certPemFilePath, keyPemFilePath); +#if NET9_0_OR_GREATER + var cert = X509CertificateLoader.LoadCertificateFromFile(certPemFilePath); +#else var cert = new X509Certificate2(certPemFilePath); +#endif rsa.Issuer.ShouldBe(cert.Issuer); rsa.Subject.ShouldBe(cert.Subject); rsa.SerialNumber.ShouldBe(cert.SerialNumber); } -} \ No newline at end of file +}