diff --git a/.azure/pipelines/azure-pipelines-compliance.yml b/.azure/pipelines/azure-pipelines-compliance.yml index ef0f8eb21f..b06c37a6c9 100644 --- a/.azure/pipelines/azure-pipelines-compliance.yml +++ b/.azure/pipelines/azure-pipelines-compliance.yml @@ -21,6 +21,10 @@ jobs: displayName: 'Use .NET Core sdk 8.0.x' inputs: version: 8.0.x + - task: UseDotNet@2 + displayName: 'Use .NET Core sdk 9.0.x' + inputs: + version: 9.0.x - task: NuGetToolInstaller@1 displayName: Nuget Tool Installer inputs: diff --git a/.azure/pipelines/azure-pipelines-external-release.yml b/.azure/pipelines/azure-pipelines-external-release.yml index a7b71dc544..6cd000b729 100644 --- a/.azure/pipelines/azure-pipelines-external-release.yml +++ b/.azure/pipelines/azure-pipelines-external-release.yml @@ -41,6 +41,10 @@ jobs: displayName: Use .NET Core sdk 8.0.x inputs: version: 8.0.x + - task: UseDotNet@2 + displayName: Use .NET Core sdk 9.0.x + inputs: + version: 9.0.x - task: DotNetCoreCLI@2 displayName: dotnet build @@ -156,10 +160,10 @@ jobs: workingDirectory: .azure/pipelines - task: CopyFiles@2 - displayName: 'Copy Zipped Files to Artifacts dir: $(Build.artifactstagingdirectory)' + displayName: 'Copy Zipped Files (both net80 and net90 in zipped file) to Artifacts dir: $(Build.artifactstagingdirectory)' inputs: Contents: '**' - SourceFolder: '$(Build.SourcesDirectory)/main/GarnetServer/bin/Release/net8.0/publish/output' + SourceFolder: '$(Build.SourcesDirectory)/main/GarnetServer/bin/Release/publish/output' TargetFolder: $(build.artifactstagingdirectory) - task: PublishBuildArtifacts@1 diff --git a/.azure/pipelines/azure-pipelines-tsavorite.yml b/.azure/pipelines/azure-pipelines-tsavorite.yml index 2a238fd6bb..5a61cf4e84 100644 --- a/.azure/pipelines/azure-pipelines-tsavorite.yml +++ b/.azure/pipelines/azure-pipelines-tsavorite.yml @@ -31,6 +31,12 @@ jobs: packageType: 'sdk' version: '8.0.x' + - task: UseDotNet@2 + displayName: Use .NET 9.0 + inputs: + packageType: 'sdk' + version: '9.0.x' + - task: NodeTool@0 displayName: Node Tool inputs: @@ -126,6 +132,12 @@ jobs: packageType: 'sdk' version: '8.0.x' + - task: UseDotNet@2 + displayName: Use .NET 9.0 + inputs: + packageType: 'sdk' + version: '9.0.x' + - bash: | sudo npm install -g azurite sudo mkdir azurite diff --git a/.azure/pipelines/azure-pipelines.yml b/.azure/pipelines/azure-pipelines.yml index f0b47badd0..c4ec25e32d 100644 --- a/.azure/pipelines/azure-pipelines.yml +++ b/.azure/pipelines/azure-pipelines.yml @@ -31,6 +31,12 @@ jobs: packageType: 'sdk' version: '8.0.x' + - task: UseDotNet@2 + displayName: Use .NET 9.0 + inputs: + packageType: 'sdk' + version: '9.0.x' + - task: NodeTool@0 displayName: Node Tool inputs: @@ -118,6 +124,11 @@ jobs: inputs: packageType: 'sdk' version: '8.0.x' + - task: UseDotNet@2 + displayName: Use .NET 9.0 + inputs: + packageType: 'sdk' + version: '9.0.x' - bash: | sudo npm install -g azurite diff --git a/.azure/pipelines/createbinaries.ps1 b/.azure/pipelines/createbinaries.ps1 index 2b8e4e9aca..8abfd35c20 100644 --- a/.azure/pipelines/createbinaries.ps1 +++ b/.azure/pipelines/createbinaries.ps1 @@ -31,13 +31,13 @@ param ( ################## CleanUpFiles ##################### # -# Publishes the files and clean it up so only the necessary files will be ready to be zipped +# After build is published, this cleans it up so only the necessary files will be ready to be zipped # ###################################################### function CleanUpFiles { - param ($publishFolder, $platform) + param ($publishFolder, $platform, $framework) - $publishPath = "$basePath/main/GarnetServer/bin/Release/net8.0/publish/$publishFolder" + $publishPath = "$basePath/main/GarnetServer/bin/Release/$framework/publish/$publishFolder" $garnetServerEXE = "$publishPath/GarnetServer.exe" $excludeGarnetServerPDB = 'GarnetServer.pdb' @@ -85,46 +85,95 @@ Set-Location $basePath/main/GarnetServer if ($mode -eq 0 -or $mode -eq 1) { Write-Host "** Publish ... **" dotnet publish GarnetServer.csproj -p:PublishProfile=linux-arm64-based -f:net8.0 - dotnet publish GarnetServer.csproj -p:PublishProfile=linux-x64-based -f:net8.0 - dotnet publish GarnetServer.csproj -p:PublishProfile=osx-arm64-based -f:net8.0 - dotnet publish GarnetServer.csproj -p:PublishProfile=osx-x64-based -f:net8.0 - dotnet publish GarnetServer.csproj -p:PublishProfile=portable -f:net8.0 - dotnet publish GarnetServer.csproj -p:PublishProfile=win-arm64-based-readytorun -f:net8.0 - dotnet publish GarnetServer.csproj -p:PublishProfile=win-x64-based-readytorun -f:net8.0 + dotnet publish GarnetServer.csproj -p:PublishProfile=linux-x64-based -f:net8.0 + dotnet publish GarnetServer.csproj -p:PublishProfile=osx-arm64-based -f:net8.0 + dotnet publish GarnetServer.csproj -p:PublishProfile=osx-x64-based -f:net8.0 + dotnet publish GarnetServer.csproj -p:PublishProfile=portable -f:net8.0 + dotnet publish GarnetServer.csproj -p:PublishProfile=win-arm64-based-readytorun -f:net8.0 + dotnet publish GarnetServer.csproj -p:PublishProfile=win-x64-based-readytorun -f:net8.0 + + dotnet publish GarnetServer.csproj -p:PublishProfile=linux-arm64-based -f:net9.0 + dotnet publish GarnetServer.csproj -p:PublishProfile=linux-x64-based -f:net9.0 + dotnet publish GarnetServer.csproj -p:PublishProfile=osx-arm64-based -f:net9.0 + dotnet publish GarnetServer.csproj -p:PublishProfile=osx-x64-based -f:net9.0 + dotnet publish GarnetServer.csproj -p:PublishProfile=portable -f:net9.0 + dotnet publish GarnetServer.csproj -p:PublishProfile=win-arm64-based-readytorun -f:net9.0 + dotnet publish GarnetServer.csproj -p:PublishProfile=win-x64-based-readytorun -f:net9.0 # Clean up all the extra files - CleanUpFiles "linux-arm64" "linux-x64" - CleanUpFiles "linux-x64" "linux-x64" - CleanUpFiles "osx-arm64" "linux-x64" - CleanUpFiles "osx-x64" "linux-x64" - #CleanUpFiles "portable" "win-x64" # don't clean up all files for portable ... leave as is - CleanUpFiles "win-x64" "win-x64" - CleanUpFiles "win-arm64" "win-x64" + CleanUpFiles "linux-arm64" "linux-x64" "net8.0" + CleanUpFiles "linux-x64" "linux-x64" "net8.0" + CleanUpFiles "osx-arm64" "linux-x64" "net8.0" + CleanUpFiles "osx-x64" "linux-x64" "net8.0" + #CleanUpFiles "portable" "win-x64" "net8.0" # don't clean up all files for portable ... leave as is + CleanUpFiles "win-x64" "win-x64" "net8.0" + CleanUpFiles "win-arm64" "win-x64" "net8.0" + + CleanUpFiles "linux-arm64" "linux-x64" "net9.0" + CleanUpFiles "linux-x64" "linux-x64" "net9.0" + CleanUpFiles "osx-arm64" "linux-x64" "net9.0" + CleanUpFiles "osx-x64" "linux-x64" "net9.0" + #CleanUpFiles "portable" "win-x64" "net9.0" # don't clean up all files for portable ... leave as is + CleanUpFiles "win-x64" "win-x64" "net9.0" + CleanUpFiles "win-arm64" "win-x64" "net9.0" } if ($mode -eq 0 -or $mode -eq 2) { - # Make sure the publish folder exists as basic check files are actually published before trying to zip - $publishedFilesFolder = "$basePath/main/GarnetServer/bin/Release/net8.0/publish" - if (!(Test-Path $publishedFilesFolder)) { - Write-Error "$publishedFilesFolder does not exist. Run .\CreateBinaries 1 to publish the binaries first." + # Make sure at publish folders are there as basic check files are actually published before trying to zip + $publishedFilesFolderNet8 = "$basePath/main/GarnetServer/bin/Release/net8.0/publish" + $publishedFilesFolderNet9 = "$basePath/main/GarnetServer/bin/Release/net9.0/publish" + + if (!(Test-Path $publishedFilesFolderNet8) -or !(Test-Path $publishedFilesFolderNet9)) { + Write-Error "$publishedFilesFolderNet8 or $publishedFilesFolderNet9 does not exist. Run .\CreateBinaries 1 to publish the binaries first." + Set-Location $lastPwd exit } - - # Create the directories - if (!(Test-Path $basePath/main/GarnetServer/bin/Release/net8.0/publish/output)) { - mkdir $basePath/main/GarnetServer/bin/Release/net8.0/publish/output + + # Create the directories - both net80 and net90 will be in the same zip file. + $directories = @("linux-arm64", "linux-x64", "osx-arm64", "osx-x64", "portable", "win-arm64", "win-x64") + $sourceFramework = @("net8.0", "net9.0") + $baseSourcePath = "$basePath/main/GarnetServer/bin/Release" + $destinationPath = "$basePath/main/GarnetServer/bin/Release/publish" + $zipfiledestinationPath = "$destinationPath/output" + + # Make the destination path where the compressed files will be + if (!(Test-Path $destinationPath)) { + mkdir $destinationPath + } + if (!(Test-Path $zipfiledestinationPath)) { + mkdir $zipfiledestinationPath + } + Set-Location $zipfiledestinationPath + + foreach ($dir in $directories) { + if (!(Test-Path (Join-Path -Path $destinationPath -ChildPath $dir))) { + mkdir (Join-Path -Path $destinationPath -ChildPath $dir) + } + } + + foreach ($dir in $directories) { + foreach ($version in $sourceFramework) { + $sourcePath = Join-Path -Path $baseSourcePath -ChildPath "$version\publish\$dir" + $destDirPath = Join-Path -Path $destinationPath -ChildPath $dir + $destVersionPath = Join-Path -Path $destDirPath -ChildPath $version + + if (!(Test-Path $destVersionPath)) { + mkdir $destVersionPath + } + + Copy-Item -Path "$sourcePath\*" -Destination $destVersionPath -Recurse -Force + } } - Set-Location $basePath/main/GarnetServer/bin/Release/net8.0/publish/output - # Compress the files + # Compress the files - both net80 and net90 in the same zip file Write-Host "** Compressing the files ... **" - 7z a -mmt20 -mx5 -scsWIN win-x64-based-readytorun.zip ../win-x64/* - 7z a -mmt20 -mx5 -scsWIN win-arm64-based-readytorun.zip ../win-arm64/* - 7z a -scsUTF-8 linux-x64-based.tar ../linux-x64/* - 7z a -scsUTF-8 linux-arm64-based.tar ../linux-arm64/* - 7z a -scsUTF-8 osx-x64-based.tar ../osx-x64/* - 7z a -scsUTF-8 osx-arm64-based.tar ../osx-arm64/* + 7z a -mmt20 -mx5 -scsWIN -r win-x64-based-readytorun.zip ../win-x64/* + 7z a -mmt20 -mx5 -scsWIN -r win-arm64-based-readytorun.zip ../win-arm64/* + 7z a -scsUTF-8 -r linux-x64-based.tar ../linux-x64/* + 7z a -scsUTF-8 -r linux-arm64-based.tar ../linux-arm64/* + 7z a -scsUTF-8 -r osx-x64-based.tar ../osx-x64/* + 7z a -scsUTF-8 -r osx-arm64-based.tar ../osx-arm64/* 7z a -mmt20 -mx5 -sdel linux-x64-based.tar.xz linux-x64-based.tar 7z a -mmt20 -mx5 -sdel linux-arm64-based.tar.xz linux-arm64-based.tar 7z a -mmt20 -mx5 -sdel osx-x64-based.tar.xz osx-x64-based.tar diff --git a/.editorconfig b/.editorconfig index 9b106068af..7446262aa2 100644 --- a/.editorconfig +++ b/.editorconfig @@ -69,6 +69,7 @@ file_header_template = Copyright (c) Microsoft Corporation.\nLicensed under the dotnet_sort_system_directives_first = true dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion dotnet_style_predefined_type_for_member_access = true:suggestion +dotnet_style_prefer_collection_expression = true:suggestion # avoid this. unless absolutely necessary dotnet_style_qualification_for_field = false:suggestion diff --git a/.github/workflows/ci-bdnbenchmark.yml b/.github/workflows/ci-bdnbenchmark.yml index a0b6921562..77fb2588d6 100644 --- a/.github/workflows/ci-bdnbenchmark.yml +++ b/.github/workflows/ci-bdnbenchmark.yml @@ -40,7 +40,7 @@ jobs: fail-fast: false matrix: os: [ ubuntu-latest, windows-latest ] - framework: [ 'net8.0' ] + framework: [ 'net8.0', 'net9.0' ] configuration: [ 'Release' ] test: [ 'Operations.BasicOperations', 'Operations.ObjectOperations', 'Operations.HashObjectOperations', 'Operations.SortedSetOperations', 'Cluster.ClusterMigrate', 'Cluster.ClusterOperations', 'Lua.LuaScripts', 'Lua.LuaScriptCacheOperations','Lua.LuaRunnerOperations','Operations.CustomOperations', 'Operations.RawStringOperations', 'Operations.ScriptOperations', 'Operations.ModuleOperations', 'Operations.PubSubOperations', 'Network.BasicOperations', 'Network.RawStringOperations' ] steps: @@ -49,7 +49,9 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: 8.0.x + dotnet-version: | + 8.0.x + 9.0.x - name: Install dependencies run: dotnet restore diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 536c0751f5..a95fa93f5d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,10 +49,14 @@ jobs: steps: - name: Check out code uses: actions/checkout@v4 - - name: Setup .NET + - name: Setup .NET 8.0 uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x + - name: Setup .NET 9.0 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 9.0.x - name: Install dependencies run: dotnet restore Garnet.sln - name: Check style format @@ -66,10 +70,14 @@ jobs: steps: - name: Check out code uses: actions/checkout@v4 - - name: Setup .NET + - name: Setup .NET 8.0 uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x + - name: Setup .NET 9.0 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 9.0.x - name: Install dependencies run: dotnet restore libs/storage/Tsavorite/cs/Tsavorite.sln - name: Check style format @@ -84,19 +92,27 @@ jobs: fail-fast: false matrix: os: [ ubuntu-latest, windows-latest ] - framework: [ 'net8.0' ] + framework: [ 'net8.0' , 'net9.0'] configuration: [ 'Debug', 'Release' ] test: [ 'Garnet.test', 'Garnet.test.cluster' ] if: needs.changes.outputs.garnet == 'true' steps: - name: Check out code uses: actions/checkout@v4 - - name: Setup .NET + - name: Setup .NET 8.0 uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x + - name: Setup .NET 9.0 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 9.0.x - name: Install dependencies run: dotnet restore + - name: Set environment variables + if: ${{ matrix.framework == 'net9.0' }} + shell: bash + run: echo "DOTNET_LegacyExceptionHandling=1" >> $GITHUB_ENV - name: Build Garnet run: dotnet build --configuration ${{ matrix.configuration }} - name: Run tests ${{ matrix.test }} @@ -118,7 +134,7 @@ jobs: fail-fast: false matrix: os: [ ubuntu-latest, windows-latest ] - framework: [ 'net8.0' ] + framework: [ 'net8.0', 'net9.0' ] configuration: [ 'Debug', 'Release' ] if: needs.changes.outputs.tsavorite == 'true' steps: @@ -134,10 +150,14 @@ jobs: - name: Set environment variable for Windows run: echo ("RunAzureTests=yes") >> $env:GITHUB_ENV if: ${{ matrix.os == 'windows-latest' }} - - name: Setup .NET + - name: Setup .NET 8.0 uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x + - name: Setup .NET 9.0 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 9.0.x - name: Setup Node.js for Azurite uses: actions/setup-node@v4 with: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000000..67d37846db --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,105 @@ +# +# Auto generated YML file to run CodeQL except for build steps at the bottom which needed to be manual since using net90 +# +name: "CodeQL Advanced" + +on: + workflow_dispatch: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + schedule: + - cron: '38 11 * * 1' + +jobs: + analyze: + name: Analyze (${{ matrix.language }}) + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners (GitHub.com only) + # Consider using larger runners or machines with greater resources for possible analysis time improvements. + runs-on: ubuntu-latest + permissions: + # required for all workflows + security-events: write + + # required to fetch internal or private CodeQL packs + packages: read + + # only required for workflows in private repositories + actions: read + contents: read + + strategy: + fail-fast: false + matrix: + include: + - language: csharp + build-mode: manual + - language: javascript-typescript + build-mode: none + # CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' + # Use `c-cpp` to analyze code written in C, C++ or both + # Use 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, + # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. + # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how + # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages + steps: + - name: Check if manual build mode + if: ${{ matrix.build-mode == 'manual' }} + run: echo "Manual build mode detected" + + - name: Checkout repository + uses: actions/checkout@v4 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + # If the analyze step fails for one of the languages you are analyzing with + # "We were unable to automatically build your code", modify the matrix above + # to set the build mode to "manual" for that language. Then modify this step + # to build your code. + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + - name: Setup .NET 8.0 + if: ${{ matrix.build-mode == 'manual' }} + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.0.x + + - name: Setup .NET 9.0 + if: ${{ matrix.build-mode == 'manual' }} + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 9.0.x + + - name: Install dependencies + if: ${{ matrix.build-mode == 'manual' }} + run: dotnet restore + + - name: Build Garnet net80 + if: ${{ matrix.build-mode == 'manual' }} + run: dotnet build -f net8.0 + + - name: Build Garnet net90 + if: ${{ matrix.build-mode == 'manual' }} + run: dotnet build -f net9.0 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 25adcdfe28..eef57fe8fd 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -19,16 +19,20 @@ jobs: fail-fast: false matrix: os: [ ubuntu-22.04, ubuntu-20.04, windows-2022, windows-2019 ] - framework: [ 'net8.0' ] + framework: [ 'net8.0', 'net9.0' ] configuration: [ 'Debug', 'Release' ] test: [ 'Garnet.test', 'Garnet.test.cluster' ] steps: - name: Check out code uses: actions/checkout@v4 - - name: Setup .NET + - name: Setup .NET 8.0 uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x + - name: Setup .NET 9.0 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 9.0.x - name: Install dependencies run: dotnet restore - name: Check style format @@ -53,7 +57,7 @@ jobs: fail-fast: false matrix: os: [ ubuntu-22.04, ubuntu-20.04, windows-2022, windows-2019 ] - framework: [ 'net8.0' ] + framework: [ 'net8.0', 'net9.0' ] configuration: [ 'Debug', 'Release' ] steps: - name: Check out code @@ -64,10 +68,14 @@ jobs: - name: Set environment variable for Windows run: echo ("RunAzureTests=yes") >> $env:GITHUB_ENV if: ${{ matrix.os == 'windows-latest' }} - - name: Setup .NET + - name: Setup .NET 8.0 uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x + - name: Setup .NET 9.0 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 9.0.x - name: Setup Node.js for Azurite uses: actions/setup-node@v4 with: diff --git a/Directory.Build.props b/Directory.Build.props index 3b5f21c18c..470cd3f559 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ - net8.0 + net8.0;net9.0 diff --git a/benchmark/BDN.benchmark/Parsing/IntegerToResp.cs b/benchmark/BDN.benchmark/Parsing/IntegerToResp.cs index 380fedb2f3..14e53da50f 100644 --- a/benchmark/BDN.benchmark/Parsing/IntegerToResp.cs +++ b/benchmark/BDN.benchmark/Parsing/IntegerToResp.cs @@ -92,14 +92,14 @@ public void WriteInt32BulkString_AllAsciiLengths() .. UnsignedInt32MultiplesOfTen.Select(n => n * -1), .. UnsignedInt32MultiplesOfTen ]; - public static int[] UnsignedInt32MultiplesOfTen => Enumerable.Range(0, 10).Select(n => (int)Math.Pow(10, n)).ToArray(); + public static int[] UnsignedInt32MultiplesOfTen => [.. Enumerable.Range(0, 10).Select(n => (int)Math.Pow(10, n))]; // All multiples of 10 from 10^-19 to 10^19 public static long[] SignedInt64MultiplesOfTen => [ .. UnsignedInt64MultiplesOfTen.Select(n => n * -1), .. UnsignedInt64MultiplesOfTen ]; - public static long[] UnsignedInt64MultiplesOfTen => Enumerable.Range(0, 19).Select(n => (long)Math.Pow(10, n)).ToArray(); + public static long[] UnsignedInt64MultiplesOfTen => [.. Enumerable.Range(0, 19).Select(n => (long)Math.Pow(10, n))]; public static int[] SignedInt32Values => [int.MinValue, -1, 0, int.MaxValue]; public static long[] SignedInt64Values => [long.MinValue, -1, 0, long.MaxValue]; diff --git a/benchmark/BDN.benchmark/Program.cs b/benchmark/BDN.benchmark/Program.cs index c8e6a96eac..f94c2d380b 100644 --- a/benchmark/BDN.benchmark/Program.cs +++ b/benchmark/BDN.benchmark/Program.cs @@ -21,6 +21,7 @@ public class BaseConfig : ManualConfig { public Job Net8BaseJob { get; } + public Job Net9BaseJob { get; } public BaseConfig() { @@ -33,9 +34,12 @@ public BaseConfig() Net8BaseJob = baseJob.WithRuntime(CoreRuntime.Core80) .WithEnvironmentVariables(new EnvironmentVariable("DOTNET_TieredPGO", "0")); + Net9BaseJob = baseJob.WithRuntime(CoreRuntime.Core90) + .WithEnvironmentVariables(new EnvironmentVariable("DOTNET_TieredPGO", "0")); AddJob( - Net8BaseJob.WithId(".NET 8") + Net8BaseJob.WithId(".NET 8"), + Net9BaseJob.WithId(".NET 9") ); } } \ No newline at end of file diff --git a/benchmark/Resp.benchmark/BenchUtils.cs b/benchmark/Resp.benchmark/BenchUtils.cs index 00e462e708..e95a210bf0 100644 --- a/benchmark/Resp.benchmark/BenchUtils.cs +++ b/benchmark/Resp.benchmark/BenchUtils.cs @@ -4,10 +4,10 @@ using System.Collections.Generic; using System.Diagnostics; using System.Net.Security; -using System.Security.Cryptography.X509Certificates; using System.Text; using Garnet.common; using Garnet.server; +using Garnet.server.TLS; using StackExchange.Redis; namespace Resp.benchmark @@ -62,7 +62,7 @@ public static SslClientAuthenticationOptions GetTlsOptions(string tlsHost, strin { return new SslClientAuthenticationOptions { - ClientCertificates = [new X509Certificate2(certFile, certPassword)], + ClientCertificates = [CertificateUtils.GetMachineCertificateByFile(certFile, certPassword)], TargetHost = tlsHost, AllowRenegotiation = false, RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true, diff --git a/benchmark/Resp.benchmark/Program.cs b/benchmark/Resp.benchmark/Program.cs index 3dd2ce5d3b..6da133408b 100644 --- a/benchmark/Resp.benchmark/Program.cs +++ b/benchmark/Resp.benchmark/Program.cs @@ -216,7 +216,7 @@ static void WaitForServer(Options opts) static void RunBasicCommandsBenchmark(Options opts) { - int[] threadBench = opts.NumThreads.ToArray(); + int[] threadBench = [.. opts.NumThreads]; int keyLen = opts.KeyLength; int valueLen = opts.ValueLength; @@ -276,7 +276,7 @@ static void RunBasicCommandsBenchmark(Options opts) static void RunHLLBenchmark(Options opts) { var bench = new RespPerfBench(opts, 0, redis); - int[] threadBench = opts.NumThreads.ToArray(); + int[] threadBench = [.. opts.NumThreads]; int loadThreads = 8; int loadBatchSize = opts.DbSize / loadThreads; diff --git a/benchmark/Resp.benchmark/RespPerfBench.cs b/benchmark/Resp.benchmark/RespPerfBench.cs index 261bdc93b7..e691091775 100644 --- a/benchmark/Resp.benchmark/RespPerfBench.cs +++ b/benchmark/Resp.benchmark/RespPerfBench.cs @@ -502,7 +502,7 @@ private void MGetThreadRunner(int threadid, int NumOps, int BatchSize = 1 << 12) } if (idx > 0) { - var result = db.StringGet(getBatch.Take(idx).ToArray()); + var result = db.StringGet([.. getBatch.Take(idx)]); if (checkResults) { for (int k = 0; k < idx; k++) @@ -544,7 +544,7 @@ private void LoadDatabaseStringSet(int BatchSize = 1 << 12) { for (int b = 0; b < DbSize; b += BatchSize) { - db.StringSet(database.Skip(b).Take(BatchSize).ToArray()); + db.StringSet([.. database.Skip(b).Take(BatchSize)]); if (b > 0 && b % 1000000 == 0) Console.WriteLine(b); } diff --git a/hosting/Windows/Garnet.worker/Garnet.worker.csproj b/hosting/Windows/Garnet.worker/Garnet.worker.csproj index b8fad9da9f..92b32e2675 100644 --- a/hosting/Windows/Garnet.worker/Garnet.worker.csproj +++ b/hosting/Windows/Garnet.worker/Garnet.worker.csproj @@ -1,7 +1,7 @@  - net8.0 + net8.0;net9.0 diff --git a/libs/cluster/Session/RespClusterReplicationCommands.cs b/libs/cluster/Session/RespClusterReplicationCommands.cs index fdb1aebf54..f9001b0ad8 100644 --- a/libs/cluster/Session/RespClusterReplicationCommands.cs +++ b/libs/cluster/Session/RespClusterReplicationCommands.cs @@ -404,7 +404,7 @@ private bool NetworkClusterAttachSync(out bool invalidParameters) else replicationOffset = clusterProvider.replicationManager.ReplicaRecoverDiskless(syncMetadata); - if (errorMessage != default) + if (!errorMessage.IsEmpty) { while (!RespWriteUtils.TryWriteError(errorMessage, ref dcurr, dend)) SendAndReset(); diff --git a/libs/common/EnumUtils.cs b/libs/common/EnumUtils.cs index 7ac88a6557..03b1209d80 100644 --- a/libs/common/EnumUtils.cs +++ b/libs/common/EnumUtils.cs @@ -42,7 +42,7 @@ public static IDictionary GetEnumNameToDescription() where T public static string[] GetEnumDescriptions(T value) where T : Enum { var nameToDesc = GetEnumNameToDescription(); - return value.ToString().Split(',').Select(f => nameToDesc.ContainsKey(f.Trim()) ? nameToDesc[f.Trim()] : f).ToArray(); + return [.. value.ToString().Split(',').Select(f => nameToDesc.ContainsKey(f.Trim()) ? nameToDesc[f.Trim()] : f)]; } /// diff --git a/libs/common/FailoverOption.cs b/libs/common/FailoverOption.cs index d4421d63e8..790f778876 100644 --- a/libs/common/FailoverOption.cs +++ b/libs/common/FailoverOption.cs @@ -50,8 +50,7 @@ public enum FailoverOption : byte /// public static class FailoverUtils { - static readonly byte[][] infoSections = Enum.GetValues() - .Select(x => Encoding.ASCII.GetBytes($"${x.ToString().Length}\r\n{x}\r\n")).ToArray(); + static readonly byte[][] infoSections = [.. Enum.GetValues().Select(x => Encoding.ASCII.GetBytes($"${x.ToString().Length}\r\n{x}\r\n"))]; /// /// Return resp formatted failover option diff --git a/libs/common/FileUtils.cs b/libs/common/FileUtils.cs index fed2418547..3562d0b80f 100644 --- a/libs/common/FileUtils.cs +++ b/libs/common/FileUtils.cs @@ -159,13 +159,15 @@ public static bool TryLoadAssemblies(IEnumerable assemblyPaths, out IEnu Assembly assembly; try { - assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(path); + // NET9 seems to hold the assembly locked if it's opened from the path directly, causing tests to fail. + using var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read); + assembly = AssemblyLoadContext.Default.LoadFromStream(fileStream); } catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException || ex is NotSupportedException || ex is BadImageFormatException || ex is SecurityException) { - if (ex is FileLoadException && ex.Message == "Assembly with same name is already loaded") + if (ex is FileLoadException && ex.Message.Contains("Assembly with same name is already loaded")) { var assemblyName = AssemblyName.GetAssemblyName(path).Name; tmpAssemblies.Add(AssemblyLoadContext.Default.Assemblies.First(a => a.GetName().Name == assemblyName)); diff --git a/libs/common/Metrics/InfoMetricsType.cs b/libs/common/Metrics/InfoMetricsType.cs index 89c3e58183..766ff0341d 100644 --- a/libs/common/Metrics/InfoMetricsType.cs +++ b/libs/common/Metrics/InfoMetricsType.cs @@ -85,8 +85,7 @@ public enum InfoMetricsType : byte /// public static class InfoCommandUtils { - static readonly byte[][] infoSections = Enum.GetValues() - .Select(x => Encoding.ASCII.GetBytes($"${x.ToString().Length}\r\n{x}\r\n")).ToArray(); + static readonly byte[][] infoSections = [.. Enum.GetValues().Select(x => Encoding.ASCII.GetBytes($"${x.ToString().Length}\r\n{x}\r\n"))]; /// /// Return resp formatted info section diff --git a/libs/host/Garnet.host.csproj b/libs/host/Garnet.host.csproj index 872aa821a5..e7b6eea052 100644 --- a/libs/host/Garnet.host.csproj +++ b/libs/host/Garnet.host.csproj @@ -38,10 +38,12 @@ - + + + - + diff --git a/libs/server/Custom/CustomCommandManager.cs b/libs/server/Custom/CustomCommandManager.cs index 19a567a242..301e90e04e 100644 --- a/libs/server/Custom/CustomCommandManager.cs +++ b/libs/server/Custom/CustomCommandManager.cs @@ -86,10 +86,10 @@ internal int Register(string name, CommandType type, CustomRawStringFunctions cu var newCmd = new CustomRawStringCommand(name, (ushort)extId, type, arity, customFunctions, expirationTicks); var setSuccessful = rawStringCommandMap.TrySetValue(cmdId, ref newCmd); Debug.Assert(setSuccessful); - - if (commandInfo != null) customCommandsInfo.AddOrUpdate(name, commandInfo, (_, _) => commandInfo); - if (commandDocs != null) customCommandsDocs.AddOrUpdate(name, commandDocs, (_, _) => commandDocs); - + if (commandInfo != null) + customCommandsInfo.AddOrUpdate(name, commandInfo, (_, _) => commandInfo); + if (commandDocs != null) + customCommandsDocs.AddOrUpdate(name, commandDocs, (_, _) => commandDocs); return extId; } @@ -113,10 +113,10 @@ internal int Register(string name, Func proc, RespCo var newCmd = new CustomTransaction(name, (byte)cmdId, arity, proc); var setSuccessful = transactionProcMap.TrySetValue(cmdId, ref newCmd); Debug.Assert(setSuccessful); - - if (commandInfo != null) customCommandsInfo.AddOrUpdate(name, commandInfo, (_, _) => commandInfo); - if (commandDocs != null) customCommandsDocs.AddOrUpdate(name, commandDocs, (_, _) => commandDocs); - + if (commandInfo != null) + customCommandsInfo.AddOrUpdate(name, commandInfo, (_, _) => commandInfo); + if (commandDocs != null) + customCommandsDocs.AddOrUpdate(name, commandDocs, (_, _) => commandDocs); return cmdId; } @@ -166,8 +166,10 @@ internal int RegisterType(CustomObjectFactory factory) var scSetSuccessful = wrapper.commandMap.TrySetValue(scId, ref newSubCmd); Debug.Assert(scSetSuccessful); - if (commandInfo != null) customCommandsInfo.AddOrUpdate(name, commandInfo, (_, _) => commandInfo); - if (commandDocs != null) customCommandsDocs.AddOrUpdate(name, commandDocs, (_, _) => commandDocs); + if (commandInfo != null) + customCommandsInfo.AddOrUpdate(name, commandInfo, (_, _) => commandInfo); + if (commandDocs != null) + customCommandsDocs.AddOrUpdate(name, commandDocs, (_, _) => commandDocs); return (extId, scId); } @@ -193,8 +195,10 @@ internal int Register(string name, Func customProcedure, RespCo var setSuccessful = customProcedureMap.TrySetValue(cmdId, ref newCmd); Debug.Assert(setSuccessful); - if (commandInfo != null) customCommandsInfo.AddOrUpdate(name, commandInfo, (_, _) => commandInfo); - if (commandDocs != null) customCommandsDocs.AddOrUpdate(name, commandDocs, (_, _) => commandDocs); + if (commandInfo != null) + customCommandsInfo.AddOrUpdate(name, commandInfo, (_, _) => commandInfo); + if (commandDocs != null) + customCommandsDocs.AddOrUpdate(name, commandDocs, (_, _) => commandDocs); return cmdId; } diff --git a/libs/server/Metrics/Info/GarnetInfoMetrics.cs b/libs/server/Metrics/Info/GarnetInfoMetrics.cs index d9137b78c5..02e14589f5 100644 --- a/libs/server/Metrics/Info/GarnetInfoMetrics.cs +++ b/libs/server/Metrics/Info/GarnetInfoMetrics.cs @@ -12,7 +12,7 @@ namespace Garnet.server { class GarnetInfoMetrics { - public static readonly InfoMetricsType[] defaultInfo = Enum.GetValues() + public static readonly InfoMetricsType[] defaultInfo = [.. Enum.GetValues() .Where(e => e switch { InfoMetricsType.STOREHASHTABLE => false, @@ -20,8 +20,7 @@ class GarnetInfoMetrics InfoMetricsType.STOREREVIV => false, InfoMetricsType.OBJECTSTOREREVIV => false, _ => true - }) - .ToArray(); + })]; MetricsItem[] serverInfo = null; MetricsItem[] memoryInfo = null; diff --git a/libs/server/Objects/SortedSet/SortedSetObjectImpl.cs b/libs/server/Objects/SortedSet/SortedSetObjectImpl.cs index 0c21272e5e..3c7708a0d7 100644 --- a/libs/server/Objects/SortedSet/SortedSetObjectImpl.cs +++ b/libs/server/Objects/SortedSet/SortedSetObjectImpl.cs @@ -1034,10 +1034,9 @@ private void SortedSetPopMinOrMaxCount(ref ObjectInput input, ref SpanByteAndMem if (validLimit) { - elementsInLex = elementsInLex + elementsInLex = [.. elementsInLex .Skip(limit.Item1 > 0 ? limit.Item1 : 0) - .Take(limit.Item2 > 0 ? limit.Item2 : elementsInLex.Count) - .ToList(); + .Take(limit.Item2 > 0 ? limit.Item2 : elementsInLex.Count)]; } } catch (ArgumentException) @@ -1086,10 +1085,9 @@ private void SortedSetPopMinOrMaxCount(ref ObjectInput input, ref SpanByteAndMem if (doReverse) scoredElements.Reverse(); if (validLimit) { - scoredElements = scoredElements + scoredElements = [.. scoredElements .Skip(limit.Item1 > 0 ? limit.Item1 : 0) - .Take(limit.Item2 > 0 ? limit.Item2 : scoredElements.Count) - .ToList(); + .Take(limit.Item2 > 0 ? limit.Item2 : scoredElements.Count)]; } if (rem) diff --git a/libs/server/Objects/SortedSetGeo/SortedSetGeoObjectImpl.cs b/libs/server/Objects/SortedSetGeo/SortedSetGeoObjectImpl.cs index 6d7ee6a77a..eb9e5cefef 100644 --- a/libs/server/Objects/SortedSetGeo/SortedSetGeoObjectImpl.cs +++ b/libs/server/Objects/SortedSetGeo/SortedSetGeoObjectImpl.cs @@ -409,7 +409,7 @@ private void GeoSearch(ref ObjectInput input, ref SpanByteAndMemory output) } // Check that we have the mandatory options - if (errorMessage == default && !((opts.FromMember || opts.FromLonLat) && (opts.ByRadius || opts.ByBox))) + if (errorMessage.IsEmpty && !((opts.FromMember || opts.FromLonLat) && (opts.ByRadius || opts.ByBox))) argNumError = true; // Check if we have a wrong number of arguments @@ -420,7 +420,7 @@ private void GeoSearch(ref ObjectInput input, ref SpanByteAndMemory output) } // Check if we encountered an error while checking the parse state - if (errorMessage != default) + if (!errorMessage.IsEmpty) { while (!RespWriteUtils.TryWriteError(errorMessage, ref curr, end)) ObjectUtils.ReallocateOutput(ref output, ref isMemory, ref ptr, ref ptrHandle, ref curr, ref end); diff --git a/libs/server/Resp/RespCommandsInfo.cs b/libs/server/Resp/RespCommandsInfo.cs index 37b5dd5295..44de7903f9 100644 --- a/libs/server/Resp/RespCommandsInfo.cs +++ b/libs/server/Resp/RespCommandsInfo.cs @@ -184,8 +184,8 @@ private static bool TryInitializeRespCommandsInfo(ILogger logger = null) .Where(ci => !ci.Value.IsInternal) .ToDictionary(kvp => kvp.Key, kvp => kvp.Value, StringComparer.OrdinalIgnoreCase)); ExternalRespSubCommandsInfo = new ReadOnlyDictionary(tmpExternalSubCommandsInfo); - AllRespCommandNames = ImmutableHashSet.Create(StringComparer.OrdinalIgnoreCase, AllRespCommandsInfo.Keys.ToArray()); - ExternalRespCommandNames = ImmutableHashSet.Create(StringComparer.OrdinalIgnoreCase, ExternalRespCommandsInfo.Keys.ToArray()); + AllRespCommandNames = ImmutableHashSet.Create(StringComparer.OrdinalIgnoreCase, [.. AllRespCommandsInfo.Keys]); + ExternalRespCommandNames = ImmutableHashSet.Create(StringComparer.OrdinalIgnoreCase, [.. ExternalRespCommandsInfo.Keys]); FlattenedRespCommandsInfo = new ReadOnlyDictionary(tmpFlattenedRespCommandsInfo); AclCommandInfo = diff --git a/libs/server/ServerConfig.cs b/libs/server/ServerConfig.cs index 634114bb31..0b39c2b582 100644 --- a/libs/server/ServerConfig.cs +++ b/libs/server/ServerConfig.cs @@ -12,13 +12,13 @@ namespace Garnet.server { static class ServerConfig { - public static readonly HashSet DefaultConfigType = Enum.GetValues(). + public static readonly HashSet DefaultConfigType = [.. Enum.GetValues(). Where(e => e switch { ServerConfigType.NONE => false, ServerConfigType.ALL => false, _ => true - }).ToHashSet(); + })]; public static unsafe ServerConfigType GetConfig(Span parameter) { diff --git a/libs/server/StoreWrapper.cs b/libs/server/StoreWrapper.cs index 0def6ff075..2d47a49b27 100644 --- a/libs/server/StoreWrapper.cs +++ b/libs/server/StoreWrapper.cs @@ -27,7 +27,7 @@ namespace Garnet.server /// /// Wrapper for store and store-specific information /// - public sealed class StoreWrapper + public sealed class StoreWrapper : IDisposable { internal readonly string version; internal readonly string redisProtocolVersion; diff --git a/libs/server/TLS/CertificateUtils.cs b/libs/server/TLS/CertificateUtils.cs index 672626f6e9..ddad3c5e47 100644 --- a/libs/server/TLS/CertificateUtils.cs +++ b/libs/server/TLS/CertificateUtils.cs @@ -58,7 +58,11 @@ public static X509Certificate2 GetMachineCertificateBySubjectName(string subject /// public static X509Certificate2 GetMachineCertificateByFile(string fileName, string password) { +#if NET9_0_OR_GREATER + return X509CertificateLoader.LoadPkcs12FromFile(fileName, password); +#else return new X509Certificate2(fileName, password); +#endif } } } \ No newline at end of file diff --git a/libs/server/TLS/GarnetTlsOptions.cs b/libs/server/TLS/GarnetTlsOptions.cs index 607a3076b5..68db7c8355 100644 --- a/libs/server/TLS/GarnetTlsOptions.cs +++ b/libs/server/TLS/GarnetTlsOptions.cs @@ -257,7 +257,11 @@ X509Certificate2 GetCertificateIssuer(string issuerCertificatePath) { try { +#if NET9_0_OR_GREATER + issuer = X509CertificateLoader.LoadCertificateFromFile(issuerCertificatePath); +#else issuer = new X509Certificate2(issuerCertificatePath); +#endif } catch (Exception ex) { @@ -295,9 +299,7 @@ bool ValidateCertificateIssuer(X509Certificate2 certificateToValidate, X509Certi var chainBuilt = chain.Build(certificateToValidate); if (!chainBuilt) { - string[] errors = chain.ChainStatus - .Select(x => String.Format("{0} ({1})", x.StatusInformation.Trim(), x.Status)) - .ToArray(); + string[] errors = [.. chain.ChainStatus.Select(x => String.Format("{0} ({1})", x.StatusInformation.Trim(), x.Status))]; string certificateErrorsString = "Unknown errors."; if (errors != null && errors.Length > 0) certificateErrorsString = String.Join(", ", errors); diff --git a/libs/storage/Tsavorite/cs/test/OverflowBucketLockTableTests.cs b/libs/storage/Tsavorite/cs/test/OverflowBucketLockTableTests.cs index 72f7298a79..4cb0324b69 100644 --- a/libs/storage/Tsavorite/cs/test/OverflowBucketLockTableTests.cs +++ b/libs/storage/Tsavorite/cs/test/OverflowBucketLockTableTests.cs @@ -317,7 +317,7 @@ FixedLengthLockableKeyStruct createKey() KeyHash = keyHash, }; } - return Enumerable.Range(0, numRecords).Select(ii => createKey()).ToArray(); + return [.. Enumerable.Range(0, numRecords).Select(ii => createKey())]; } void AssertSorted(FixedLengthLockableKeyStruct[] keys, int count) diff --git a/main/GarnetServer/Properties/PublishProfiles/linux-arm64-based.pubxml b/main/GarnetServer/Properties/PublishProfiles/linux-arm64-based.pubxml index f3fcef046b..5d2e057b2d 100644 --- a/main/GarnetServer/Properties/PublishProfiles/linux-arm64-based.pubxml +++ b/main/GarnetServer/Properties/PublishProfiles/linux-arm64-based.pubxml @@ -3,15 +3,23 @@ https://go.microsoft.com/fwlink/?LinkID=208121. --> - - Release - Any CPU - bin\Release\net8.0\publish\linux-arm64\ - FileSystem - <_TargetId>Folder - net8.0 - linux-arm64 - false - true - - \ No newline at end of file + + Release + Any CPU + FileSystem + <_TargetId>Folder + net8.0;net9.0 + linux-arm64 + false + true + + + + bin\Release\net8.0\publish\linux-arm64\ + + + + bin\Release\net9.0\publish\linux-arm64\ + + + diff --git a/main/GarnetServer/Properties/PublishProfiles/linux-x64-based.pubxml b/main/GarnetServer/Properties/PublishProfiles/linux-x64-based.pubxml index 49c61f6121..b81d7b436c 100644 --- a/main/GarnetServer/Properties/PublishProfiles/linux-x64-based.pubxml +++ b/main/GarnetServer/Properties/PublishProfiles/linux-x64-based.pubxml @@ -9,9 +9,17 @@ https://go.microsoft.com/fwlink/?LinkID=208121. bin\Release\net8.0\publish\linux-x64\ FileSystem <_TargetId>Folder - net8.0 + net8.0;net9.0 linux-x64 false true + + + bin\Release\net8.0\publish\linux-x64\ + + + + bin\Release\net9.0\publish\linux-x64\ + \ No newline at end of file diff --git a/main/GarnetServer/Properties/PublishProfiles/osx-arm64-based.pubxml b/main/GarnetServer/Properties/PublishProfiles/osx-arm64-based.pubxml index a8ede61b7a..539c32a94c 100644 --- a/main/GarnetServer/Properties/PublishProfiles/osx-arm64-based.pubxml +++ b/main/GarnetServer/Properties/PublishProfiles/osx-arm64-based.pubxml @@ -6,12 +6,19 @@ https://go.microsoft.com/fwlink/?LinkID=208121. Release Any CPU - bin\Release\net8.0\publish\osx-arm64\ FileSystem <_TargetId>Folder - net8.0 + net8.0;net9.0 osx-arm64 false true + + + bin\Release\net8.0\publish\osx-arm64\ + + + + bin\Release\net9.0\publish\osx-arm64\ + \ No newline at end of file diff --git a/main/GarnetServer/Properties/PublishProfiles/osx-x64-based.pubxml b/main/GarnetServer/Properties/PublishProfiles/osx-x64-based.pubxml index 14715051d3..385acfa711 100644 --- a/main/GarnetServer/Properties/PublishProfiles/osx-x64-based.pubxml +++ b/main/GarnetServer/Properties/PublishProfiles/osx-x64-based.pubxml @@ -6,12 +6,19 @@ https://go.microsoft.com/fwlink/?LinkID=208121. Release Any CPU - bin\Release\net8.0\publish\osx-x64\ FileSystem <_TargetId>Folder - net8.0 + net8.0;net9.0 osx-x64 false true + + + bin\Release\net8.0\publish\osx-x64\ + + + + bin\Release\net9.0\publish\osx-x64\ + \ No newline at end of file diff --git a/main/GarnetServer/Properties/PublishProfiles/portable.pubxml b/main/GarnetServer/Properties/PublishProfiles/portable.pubxml index a48466510a..ccf19e6a15 100644 --- a/main/GarnetServer/Properties/PublishProfiles/portable.pubxml +++ b/main/GarnetServer/Properties/PublishProfiles/portable.pubxml @@ -6,10 +6,17 @@ https://go.microsoft.com/fwlink/?LinkID=208121. Release Any CPU - bin\Release\net8.0\publish\portable\ FileSystem <_TargetId>Folder - net8.0 + net8.0;net9.0 false + + + bin\Release\net8.0\publish\portable\ + + + + bin\Release\net9.0\publish\portable\ + \ No newline at end of file diff --git a/main/GarnetServer/Properties/PublishProfiles/win-arm64-based-readytorun.pubxml b/main/GarnetServer/Properties/PublishProfiles/win-arm64-based-readytorun.pubxml index c02cd8414f..a2cf6e89f1 100644 --- a/main/GarnetServer/Properties/PublishProfiles/win-arm64-based-readytorun.pubxml +++ b/main/GarnetServer/Properties/PublishProfiles/win-arm64-based-readytorun.pubxml @@ -6,13 +6,20 @@ https://go.microsoft.com/fwlink/?LinkID=208121. Release Any CPU - bin\Release\net8.0\publish\win-arm64\ FileSystem <_TargetId>Folder - net8.0 + net8.0;net9.0 win-arm64 false true true + + + bin\Release\net8.0\publish\win-arm64\ + + + + bin\Release\net9.0\publish\win-arm64\ + \ No newline at end of file diff --git a/main/GarnetServer/Properties/PublishProfiles/win-x64-based-readytorun.pubxml b/main/GarnetServer/Properties/PublishProfiles/win-x64-based-readytorun.pubxml index 0dbb866b72..645e8752f5 100644 --- a/main/GarnetServer/Properties/PublishProfiles/win-x64-based-readytorun.pubxml +++ b/main/GarnetServer/Properties/PublishProfiles/win-x64-based-readytorun.pubxml @@ -6,13 +6,20 @@ https://go.microsoft.com/fwlink/?LinkID=208121. Release Any CPU - bin\Release\net8.0\publish\win-x64\ FileSystem <_TargetId>Folder - net8.0 + net8.0;net9.0 win-x64 false true true + + + bin\Release\net8.0\publish\win-x64\ + + + + bin\Release\net9.0\publish\win-x64\ + \ No newline at end of file diff --git a/playground/ClusterStress/Program.cs b/playground/ClusterStress/Program.cs index fcea43a3bb..a6d943c708 100644 --- a/playground/ClusterStress/Program.cs +++ b/playground/ClusterStress/Program.cs @@ -62,7 +62,7 @@ static void RunShardedBasicCommandsBenchmark(Options opts) if (!opts.SkipLoad) bench.LoadData(keyLen: opts.KeyLength, valueLen: opts.ValueLength, BatchSize: opts.BatchSize.First()); - int[] threadBench = opts.NumThreads.ToArray(); + int[] threadBench = [.. opts.NumThreads]; int keyLen = opts.KeyLength; int valueLen = opts.ValueLength; foreach (int BatchSize in opts.BatchSize) diff --git a/playground/CommandInfoUpdater/CommandInfoUpdater.cs b/playground/CommandInfoUpdater/CommandInfoUpdater.cs index fd0ab4238e..a96d70dda2 100644 --- a/playground/CommandInfoUpdater/CommandInfoUpdater.cs +++ b/playground/CommandInfoUpdater/CommandInfoUpdater.cs @@ -276,7 +276,7 @@ private static IReadOnlyDictionary GetUpdatedCommandsI if (existingCommandsInfo.ContainsKey(command.Command)) { updatedSubCommands = existingCommandsInfo[command.Command].SubCommands == null - ? new List() + ? [] : [.. existingCommandsInfo[command.Command].SubCommands]; // Add sub-commands with updated queried command info diff --git a/playground/Embedded.perftest/EmbeddedPerformanceTest.cs b/playground/Embedded.perftest/EmbeddedPerformanceTest.cs index 49c123d160..1df47f5846 100644 --- a/playground/Embedded.perftest/EmbeddedPerformanceTest.cs +++ b/playground/Embedded.perftest/EmbeddedPerformanceTest.cs @@ -53,8 +53,8 @@ public EmbeddedPerformanceTest(EmbeddedRespServer server, Options opts, ILoggerF if (opts.OpPercent == null || opts.OpWorkload == null) throw new Exception("OpPercent and OpWorkload must be specified!"); - opPercent = opts.OpPercent.ToArray(); - opWorkload = opts.OpWorkload.ToArray(); + opPercent = [.. opts.OpPercent]; + opWorkload = [.. opts.OpWorkload]; if (opPercent.Length != opWorkload.Length) throw new Exception($"opPercent {opWorkload.Length} and opWorkload {opWorkload.Length} mismatch!"); diff --git a/playground/GarnetClientStress/Program.cs b/playground/GarnetClientStress/Program.cs index 793e6dda6f..b622bb71ce 100644 --- a/playground/GarnetClientStress/Program.cs +++ b/playground/GarnetClientStress/Program.cs @@ -24,11 +24,6 @@ static void Main(string[] args) private static void ConfigureGlobalRuntimeSettings() { ThreadPool.SetMinThreads(workerThreads: 1000, completionPortThreads: 1000); - ServicePointManager.UseNagleAlgorithm = false; - ServicePointManager.Expect100Continue = false; - ServicePointManager.CheckCertificateRevocationList = false; - ServicePointManager.DefaultConnectionLimit = 1024; - ServicePointManager.ReusePort = true; } } } \ No newline at end of file diff --git a/playground/GarnetClientStress/StressTestUtil.cs b/playground/GarnetClientStress/StressTestUtil.cs index 83877aca14..aa90ec6098 100644 --- a/playground/GarnetClientStress/StressTestUtil.cs +++ b/playground/GarnetClientStress/StressTestUtil.cs @@ -20,17 +20,25 @@ public class StressTestUtils public static string RandomValue(Random r, int valueSize) { - return new string(Enumerable.Repeat(ascii_chars, valueSize) - .Select(s => s[r.Next(s.Length)]).ToArray()); + return new string([.. Enumerable.Repeat(ascii_chars, valueSize).Select(s => s[r.Next(s.Length)])]); } public static T NotNull(T argument, string parameterName) where T : class => argument ?? throw new ArgumentNullException(parameterName); + private static X509Certificate2 GetClientCertificate(string filename, string password) + { +#if NET9_0_OR_GREATER + return X509CertificateLoader.LoadPkcs12FromFile(filename, password); +#else + return new X509Certificate2(filename, password); +#endif + } + public static SslClientAuthenticationOptions GetTlsOptions(string tlsHost) { return new SslClientAuthenticationOptions { - ClientCertificates = [new X509Certificate2("testcert.pfx", "placeholder")], + ClientCertificates = [GetClientCertificate("testcert.pfx", "placeholder")], TargetHost = tlsHost, AllowRenegotiation = false, RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true, diff --git a/samples/GarnetClientSample/GarnetClientSamples.cs b/samples/GarnetClientSample/GarnetClientSamples.cs index 75521c07e1..45837a045c 100644 --- a/samples/GarnetClientSample/GarnetClientSamples.cs +++ b/samples/GarnetClientSample/GarnetClientSamples.cs @@ -251,9 +251,18 @@ async Task SetGetMemoryAsync() Console.WriteLine("SetGetMemoryAsync: Success"); } + static X509Certificate2 GetClientCertificate(string filename, string password) + { +#if NET9_0_OR_GREATER + return X509CertificateLoader.LoadPkcs12FromFile(filename, password); +#else + return new X509Certificate2(filename, password); +#endif + } + SslClientAuthenticationOptions GetSslOpts() => useTLS ? new() { - ClientCertificates = [new X509Certificate2("testcert.pfx", "placeholder")], + ClientCertificates = [GetClientCertificate("testcert.pfx", "placeholder")], TargetHost = "GarnetTest", RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true, } : null; diff --git a/test/BDNPerfTests/BDN_Benchmark_Config.json b/test/BDNPerfTests/BDN_Benchmark_Config.json index da7782f563..feaf448261 100644 --- a/test/BDNPerfTests/BDN_Benchmark_Config.json +++ b/test/BDNPerfTests/BDN_Benchmark_Config.json @@ -1,7 +1,7 @@ { "_comment": "NOTE: If adding a new BDN perf test to this file, you will need to add the name to the test: line in ci-bdnbenchmark.yml (~line 45). This ensures all the tests are not ran sequentially when ran as github action.", "_comment2": "NOTE: The BDN Perf name in the ci-bdnbenchmark.yml file test: line should NOT have the BDN.benchmark prefix and the .* ending. It needs to be this way for the reporting part of the BDN Charts.", - "_comment3": "NOTE: The expected values are the Allocated results from BDN tests.", + "_comment3": "NOTE: The expected values are the Allocated results from BDN tests. The values listed here are used for Windows / Linux and Net 8.0 and Net 9.0. In the case where one configuration is higher, set that higher value here.", "BDN.benchmark.Operations.BasicOperations.*": { "expected_InlinePing_ACL": 0, @@ -31,7 +31,7 @@ "expected_HMGet_ACL": 0, "expected_HMSet_ACL": 0, "expected_HRandField_ACL": 0, - "expected_HScan_ACL": 776, + "expected_HScan_ACL": 5100, "expected_HSetNx_ACL": 0, "expected_HStrLen_ACL": 0, "expected_HVals_ACL": 0, @@ -43,26 +43,26 @@ "expected_HIncrbyFloat_AOF": 14400, "expected_HKeys_AOF": 3200, "expected_HLen_AOF": 3200, - "expected_HMGet_AOF": 9600, + "expected_HMGet_AOF": 76000, "expected_HMSet_AOF": 16000, "expected_HRandField_AOF": 8800, - "expected_HScan_AOF": 776, - "expected_HSetNx_AOF": 9600, - "expected_HStrLen_AOF": 6400, + "expected_HScan_AOF": 4900, + "expected_HSetNx_AOF": 69000, + "expected_HStrLen_AOF": 47000, "expected_HVals_AOF": 3200, - "expected_HSetDel_None": 16000, + "expected_HSetDel_None": 120000, "expected_HExists_None": 6400, "expected_HGet_None": 6400, "expected_HGetAll_None": 3200, - "expected_HIncrby_None": 14400, + "expected_HIncrby_None": 58400, "expected_HIncrbyFloat_None": 14400, "expected_HKeys_None": 3200, "expected_HLen_None": 3200, - "expected_HMGet_None": 9600, - "expected_HMSet_None": 16000, + "expected_HMGet_None": 67000, + "expected_HMSet_None": 114000, "expected_HRandField_None": 8800, - "expected_HScan_None": 776, - "expected_HSetNx_None": 9600, + "expected_HScan_None": 4500, + "expected_HSetNx_None": 74000, "expected_HStrLen_None": 6400, "expected_HVals_None": 3200 }, @@ -81,7 +81,7 @@ "expected_ZMScore_ACL": 0, "expected_ZPopMax_ACL": 6400, "expected_ZPopMin_ACL": 6400, - "expected_ZRandMember_ACL": 1184, + "expected_ZRandMember_ACL": 7400, "expected_ZRange_ACL": 0, "expected_ZRangeStore_ACL": 0, "expected_ZRank_ACL": 0, @@ -95,56 +95,56 @@ "expected_ZUnionStore_ACL": 0, "expected_ZAddRem_AOF": 18400, "expected_ZCard_AOF": 3200, - "expected_ZCount_AOF": 20000, - "expected_ZDiff_AOF": 25600, + "expected_ZCount_AOF": 135000, + "expected_ZDiff_AOF": 303000, "expected_ZDiffStore_AOF": 27200, "expected_ZIncrby_AOF": 12000, - "expected_ZInter_AOF": 34400, - "expected_ZInterCard_AOF": 34400, + "expected_ZInter_AOF": 221000, + "expected_ZInterCard_AOF": 212000, "expected_ZInterStore_AOF": 123200, "expected_ZLexCount_AOF": 66400, "expected_ZMPop_AOF": 59201, "expected_ZMScore_AOF": 6400, "expected_ZPopMax_AOF": 48001, "expected_ZPopMin_AOF": 48001, - "expected_ZRandMember_AOF": 1184, - "expected_ZRange_AOF": 28000, - "expected_ZRangeStore_AOF": 12800, - "expected_ZRank_AOF": 13600, + "expected_ZRandMember_AOF": 6900, + "expected_ZRange_AOF": 209588, + "expected_ZRangeStore_AOF": 580000, + "expected_ZRank_AOF": 100000, "expected_ZRemRangeByLex_AOF": 111201, "expected_ZRemRangeByRank_AOF": 84801, "expected_ZRemRangeByScore_AOF": 84001, - "expected_ZRevRank_AOF": 13600, - "expected_ZScan_AOF": 776, + "expected_ZRevRank_AOF": 87600, + "expected_ZScan_AOF": 4800, "expected_ZScore_AOF": 6400, - "expected_ZUnion_AOF": 34400, - "expected_ZUnionStore_AOF": 129600, - "expected_ZAddRem_None": 18400, + "expected_ZUnion_AOF": 260000, + "expected_ZUnionStore_AOF": 452600, + "expected_ZAddRem_None": 149000, "expected_ZCard_None": 3200, - "expected_ZCount_None": 20000, - "expected_ZDiff_None": 25600, + "expected_ZCount_None": 150000, + "expected_ZDiff_None": 179000, "expected_ZDiffStore_None": 27200, "expected_ZIncrby_None": 12000, - "expected_ZInter_None": 34400, - "expected_ZInterCard_None": 34400, - "expected_ZInterStore_None": 79200, + "expected_ZInter_None": 250000, + "expected_ZInterCard_None": 222071, + "expected_ZInterStore_None": 537000, "expected_ZLexCount_None": 66400, "expected_ZMPop_None": 59201, "expected_ZMScore_None": 6400, "expected_ZPopMax_None": 48001, "expected_ZPopMin_None": 48001, - "expected_ZRandMember_None": 1184, - "expected_ZRange_None": 28000, - "expected_ZRangeStore_None": 12800, - "expected_ZRank_None": 13600, + "expected_ZRandMember_None": 7150, + "expected_ZRange_None": 320000, + "expected_ZRangeStore_None": 572000, + "expected_ZRank_None": 86000, "expected_ZRemRangeByLex_None": 111201, "expected_ZRemRangeByRank_None": 84801, "expected_ZRemRangeByScore_None": 84001, - "expected_ZRevRank_None": 13600, + "expected_ZRevRank_None": 80000, "expected_ZScan_None": 776, "expected_ZScore_None": 6400, - "expected_ZUnion_None": 34400, - "expected_ZUnionStore_None": 84800 + "expected_ZUnion_None": 220000, + "expected_ZUnionStore_None": 528000 }, "BDN.benchmark.Cluster.ClusterOperations.*": { "expected_Get_DSV": 0, @@ -192,8 +192,8 @@ "expected_ConstructSmall_Managed,Limit": 2097602, "expected_ConstructLarge_Managed,Limit": 2100666, "expected_CompileForSessionSmall_Managed,Limit": 1984, - "expected_CompileForSessionLarge_Managed,Limit": 1984, - "expected_ResetParametersSmall_Managed,None": 1984, + "expected_CompileForSessionLarge_Managed,Limit": 3000, + "expected_ResetParametersSmall_Managed,None": 3000, "expected_ResetParametersLarge_Managed,None": 1984, "expected_ConstructSmall_Managed,None": 2097674, "expected_ConstructLarge_Managed,None": 2100738, @@ -201,21 +201,21 @@ "expected_CompileForSessionLarge_Managed,None": 1984, "expected_ResetParametersSmall_Native,None": 1984, "expected_ResetParametersLarge_Native,None": 1984, - "expected_ConstructSmall_Native,None": 2400, + "expected_ConstructSmall_Native,None": 3024, "expected_ConstructLarge_Native,None": 5500, "expected_CompileForSessionSmall_Native,None": 2000, "expected_CompileForSessionLarge_Native,None": 1984, "expected_ResetParametersSmall_Tracked,Limit": 1984, "expected_ResetParametersLarge_Tracked,Limit": 1984, "expected_ConstructSmall_Tracked,Limit": 2400, - "expected_ConstructLarge_Tracked,Limit": 5500, + "expected_ConstructLarge_Tracked,Limit": 6500, "expected_CompileForSessionSmall_Tracked,Limit": 1984, "expected_CompileForSessionLarge_Tracked,Limit": 1984, "expected_ResetParametersSmall_Tracked,None": 1984, "expected_ResetParametersLarge_Tracked,None": 1984, "expected_ConstructSmall_Tracked,None": 2400, "expected_ConstructLarge_Tracked,None": 5500, - "expected_CompileForSessionSmall_Tracked,None": 1984, + "expected_CompileForSessionSmall_Tracked,None": 3000, "expected_CompileForSessionLarge_Tracked,None": 1984 }, "BDN.benchmark.Lua.LuaScriptCacheOperations.*": { @@ -227,21 +227,21 @@ "expected_Digest_Managed,Limit": 2000, "expected_LookupHit_Managed,None": 1984, "expected_LookupMiss_Managed,None": 1984, - "expected_LoadOuterHit_Managed,None": 1984, + "expected_LoadOuterHit_Managed,None": 3000, "expected_LoadInnerHit_Managed,None": 2097760, "expected_LoadMiss_Managed,None": 2000, "expected_Digest_Managed,None": 1984, "expected_LookupHit_Native,None": 1984, "expected_LookupMiss_Native,None": 1984, - "expected_LoadOuterHit_Native,None": 1984, + "expected_LoadOuterHit_Native,None": 2700, "expected_LoadInnerHit_Native,None": 2350, "expected_LoadMiss_Native,None": 1984, - "expected_Digest_Native,None": 1984, + "expected_Digest_Native,None": 3000, "expected_LookupHit_Tracked,Limit": 2000, "expected_LookupMiss_Tracked,Limit": 2000, - "expected_LoadOuterHit_Tracked,Limit": 1984, + "expected_LoadOuterHit_Tracked,Limit": 3000, "expected_LoadInnerHit_Tracked,Limit": 2350, - "expected_LoadMiss_Tracked,Limit": 1984, + "expected_LoadMiss_Tracked,Limit": 2700, "expected_Digest_Tracked,Limit": 1984, "expected_LookupHit_Tracked,None": 1984, "expected_LookupMiss_Tracked,None": 1984, @@ -303,65 +303,65 @@ "expected_Eval_Managed,Limit": 0, "expected_EvalSha_Managed,Limit": 0, "expected_SmallScript_Managed,Limit": 0, - "expected_LargeScript_Managed,Limit": 16, - "expected_ArrayReturn_Managed,Limit": 0, + "expected_LargeScript_Managed,Limit": 26, + "expected_ArrayReturn_Managed,Limit": 1, "expected_ScriptLoad_Managed,None": 9600, "expected_ScriptExistsTrue_Managed,None": 0, "expected_ScriptExistsFalse_Managed,None": 0, "expected_Eval_Managed,None": 0, "expected_EvalSha_Managed,None": 0, "expected_SmallScript_Managed,None": 0, - "expected_LargeScript_Managed,None": 16, - "expected_ArrayReturn_Managed,None": 0, + "expected_LargeScript_Managed,None": 26, + "expected_ArrayReturn_Managed,None": 1, "expected_ScriptLoad_Native,None": 9600, "expected_ScriptExistsTrue_Native,None": 0, "expected_ScriptExistsFalse_Native,None": 0, "expected_Eval_Native,None": 0, "expected_EvalSha_Native,None": 0, "expected_SmallScript_Native,None": 0, - "expected_LargeScript_Native,None": 16, - "expected_ArrayReturn_Native,None": 0, + "expected_LargeScript_Native,None": 26, + "expected_ArrayReturn_Native,None": 1, "expected_ScriptLoad_Tracked,Limit": 9600, "expected_ScriptExistsTrue_Tracked,Limit": 0, "expected_ScriptExistsFalse_Tracked,Limit": 0, "expected_Eval_Tracked,Limit": 0, "expected_EvalSha_Tracked,Limit": 0, "expected_SmallScript_Tracked,Limit": 0, - "expected_LargeScript_Tracked,Limit": 31, - "expected_ArrayReturn_Tracked,Limit": 0, + "expected_LargeScript_Tracked,Limit": 2800, + "expected_ArrayReturn_Tracked,Limit": 1, "expected_ScriptLoad_Tracked,None": 9600, "expected_ScriptExistsTrue_Tracked,None": 0, "expected_ScriptExistsFalse_Tracked,None": 0, "expected_Eval_Tracked,None": 0, "expected_EvalSha_Tracked,None": 0, "expected_SmallScript_Tracked,None": 0, - "expected_LargeScript_Tracked,None": 31, - "expected_ArrayReturn_Tracked,None": 0 + "expected_LargeScript_Tracked,None": 1000, + "expected_ArrayReturn_Tracked,None": 1 }, "BDN.benchmark.Operations.ModuleOperations.*": { "expected_ModuleNoOpRawStringReadCommand_ACL": 0, "expected_ModuleNoOpRawStringRmwCommand_ACL": 0, "expected_ModuleNoOpObjRmwCommand_ACL": 3200, - "expected_ModuleNoOpObjReadCommand_ACL": 3200, + "expected_ModuleNoOpObjReadCommand_ACL": 21000, "expected_ModuleNoOpProc_ACL": 0, "expected_ModuleNoOpTxn_ACL": 0, - "expected_ModuleJsonGetCommand_ACL": 72800, + "expected_ModuleJsonGetCommand_ACL": 400000, "expected_ModuleJsonSetCommand_ACL": 223200, "expected_ModuleNoOpRawStringReadCommand_AOF": 0, "expected_ModuleNoOpRawStringRmwCommand_AOF": 0, - "expected_ModuleNoOpObjRmwCommand_AOF": 3200, - "expected_ModuleNoOpObjReadCommand_AOF": 3200, + "expected_ModuleNoOpObjRmwCommand_AOF": 24000, + "expected_ModuleNoOpObjReadCommand_AOF": 26000, "expected_ModuleNoOpProc_AOF": 0, "expected_ModuleNoOpTxn_AOF": 0, - "expected_ModuleJsonGetCommand_AOF": 72800, - "expected_ModuleJsonSetCommand_AOF": 223200, + "expected_ModuleJsonGetCommand_AOF": 405000, + "expected_ModuleJsonSetCommand_AOF": 1550000, "expected_ModuleNoOpRawStringReadCommand_None": 0, "expected_ModuleNoOpRawStringRmwCommand_None": 0, "expected_ModuleNoOpObjRmwCommand_None": 3200, "expected_ModuleNoOpObjReadCommand_None": 3200, "expected_ModuleNoOpProc_None": 0, "expected_ModuleNoOpTxn_None": 0, - "expected_ModuleJsonGetCommand_None": 72800, + "expected_ModuleJsonGetCommand_None": 430000, "expected_ModuleJsonSetCommand_None": 223200 }, "BDN.benchmark.Network.RawStringOperations.*": { diff --git a/test/BDNPerfTests/run_bdnperftest.ps1 b/test/BDNPerfTests/run_bdnperftest.ps1 index f3f72a0efe..376f16420a 100644 --- a/test/BDNPerfTests/run_bdnperftest.ps1 +++ b/test/BDNPerfTests/run_bdnperftest.ps1 @@ -48,6 +48,7 @@ function AnalyzeResult { if ($warnonly) { Write-Host "** << PERF REGRESSION WARNING! >> The BDN benchmark found Allocated value ($dblfoundResultValue) is above the acceptable threshold of $UpperBound (Expected value $expectedResultValue + $acceptablePercentRange%)" Write-Host "** " + return $true # Since it is warning, don't want to cause a fail } else { Write-Host "** << PERF REGRESSION FAIL! >> The BDN benchmark found Allocated value ($dblfoundResultValue) is above the acceptable threshold of $UpperBound (Expected value $expectedResultValue + $acceptablePercentRange%)" @@ -235,7 +236,7 @@ Get-Content $resultsFile | ForEach-Object { # Check if found value is not equal to expected value Write-Host "** Config: "$expectedResultsArray[$currentExpectedProp, 0].Substring(2) $expectedResultsArray[$currentExpectedProp, 1] - $currentResults = AnalyzeResult $foundValue $expectedResultsArray[$currentExpectedProp, 2] $acceptableAllocatedRange $true + $currentResults = AnalyzeResult $foundValue $expectedResultsArray[$currentExpectedProp, 2] $acceptableAllocatedRange $false if ($currentResults -eq $false) { $testSuiteResult = $false } diff --git a/test/Garnet.test.cluster/ClusterMigrateTests.cs b/test/Garnet.test.cluster/ClusterMigrateTests.cs index 440cf64250..76cb5f06ec 100644 --- a/test/Garnet.test.cluster/ClusterMigrateTests.cs +++ b/test/Garnet.test.cluster/ClusterMigrateTests.cs @@ -794,7 +794,7 @@ private string DoZCOUNT(int nodeIndex, byte[] key, out int count, out string add address = ((IPEndPoint)server.EndPoint).Address.ToString(); port = ((IPEndPoint)server.EndPoint).Port; slot = ClusterTestUtils.HashSlot(key); - return ("OK", ((RedisResult[])result).Select(x => (string)x).ToList()); + return ("OK", [.. ((RedisResult[])result).Select(x => (string)x)]); } catch (Exception e) { diff --git a/test/Garnet.test.cluster/ClusterRedirectTests.cs b/test/Garnet.test.cluster/ClusterRedirectTests.cs index 11ce401f05..d0434027e7 100644 --- a/test/Garnet.test.cluster/ClusterRedirectTests.cs +++ b/test/Garnet.test.cluster/ClusterRedirectTests.cs @@ -643,7 +643,7 @@ public void ClusterSingleKeyRedirectionTests() context.CreateInstances(Shards, cleanClusterConfig: true); context.CreateConnection(); - var connections = ClusterTestUtils.CreateLightRequestConnections(Enumerable.Range(Port, Shards).ToArray()); + var connections = ClusterTestUtils.CreateLightRequestConnections([.. Enumerable.Range(Port, Shards)]); _ = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); //1. Regular operation redirect responses @@ -708,7 +708,7 @@ public void ClusterMultiKeyRedirectionTests() context.CreateInstances(Shards, cleanClusterConfig: true); context.CreateConnection(); - var connections = ClusterTestUtils.CreateLightRequestConnections(Enumerable.Range(Port, Shards).ToArray()); + var connections = ClusterTestUtils.CreateLightRequestConnections([.. Enumerable.Range(Port, Shards)]); _ = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); //1. test regular operation redirection diff --git a/test/Garnet.test.cluster/ClusterTestUtils.cs b/test/Garnet.test.cluster/ClusterTestUtils.cs index d5b1ea83a4..499f23a1b9 100644 --- a/test/Garnet.test.cluster/ClusterTestUtils.cs +++ b/test/Garnet.test.cluster/ClusterTestUtils.cs @@ -123,10 +123,10 @@ private void ThrowException(string msg) } public IPEndPoint[] GetEndpoints() - => endpoints.Select(x => (IPEndPoint)x).ToArray(); + => [.. endpoints.Select(x => (IPEndPoint)x)]; public IPEndPoint[] GetEndpointsWithout(IPEndPoint endPoint) => - endpoints.Select(x => (IPEndPoint)x).Where(x => x.Port != endPoint.Port || x.Address != endPoint.Address).ToArray(); + [.. endpoints.Select(x => (IPEndPoint)x).Where(x => x.Port != endPoint.Port || x.Address != endPoint.Address)]; public RedisResult Execute(IPEndPoint endPoint, string cmd, ICollection args, bool skipLogging = false, ILogger logger = null) { @@ -146,7 +146,7 @@ public RedisResult Execute(IPEndPoint endPoint, string cmd, ICollection } public RedisResult NodesV2(IPEndPoint endPoint, ILogger logger = null) - => Execute(endPoint, "cluster", new List { "nodes" }, skipLogging: true, logger); + => Execute(endPoint, "cluster", ["nodes"], skipLogging: true, logger); public string NodesMyself(IPEndPoint endPoint, ClusterInfoTag tag, ILogger logger) { @@ -252,7 +252,7 @@ public string ClusterMyId(IPEndPoint source, ILogger logger = null) private static List<(int, int)>[] GetSlotRanges(int primary_count) { - List<(int, int)>[] slotRanges = new List<(int, int)>[primary_count]; + var slotRanges = new List<(int, int)>[primary_count]; int slotCount = 16384; for (int i = 0; i < primary_count; i++) @@ -1050,7 +1050,7 @@ public void BumpEpoch(IPEndPoint endPoint, bool waitForSync = false, ILogger log public void WaitForConfigPropagation(int fromNode, List nodes = null, ILogger logger = null) { if (nodes == null) - nodes = Enumerable.Range(0, endpoints.Count).ToList(); + nodes = [.. Enumerable.Range(0, endpoints.Count)]; var fromNodeConfig = ClusterNodes(fromNode, logger: logger); while (true) { @@ -1419,7 +1419,7 @@ public List GetKeysInSlot(int nodeIndex, int slot, int keyCount, ILogger var server = redis.GetServer((IPEndPoint)endpoints[nodeIndex]); var resp = server.Execute("cluster", "getkeysinslot", $"{slot}", $"{keyCount}"); - return ((RedisResult[])resp).Select(x => Encoding.ASCII.GetBytes((string)x)).ToList(); + return [.. ((RedisResult[])resp).Select(x => Encoding.ASCII.GetBytes((string)x))]; } catch (Exception ex) { @@ -2371,7 +2371,7 @@ public string GetMultiKey(int nodeIndex, List keys, out List get try { var result = server.Execute("mget", args, CommandFlags.NoRedirect); - getResult = ((RedisResult[])result).Select(x => (byte[])x).ToList(); + getResult = [.. ((RedisResult[])result).Select(x => (byte[])x)]; return "OK"; } catch (Exception e) diff --git a/test/Garnet.test/GarnetClientTests.cs b/test/Garnet.test/GarnetClientTests.cs index eb51cac399..bf21b491d7 100644 --- a/test/Garnet.test/GarnetClientTests.cs +++ b/test/Garnet.test/GarnetClientTests.cs @@ -518,7 +518,7 @@ public async Task CanDoBulkDeleteTests([Values] bool useStringType) var sc = new CancellationTokenSource(); var t = sc.Token; ManualResetEventSlim mrObj = new(false); - var tDeletingK = Task.Run(async () => { await DeleteKeysWithCT(keys.Skip(iterationSize).Take(iterationSize).ToArray(), null, mrObj, t); }); + var tDeletingK = Task.Run(async () => { await DeleteKeysWithCT([.. keys.Skip(iterationSize).Take(iterationSize)], null, mrObj, t); }); // send the cancellation so the task throws an exception sc.Cancel(); @@ -547,7 +547,7 @@ public async Task CanDoBulkDeleteTests([Values] bool useStringType) ManualResetEventSlim mrObj = new(false); // try delete using Memory type - var tDeletingKeysMB = Task.Run(async () => { await DeleteKeysWithCT(null, keysMemoryByte.Skip(iterationSize).Take(iterationSize).ToArray(), mrObj, t, true); }); + var tDeletingKeysMB = Task.Run(async () => { _ = await DeleteKeysWithCT(null, [.. keysMemoryByte.Skip(iterationSize).Take(iterationSize)], mrObj, t, true); }); sc.Cancel(); mrObj.Set(); Assert.Throws(() => tDeletingKeysMB.Wait(sc.Token)); diff --git a/test/Garnet.test/HyperLogLogTests.cs b/test/Garnet.test/HyperLogLogTests.cs index 646cfd86d4..87a91ed689 100644 --- a/test/Garnet.test/HyperLogLogTests.cs +++ b/test/Garnet.test/HyperLogLogTests.cs @@ -516,7 +516,7 @@ public RedisValue[] RandomRedisValueSubseq(List list, int count) public static List ToList(RedisValue[] rss) { - return rss.Select(x => (long)x).ToList(); + return [.. rss.Select(x => (long)x)]; } [Test] diff --git a/test/Garnet.test/LuaScriptTests.cs b/test/Garnet.test/LuaScriptTests.cs index 42d0894131..b1a6a79786 100644 --- a/test/Garnet.test/LuaScriptTests.cs +++ b/test/Garnet.test/LuaScriptTests.cs @@ -915,9 +915,27 @@ public void ScriptExistsMultiple() } } + private void DoErroneousRedisCall(IDatabase db, string[] args, string expectedError) + { + var exc = Assert.Throws(() => db.ScriptEvaluate($"return redis.call({string.Join(',', args)})")); + ClassicAssert.IsNotNull(exc); + StringAssert.StartsWith(expectedError, exc!.Message); + } + [Test] public void RedisCallErrors() { + // This is a temporary fix to address a regression in .NET9, an open issue can be found here - https://github.com/dotnet/runtime/issues/111242 + // Once the issue is resolved the #if can be removed permanently, as well as the environment variable setting in the CI. +#if NET9_0_OR_GREATER + var legacyExceptionHandlingEnvVarName = "DOTNET_LegacyExceptionHandling"; + var legacyExceptionHandlingEnvVarValue = Environment.GetEnvironmentVariable(legacyExceptionHandlingEnvVarName); + if (string.IsNullOrEmpty(legacyExceptionHandlingEnvVarValue)) + { + Assert.Ignore($"Ignoring test when {legacyExceptionHandlingEnvVarName} environment variable is not set."); + } +#endif + // Testing that our error replies for redis.call match Redis behavior // // TODO: exact matching of the hash and line number would also be nice, but that is trickier @@ -925,43 +943,30 @@ public void RedisCallErrors() var db = redis.GetDatabase(); // No args - { - var exc = ClassicAssert.Throws(() => db.ScriptEvaluate("return redis.call()")); - ClassicAssert.IsTrue(exc.Message.StartsWith("ERR Please specify at least one argument for this redis lib call")); - } + DoErroneousRedisCall(db, [], + Encoding.ASCII.GetString( + CmdStrings.LUA_ERR_Please_specify_at_least_one_argument_for_this_redis_lib_call)); // Unknown command - { - var exc = ClassicAssert.Throws(() => db.ScriptEvaluate("return redis.call('123')")); - ClassicAssert.IsTrue(exc.Message.StartsWith("ERR Unknown Redis command called from script")); - } + DoErroneousRedisCall(db, ["'123'"], + Encoding.ASCII.GetString(CmdStrings.LUA_ERR_Unknown_Redis_command_called_from_script)); + + var badArgumentsMessage = + Encoding.ASCII.GetString(CmdStrings + .LUA_ERR_Lua_redis_lib_command_arguments_must_be_strings_or_integers); // Bad command type - { - var exc = ClassicAssert.Throws(() => db.ScriptEvaluate("return redis.call({ foo = 'bar'})")); - ClassicAssert.IsTrue(exc.Message.StartsWith("ERR Lua redis lib command arguments must be strings or integers")); - } + DoErroneousRedisCall(db, ["{ foo = 'bar'}"], badArgumentsMessage); // GET bad arg type - { - var exc = ClassicAssert.Throws(() => db.ScriptEvaluate("return redis.call('GET', { foo = 'bar' })")); - ClassicAssert.IsTrue(exc.Message.StartsWith("ERR Lua redis lib command arguments must be strings or integers")); - } + DoErroneousRedisCall(db, ["'GET'", "{ foo = 'bar'}"], badArgumentsMessage); // SET bad arg types - { - var exc1 = ClassicAssert.Throws(() => db.ScriptEvaluate("return redis.call('SET', 'hello', { foo = 'bar' })")); - ClassicAssert.IsTrue(exc1.Message.StartsWith("ERR Lua redis lib command arguments must be strings or integers")); - - var exc2 = ClassicAssert.Throws(() => db.ScriptEvaluate("return redis.call('SET', { foo = 'bar' }, 'world')")); - ClassicAssert.IsTrue(exc2.Message.StartsWith("ERR Lua redis lib command arguments must be strings or integers")); - } + DoErroneousRedisCall(db, ["'SET'", "'hello'", "{ foo = 'bar'}"], badArgumentsMessage); + DoErroneousRedisCall(db, ["'SET'", "{ foo = 'bar'}", "'world'"], badArgumentsMessage); // Other bad arg types - { - var exc = ClassicAssert.Throws(() => db.ScriptEvaluate("return redis.call('DEL', { foo = 'bar' })")); - ClassicAssert.IsTrue(exc.Message.StartsWith("ERR Lua redis lib command arguments must be strings or integers")); - } + DoErroneousRedisCall(db, ["'DEL'", "{ foo = 'bar'}", "'world'"], badArgumentsMessage); } [Test] diff --git a/test/Garnet.test/RespAdminCommandsTests.cs b/test/Garnet.test/RespAdminCommandsTests.cs index 3e74e3c6a4..88319339d0 100644 --- a/test/Garnet.test/RespAdminCommandsTests.cs +++ b/test/Garnet.test/RespAdminCommandsTests.cs @@ -198,7 +198,7 @@ public void SeSaveRecoverObjectTest() { var db = redis.GetDatabase(0); db.ListLeftPush(key, ldata); - ldata = ldata.Select(x => x).Reverse().ToArray(); + ldata = [.. ldata.Select(x => x).Reverse()]; returned_data_before_recovery = db.ListRange(key); ClassicAssert.AreEqual(ldata, returned_data_before_recovery); diff --git a/test/Garnet.test/RespAofTests.cs b/test/Garnet.test/RespAofTests.cs index 4479630dc8..585a16842e 100644 --- a/test/Garnet.test/RespAofTests.cs +++ b/test/Garnet.test/RespAofTests.cs @@ -636,7 +636,7 @@ public void AofListObjectStoreRecoverTest() var count = db.ListLeftPush(key, ldata); ClassicAssert.AreEqual(4, count); - ldata = ldata.Select(x => x).Reverse().ToArray(); + ldata = [.. ldata.Select(x => x).Reverse()]; returned_data_before_recovery = db.ListRange(key); ClassicAssert.AreEqual(ldata, returned_data_before_recovery); } diff --git a/test/Garnet.test/RespCommandTests.cs b/test/Garnet.test/RespCommandTests.cs index 70b2e4ae9b..938d854b17 100644 --- a/test/Garnet.test/RespCommandTests.cs +++ b/test/Garnet.test/RespCommandTests.cs @@ -84,7 +84,7 @@ .. respCommandsInfo.Values.Where(ci => ci.IsInternal).Select(ci => ci.Command) public void TearDown() { server.Dispose(); - TestUtils.DeleteDirectory(TestUtils.MethodTestDir); + TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); TestUtils.DeleteDirectory(Directory.GetParent(extTestDir)?.FullName); } diff --git a/test/Garnet.test/RespGetLowMemoryTests.cs b/test/Garnet.test/RespGetLowMemoryTests.cs index ff39389a7e..e7fff41990 100644 --- a/test/Garnet.test/RespGetLowMemoryTests.cs +++ b/test/Garnet.test/RespGetLowMemoryTests.cs @@ -58,7 +58,7 @@ public void ScatterGatherGet() tasks[i] = (input[offset].Value, db.StringGetAsync(input[offset].Key)); } - Task.WaitAll(tasks.Select(r => r.Item2).ToArray()); + Task.WaitAll([.. tasks.Select(r => r.Item2)]); for (int i = 0; i < numGets; i++) ClassicAssert.AreEqual(tasks[i].Item1, tasks[i].Item2.Result); } @@ -79,7 +79,7 @@ public void ScatterGatherMGet() var result = db.StringSet(input); ClassicAssert.IsTrue(result); - var results = db.StringGet(input.Select(r => (RedisKey)r.Key).ToArray()); + var results = db.StringGet([.. input.Select(r => (RedisKey)r.Key)]); for (int i = 0; i < length; i++) ClassicAssert.AreEqual(input[i].Value, results[i]); } diff --git a/test/Garnet.test/RespSetTest.cs b/test/Garnet.test/RespSetTest.cs index fbb1eae1ec..d3251b3cff 100644 --- a/test/Garnet.test/RespSetTest.cs +++ b/test/Garnet.test/RespSetTest.cs @@ -556,7 +556,7 @@ public void CanDoSdiff(string key1, string key2) result = db.SetCombine(SetOperation.Difference, [new RedisKey(key1), new RedisKey(key2), new RedisKey(key3)]); ClassicAssert.AreEqual(2, result.Length); - strResult = result.Select(r => r.ToString()).ToArray(); + strResult = [.. result.Select(r => r.ToString())]; expectedResult = ["b", "d"]; ClassicAssert.IsTrue(expectedResult.OrderBy(t => t).SequenceEqual(strResult.OrderBy(t => t))); @@ -651,7 +651,7 @@ public void CanDoSmoveBasic(string source, string destination) ClassicAssert.IsTrue(expectedResult.OrderBy(t => t).SequenceEqual(strResult.OrderBy(t => t))); membersResult = db.SetMembers(destination); - strResult = membersResult.Select(r => r.ToString()).ToArray(); + strResult = [.. membersResult.Select(r => r.ToString())]; expectedResult = ["three", "two"]; ClassicAssert.IsTrue(expectedResult.OrderBy(t => t).SequenceEqual(strResult.OrderBy(t => t))); @@ -662,7 +662,7 @@ public void CanDoSmoveBasic(string source, string destination) ClassicAssert.IsFalse(exists); membersResult = db.SetMembers(destination); - strResult = membersResult.Select(r => r.ToString()).ToArray(); + strResult = [.. membersResult.Select(r => r.ToString())]; expectedResult = ["three", "two", "one"]; ClassicAssert.IsTrue(expectedResult.OrderBy(t => t).SequenceEqual(strResult.OrderBy(t => t))); } @@ -1570,7 +1570,7 @@ public void CheckIfMemberExistsInSetLC(string valuesInput, string findInput, str db.SetAdd(key, value); } - var actualResult = db.SetContains(key, find.Select(x => (RedisValue)x).ToArray()); + var actualResult = db.SetContains(key, [.. find.Select(x => (RedisValue)x)]); CollectionAssert.AreEqual(expectedResult, actualResult); } diff --git a/test/Garnet.test/RespSortedSetTests.cs b/test/Garnet.test/RespSortedSetTests.cs index 48819d416e..e40891b96a 100644 --- a/test/Garnet.test/RespSortedSetTests.cs +++ b/test/Garnet.test/RespSortedSetTests.cs @@ -308,13 +308,13 @@ public void AddWithOptionsErrorConditions() foreach (var argCombination in argCombinations) { - args = argCombination.Union(sampleEntries).ToArray(); + args = [.. argCombination.Union(sampleEntries)]; ex = Assert.Throws(() => db.Execute("ZADD", args)); ClassicAssert.AreEqual(Encoding.ASCII.GetString(CmdStrings.RESP_ERR_GT_LT_NX_NOT_COMPATIBLE), ex.Message); } // INCR option supports only one score-element pair - args = new[] { key, "INCR" }.Union(sampleEntries).ToArray(); + args = [.. new[] { key, "INCR" }.Union(sampleEntries)]; ex = Assert.Throws(() => db.Execute("ZADD", args)); ClassicAssert.AreEqual(Encoding.ASCII.GetString(CmdStrings.RESP_ERR_INCR_SUPPORTS_ONLY_SINGLE_PAIR), ex.Message); @@ -384,7 +384,7 @@ public void AddRemove() ClassicAssert.AreEqual(expectedResponse, actualValue); // remove all entries - var removed = db.SortedSetRemove(key, entries.Select(e => e.Element).ToArray()); + var removed = db.SortedSetRemove(key, [.. entries.Select(e => e.Element)]); ClassicAssert.AreEqual(entries.Length, removed); // length should be 0 @@ -410,7 +410,7 @@ public void AddRemove() ClassicAssert.AreEqual(expectedResponse, actualValue); // remove the single entry - removed = db.SortedSetRemove(key, entries.Take(1).Select(e => e.Element).ToArray()); + removed = db.SortedSetRemove(key, [.. entries.Take(1).Select(e => e.Element)]); ClassicAssert.AreEqual(1, removed); // length should be 0 @@ -452,7 +452,7 @@ public void AddRemove() ClassicAssert.AreEqual(expectedResponse, actualValue); // remaining entries removed - removed = db.SortedSetRemove(key, entries.Select(e => e.Element).ToArray()); + removed = db.SortedSetRemove(key, [.. entries.Select(e => e.Element)]); ClassicAssert.AreEqual(entries.Length - 1, removed); keyExists = db.KeyExists(key); @@ -1447,7 +1447,7 @@ public void CanDoZInterWithSE(int numKeys, string command, string[] expectedValu { var resultWithScores = db.SortedSetCombineWithScores(SetOperation.Intersect, command.Contains("WEIGHTS") ? [new RedisKey("zset1"), new RedisKey("zset2")] : - Enumerable.Range(1, numKeys).Select(i => new RedisKey($"zset{i}")).ToArray(), + [.. Enumerable.Range(1, numKeys).Select(i => new RedisKey($"zset{i}"))], command.Contains("WEIGHTS") ? [2.0, 3.0] : null, command.Contains("MAX") ? Aggregate.Max : command.Contains("MIN") ? Aggregate.Min : Aggregate.Sum); @@ -1462,7 +1462,7 @@ public void CanDoZInterWithSE(int numKeys, string command, string[] expectedValu else { var result = db.SortedSetCombine(SetOperation.Intersect, - Enumerable.Range(1, numKeys).Select(i => new RedisKey($"zset{i}")).ToArray()); + [.. Enumerable.Range(1, numKeys).Select(i => new RedisKey($"zset{i}"))]); ClassicAssert.AreEqual(expectedValues.Length, result.Length); for (int i = 0; i < expectedValues.Length; i++) diff --git a/test/Garnet.test/RespTests.cs b/test/Garnet.test/RespTests.cs index bde2c6911b..0a1f1c1345 100644 --- a/test/Garnet.test/RespTests.cs +++ b/test/Garnet.test/RespTests.cs @@ -505,7 +505,7 @@ public void MultiSetGet() var result = db.StringSet(input, When.NotExists); ClassicAssert.IsTrue(result); - var value = db.StringGet(input.Select(e => e.Key).ToArray()); + var value = db.StringGet([.. input.Select(e => e.Key)]); ClassicAssert.AreEqual(length, value.Length); for (int i = 0; i < length; i++) @@ -1460,8 +1460,7 @@ public void SingleDeleteWithObjectStoreDisabled() private string GetRandomString(int len) { const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - return new string(Enumerable.Repeat(chars, len) - .Select(s => s[r.Next(s.Length)]).ToArray()); + return new string([.. Enumerable.Repeat(chars, len).Select(s => s[r.Next(s.Length)])]); } [Test] diff --git a/test/Garnet.test/RespTlsTests.cs b/test/Garnet.test/RespTlsTests.cs index bfe58dd7a7..d9b418e450 100644 --- a/test/Garnet.test/RespTlsTests.cs +++ b/test/Garnet.test/RespTlsTests.cs @@ -90,7 +90,7 @@ public void TlsMultiSetGet() var result = db.StringSet(input); ClassicAssert.IsTrue(result); - var value = db.StringGet(input.Select(e => e.Key).ToArray()); + var value = db.StringGet([.. input.Select(e => e.Key)]); ClassicAssert.AreEqual(length, value.Length); for (int i = 0; i < length; i++) diff --git a/test/Garnet.test/TestProcedureHash.cs b/test/Garnet.test/TestProcedureHash.cs index 570a5f3312..cc51de2700 100644 --- a/test/Garnet.test/TestProcedureHash.cs +++ b/test/Garnet.test/TestProcedureHash.cs @@ -56,7 +56,7 @@ private static bool TestAPI(TGarnetApi api, ref CustomProcedureInput } // HSET - var status = api.HashSet(myHash, pairs.Take(pairs.Length - 2).ToArray(), out var count); + var status = api.HashSet(myHash, [.. pairs.Take(pairs.Length - 2)], out var count); if (status != GarnetStatus.OK || count != pairs.Length - 2) return false; diff --git a/test/Garnet.test/TestProcedureSet.cs b/test/Garnet.test/TestProcedureSet.cs index 17f782a8f8..2f33531bd4 100644 --- a/test/Garnet.test/TestProcedureSet.cs +++ b/test/Garnet.test/TestProcedureSet.cs @@ -51,7 +51,7 @@ private static bool TestAPI(TGarnetApi api, ref CustomProcedureInput elements[i] = GetNextArg(ref procInput, ref offset); } - var status = api.SetAdd(setA, elements.Take(9).ToArray(), out var count); + var status = api.SetAdd(setA, [.. elements.Take(9)], out var count); if (status != GarnetStatus.OK || count != 9) return false; diff --git a/test/Garnet.test/TestUtils.cs b/test/Garnet.test/TestUtils.cs index fc33c512f1..a74cbc5a9b 100644 --- a/test/Garnet.test/TestUtils.cs +++ b/test/Garnet.test/TestUtils.cs @@ -604,7 +604,7 @@ public static GarnetServerOptions GetGarnetServerOptions( tlsServerOptionsOverride: null, clusterTlsClientOptionsOverride: new SslClientAuthenticationOptions { - ClientCertificates = certificates ?? [new X509Certificate2(certFile, certPassword)], + ClientCertificates = certificates ?? [CertificateUtils.GetMachineCertificateByFile(certFile, certPassword)], TargetHost = "GarnetTest", AllowRenegotiation = false, RemoteCertificateValidationCallback = ValidateServerCertificate, @@ -714,7 +714,7 @@ public static ConfigurationOptions GetConfig( ( new SslClientAuthenticationOptions { - ClientCertificates = certificates ?? [new X509Certificate2(certFile, certPassword)], + ClientCertificates = certificates ?? [CertificateUtils.GetMachineCertificateByFile(certFile, certPassword)], TargetHost = "GarnetTest", AllowRenegotiation = false, RemoteCertificateValidationCallback = ValidateServerCertificate, @@ -731,7 +731,7 @@ public static GarnetClient GetGarnetClient(EndPoint endpoint = null, bool useTLS { sslOptions = new SslClientAuthenticationOptions { - ClientCertificates = [new X509Certificate2(certFile, certPassword)], + ClientCertificates = [CertificateUtils.GetMachineCertificateByFile(certFile, certPassword)], TargetHost = "GarnetTest", AllowRenegotiation = false, RemoteCertificateValidationCallback = ValidateServerCertificate, @@ -747,7 +747,7 @@ public static GarnetClientSession GetGarnetClientSession(bool useTLS = false, bo { sslOptions = new SslClientAuthenticationOptions { - ClientCertificates = [new X509Certificate2(certFile, certPassword)], + ClientCertificates = [CertificateUtils.GetMachineCertificateByFile(certFile, certPassword)], TargetHost = "GarnetTest", AllowRenegotiation = false, RemoteCertificateValidationCallback = ValidateServerCertificate, @@ -763,7 +763,7 @@ public static LightClientRequest CreateRequest(LightClient.OnResponseDelegateUns { sslOptions = new SslClientAuthenticationOptions { - ClientCertificates = [new X509Certificate2(certFile, certPassword)], + ClientCertificates = [CertificateUtils.GetMachineCertificateByFile(certFile, certPassword)], TargetHost = "GarnetTest", AllowRenegotiation = false, RemoteCertificateValidationCallback = ValidateServerCertificate,