From 0a439885e82d66b6b4dac02980aa4ade61e8a7ba Mon Sep 17 00:00:00 2001 From: Amer Jusupovic <32405726+amerjusupovic@users.noreply.github.com> Date: Thu, 25 Jul 2024 10:22:18 -0700 Subject: [PATCH 1/2] Use GitHub workflow for PR builds (#582) * add ci.yml for testing * remove comments * fix pull request syntax * fix codeql version * fix codeql, test failing pipeline * revert test change * add security events write permission * update publish tests path * update task versions * update task versions * remove exit 0 for tests * remove unused pipelines --- .github/workflows/ci.yml | 53 +++++++++ .pipelines/OneBranch.Official.yml | 175 ------------------------------ .pipelines/windows-buddy.yml | 125 --------------------- 3 files changed, 53 insertions(+), 300 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .pipelines/OneBranch.Official.yml delete mode 100644 .pipelines/windows-buddy.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..af9b1d22 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,53 @@ +name: AppConfiguration-DotnetProvider CI + +on: + push: + branches: + - main + - preview + - release/* + pull_request: + branches: + - main + - preview + - release/* + +permissions: + security-events: write + +jobs: + build: + runs-on: windows-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Install .NET + run: pwsh build/install-dotnet.ps1 -RestoreOnly + + - name: Restore + run: pwsh build.ps1 -RestoreOnly + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: 'csharp' + + - name: Dotnet Build + run: pwsh build.ps1 + + - name: Dotnet Pack + run: pwsh pack.ps1 + + - name: Dotnet Test + run: pwsh test.ps1 + + - name: Publish Test Results + uses: actions/upload-artifact@v4 + with: + name: Unit Test Results + path: ${{ github.workspace }}/tests/**/*.trx + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml deleted file mode 100644 index 1297da99..00000000 --- a/.pipelines/OneBranch.Official.yml +++ /dev/null @@ -1,175 +0,0 @@ -trigger: none - -parameters: # parameters are shown up in ADO UI in a build queue time -- name: 'debug' - displayName: 'Enable debug output' - type: boolean - default: false - -variables: - CDP_DEFINITION_BUILD_COUNT: $[counter('', 0)] # needed for onebranch.pipeline.version task - system.debug: ${{ parameters.debug }} - ENABLE_PRS_DELAYSIGN: 1 - ROOT: $(Build.SourcesDirectory) - REPOROOT: $(Build.SourcesDirectory) - OUTPUTROOT: $(REPOROOT)\out - CDP_USER_SOURCE_FOLDER_CONTAINER_PATH: $(Build.SourcesDirectory) - CDP_DEFINITION_BUILD_COUNT_DAY: $[counter(format('{0:yyyyMMdd}', pipeline.startTime), 1)] - CDP_DEFINITION_BUILD_COUNT_MONTH: $[counter(format('{0:yyyyMM}', pipeline.startTime), 1)] - CDP_DEFINITION_BUILD_COUNT_YEAR: $[counter(format('{0:yyyy}', pipeline.startTime), 1)] - NUGET_XMLDOC_MODE: none - - # Docker image which is used to build the project - WindowsContainerImage: 'onebranch.azurecr.io/windows/ltsc2019/vse2022:latest' - -resources: - repositories: - - repository: templates - type: git - name: OneBranch.Pipelines/GovernedTemplates - ref: refs/heads/main - -extends: - template: v2/OneBranch.Official.CrossPlat.yml@templates - parameters: - cloudvault: - enabled: false - globalSdl: - tsa: - enabled: false # onebranch publish all sdl results to TSA. If TSA is disabled all SDL tools will forced into 'break' build mode. - # credscan: - # suppressionsFile: $(Build.SourcesDirectory)\.config\CredScanSuppressions.json - binskim: - break: true # always break the build on binskim issues in addition to TSA upload - policheck: - break: true # always break the build on policheck issues. You can disable it by setting to 'false' - # baseline: - # baselineFile: $(Build.SourcesDirectory)\.gdn\global.gdnbaselines - cg: - failOnAlert: false - - stages: - - stage: build - jobs: - - job: main - pool: - type: windows - - variables: - ob_outputDirectory: '$(REPOROOT)\out' # this directory is uploaded to pipeline artifacts, reddog and cloudvault - ob_sdl_binskim_break: true - ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/master') }}: # conditionally enable symbolsPublishing for master branch only - ob_symbolsPublishing_enabled: true - # ob_sdl_baseline_baselineFile: $(Build.SourcesDirectory)\.gdn\build.official.gdnbaselines - # ob_sdl_codeSignValidation_excludes: -|**\*.js # Example -|**\*.js;-|**\Test*\** - ob_artifactBaseName: 'drop' - ob_sdl_cg_failOnAlert: false - - steps: - - task: CmdLine@2 - displayName: 'Install .NET' - inputs: - script: $(Build.SourcesDirectory)\build\CallPowerShell.cmd build/install-dotnet.ps1 -RestoreOnly - workingDirectory: '$(Build.SourcesDirectory)' - - - task: CmdLine@2 - displayName: 'Restore' - inputs: - script: $(Build.SourcesDirectory)\build\CallPowerShell.cmd build.ps1 -RestoreOnly - workingDirectory: '$(Build.SourcesDirectory)' - - - task: onebranch.pipeline.version@1 # generates automatic version - displayName: 'Setup BuildNumber' - inputs: - system: 'BuildRevision' - major: '1' - minor: '0' - name: 'Azconfig-DotnetProvider' - # exclude_commit: true - - - - - task: CmdLine@2 - displayName: 'Dotnet Build' - inputs: - script: $(Build.SourcesDirectory)\build\CallPowerShell.cmd build.ps1 - workingDirectory: '$(Build.SourcesDirectory)' - - - task: CopyFiles@2 - inputs: - SourceFolder: '$(Build.SourcesDirectory)\buildlogs' - Contents: | - **/* - TargetFolder: '$(Build.SourcesDirectory)\out\outputs\build\Build Logs' - - - - - task: onebranch.pipeline.signing@1 - displayName: 'Signing' - inputs: - command: 'sign' - signing_environment: 'azure-ado' - signing_profile: 'external_distribution ' - files_to_sign: '*/bin/Release/**/*' - search_root: '$(Build.SourcesDirectory)\src' - - - - task: CopyFiles@2 - inputs: - SourceFolder: '$(Build.SourcesDirectory)\src' - Contents: | - */bin/Release/**/* - TargetFolder: '$(Build.SourcesDirectory)\out\outputs\build\Binaries' - - - task: CmdLine@2 - displayName: 'Dotnet Pack' - inputs: - script: $(Build.SourcesDirectory)\build\CallPowerShell.cmd pack.ps1 - workingDirectory: '$(Build.SourcesDirectory)' - - - task: CopyFiles@2 - inputs: - SourceFolder: '$(Build.SourcesDirectory)\buildlogs' - Contents: | - **/* - TargetFolder: '$(Build.SourcesDirectory)\out\outputs\package\Build Logs' - - - - - task: onebranch.pipeline.signing@1 - displayName: 'Signing' - inputs: - command: 'sign' - signing_environment: 'azure-ado' - signing_profile: 'external_distribution ' - files_to_sign: '*/bin/PackageOutput/**/*.nupkg' - search_root: '$(Build.SourcesDirectory)\src' - - - - task: CopyFiles@2 - inputs: - SourceFolder: '$(Build.SourcesDirectory)\src' - Contents: | - */bin/PackageOutput/**/*.nupkg - TargetFolder: '$(Build.SourcesDirectory)\out\outputs\package\Packages' - - - task: CmdLine@2 - displayName: 'Dotnet Test' - inputs: - script: '$(Build.SourcesDirectory)\build/CallPowerShell.cmd test.ps1|| exit /b 0' - workingDirectory: '$(Build.SourcesDirectory)' - - - task: CopyFiles@2 - inputs: - SourceFolder: '$(Build.SourcesDirectory)\tests' - Contents: '**/*.trx' - TargetFolder: '$(Build.SourcesDirectory)\out\outputs\test\_post_command__run_log_alerts_schedular_tests\_testresults' - - - task: PublishTestResults@2 - displayName: 'Unit Tests' - inputs: - testResultsFormat: 'vstest' - testResultsFiles: '**/*.trx' - searchFolder: '' - failTaskOnFailedTests: True - testRunTitle: Unit Tests \ No newline at end of file diff --git a/.pipelines/windows-buddy.yml b/.pipelines/windows-buddy.yml deleted file mode 100644 index b9dcd260..00000000 --- a/.pipelines/windows-buddy.yml +++ /dev/null @@ -1,125 +0,0 @@ - -pr: -- main -- preview -- release/* - -trigger: -- none - -parameters: # parameters are shown up in ADO UI in a build queue time -- name: 'debug' - displayName: 'Enable debug output' - type: boolean - default: false - -jobs: -- job: main - pool: - type: windows - isCustom: true - name: Azure Pipelines - vmImage: 'windows-latest' - - variables: - Codeql.Enabled: true - - steps: - - task: AntiMalware@4 - inputs: - InputType: 'Basic' - ScanType: 'CustomScan' - FileDirPath: '$(Build.StagingDirectory)' - TreatSignatureUpdateFailureAs: 'Warning' - SignatureFreshness: 'UpToDate' - TreatStaleSignatureAs: 'Error' - - - task: CredScan@3 - - - task: nuget-security-analysis@0 - - - task: CmdLine@2 - displayName: 'Install .NET' - inputs: - script: build\CallPowerShell.cmd build/install-dotnet.ps1 -RestoreOnly - workingDirectory: '$(Build.SourcesDirectory)' - - - task: CmdLine@2 - displayName: 'Restore' - inputs: - script: $(Build.SourcesDirectory)\build\CallPowerShell.cmd build.ps1 -RestoreOnly - workingDirectory: '$(Build.SourcesDirectory)' - - - task: CodeQL3000Init@0 - displayName: 'Initialize CodeQL' - - - task: CmdLine@2 - displayName: 'Dotnet Build' - inputs: - script: $(Build.SourcesDirectory)\build\CallPowerShell.cmd build.ps1 - workingDirectory: '$(Build.SourcesDirectory)' - - - task: CopyFiles@2 - inputs: - SourceFolder: '$(Build.SourcesDirectory)\buildlogs' - Contents: | - **/* - TargetFolder: '$(Build.SourcesDirectory)\out\outputs\build\Build Logs' - - - task: CmdLine@2 - displayName: 'Dotnet Pack' - inputs: - script: $(Build.SourcesDirectory)\build\CallPowerShell.cmd pack.ps1 - workingDirectory: '$(Build.SourcesDirectory)' - - - task: CopyFiles@2 - inputs: - SourceFolder: '$(Build.SourcesDirectory)\buildlogs' - Contents: | - **/* - TargetFolder: '$(Build.SourcesDirectory)\out\outputs\package\Build Logs' - - - task: CmdLine@2 - displayName: 'Dotnet Test' - inputs: - script: '$(Build.SourcesDirectory)\build/CallPowerShell.cmd test.ps1|| exit /b 0' - workingDirectory: '$(Build.SourcesDirectory)' - - - task: CopyFiles@2 - inputs: - SourceFolder: '$(Build.SourcesDirectory)\tests' - Contents: '**/*.trx' - TargetFolder: '$(Build.SourcesDirectory)\out\outputs\test\_post_command__run_log_alerts_schedular_tests\_testresults' - - - task: PublishTestResults@2 - displayName: 'Unit Tests' - inputs: - testResultsFormat: 'vstest' - testResultsFiles: '**/*.trx' - searchFolder: '' - failTaskOnFailedTests: True - testRunTitle: Unit Tests - - - task: ComponentGovernanceComponentDetection@0 - displayName: "Component Detection" - inputs: - scanType: 'Register' - verbosity: 'Verbose' - alertWarningLevel: 'High' - - - task: BinSkim@4 - inputs: - InputType: 'Basic' - Function: 'analyze' - TargetPattern: 'guardianGlob' - AnalyzeTargetGlob: '$(Build.SourcesDirectory)\**.dll;$(Build.SourcesDirectory)\**.exe;' - - - task: PublishPipelineArtifact@1 - displayName: 'Publish Artifacts' - inputs: - targetPath: '$(Build.SourcesDirectory)\out\outputs' - artifact: 'drop' - publishLocation: 'pipeline' - - - task: CodeQL3000Finalize@0 - displayName: 'Finalize CodeQL' From 08e5930e24c4ebb75e5542f6a736175e2c03cb9e Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Fri, 26 Jul 2024 13:01:42 +0800 Subject: [PATCH 2/2] Add linting rule (#571) * add linting rule * remove unused package * fix format issue & enforce format check * fix format issue * fix format issue * add directory props * merge * update --- .editorconfig | 39 ++ Directory.Build.props | 7 + .../ConfigStoreDemo/ConfigStoreDemo.csproj | 7 +- .../ConfigStoreDemo/Pages/About.cshtml.cs | 4 - .../ConfigStoreDemo/Pages/Contact.cshtml.cs | 4 - .../ConfigStoreDemo/Pages/Error.cshtml.cs | 6 +- .../ConsoleApplication.csproj | 2 +- ...t.Azure.AppConfiguration.AspNetCore.csproj | 2 +- ...e.AppConfiguration.Functions.Worker.csproj | 2 +- .../AssemblyInfo.cs | 2 +- .../AzureAppConfigurationProvider.cs | 8 +- .../AzureAppConfigurationRefreshOptions.cs | 2 +- .../AzureAppConfigurationSource.cs | 3 +- .../AzureKeyVaultKeyValueAdapter.cs | 2 +- .../ConfigurationClientManager.cs | 16 +- .../Constants/HttpStatusCodes.cs | 2 +- .../Constants/RequestTracingConstants.cs | 2 +- .../Exceptions/KeyVaultReferenceException.cs | 5 +- .../ConfigurationClientExtensions.cs | 2 +- .../Extensions/EventGridEventExtensions.cs | 2 +- .../Extensions/ListExtensions.cs | 2 +- .../FeatureManagement/ClientFilter.cs | 2 +- .../FeatureManagement/FeatureConditions.cs | 2 +- .../FeatureManagement/FeatureFilterTracing.cs | 2 +- .../FeatureManagement/FeatureFlag.cs | 2 +- .../FeatureManagement/FeatureFlagOptions.cs | 2 +- .../FeatureManagementKeyValueAdapter.cs | 2 +- .../FeatureManagement/JsonFlattener.cs | 2 + .../JsonKeyValueAdapter.cs | 2 +- ...Configuration.AzureAppConfiguration.csproj | 5 +- .../PushNotification.cs | 5 +- .../SrvLookupClient.cs | 6 +- .../TracingUtils.cs | 4 +- .../AzureAppConfigurationExtensionsTests.cs | 5 +- .../RefreshMiddlewareTests.cs | 2 - .../TestHelper.cs | 5 +- ...ts.AzureAppConfiguration.AspNetCore.csproj | 3 +- ...reAppConfiguration.Functions.Worker.csproj | 2 +- .../Azure.Core.Testing/MockRequest.cs | 1 + .../Azure.Core.Testing/TaskExtensions.cs | 1 - .../ConnectTests.cs | 2 - .../FailoverTests.cs | 4 +- .../FeatureManagementTests.cs | 7 +- .../KeyVaultReferenceTests.cs | 50 +-- .../LoggingTests.cs | 5 +- tests/Tests.AzureAppConfiguration/MapTests.cs | 55 ++- .../MockedConfigurationClientManager.cs | 4 +- .../PushRefreshTests.cs | 414 +++++++++--------- .../RefreshTests.cs | 16 +- .../Tests.AzureAppConfiguration/TestHelper.cs | 3 + .../Tests.AzureAppConfiguration.csproj | 3 +- tests/Tests.AzureAppConfiguration/Tests.cs | 2 +- 52 files changed, 404 insertions(+), 337 deletions(-) create mode 100644 .editorconfig create mode 100644 Directory.Build.props diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..233e6128 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,39 @@ +# editorconfig.org + +# top-most EditorConfig file +root = true + +## Default settings ## +[*] +insert_final_newline = true +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true + +## Formatting rule ## +# https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055 +dotnet_diagnostic.IDE0055.severity = error + +# 'Using' directive preferences +dotnet_sort_system_directives_first = false + +# New line preferences +dotnet_diagnostic.IDE2002.severity = error +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false +dotnet_diagnostic.IDE2004.severity = error +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = false +dotnet_diagnostic.IDE2005.severity = error +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = false +dotnet_diagnostic.IDE2006.severity = error +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = false +dotnet_diagnostic.IDE2000.severity = error +dotnet_style_allow_multiple_blank_lines_experimental = false +dotnet_diagnostic.IDE2003.severity = error +dotnet_style_allow_statement_immediately_after_block_experimental = false + +[*.csproj] +indent_size = 2 +charset = utf-8 + +[*.json] +indent_size = 2 \ No newline at end of file diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 00000000..e1220a8d --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,7 @@ + + + + True + + + \ No newline at end of file diff --git a/examples/ConfigStoreDemo/ConfigStoreDemo.csproj b/examples/ConfigStoreDemo/ConfigStoreDemo.csproj index caab5885..a4845d9f 100644 --- a/examples/ConfigStoreDemo/ConfigStoreDemo.csproj +++ b/examples/ConfigStoreDemo/ConfigStoreDemo.csproj @@ -1,17 +1,22 @@ - + + false net8.0 + + + Always + diff --git a/examples/ConfigStoreDemo/Pages/About.cshtml.cs b/examples/ConfigStoreDemo/Pages/About.cshtml.cs index dbbdbbf1..ab5a5b85 100644 --- a/examples/ConfigStoreDemo/Pages/About.cshtml.cs +++ b/examples/ConfigStoreDemo/Pages/About.cshtml.cs @@ -1,10 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. // -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.RazorPages; namespace Microsoft.Extensions.Configuration.AzureAppConfiguration.Examples.ConfigStoreDemo.Pages diff --git a/examples/ConfigStoreDemo/Pages/Contact.cshtml.cs b/examples/ConfigStoreDemo/Pages/Contact.cshtml.cs index 846a4cbc..64453907 100644 --- a/examples/ConfigStoreDemo/Pages/Contact.cshtml.cs +++ b/examples/ConfigStoreDemo/Pages/Contact.cshtml.cs @@ -1,10 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. // -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.RazorPages; namespace Microsoft.Extensions.Configuration.AzureAppConfiguration.Examples.ConfigStoreDemo.Pages diff --git a/examples/ConfigStoreDemo/Pages/Error.cshtml.cs b/examples/ConfigStoreDemo/Pages/Error.cshtml.cs index a75e869d..61725493 100644 --- a/examples/ConfigStoreDemo/Pages/Error.cshtml.cs +++ b/examples/ConfigStoreDemo/Pages/Error.cshtml.cs @@ -1,12 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. // -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.RazorPages; +using System.Diagnostics; namespace Microsoft.Extensions.Configuration.AzureAppConfiguration.Examples.ConfigStoreDemo.Pages { diff --git a/examples/ConsoleApplication/ConsoleApplication.csproj b/examples/ConsoleApplication/ConsoleApplication.csproj index bd4756fa..0b63a9e4 100644 --- a/examples/ConsoleApplication/ConsoleApplication.csproj +++ b/examples/ConsoleApplication/ConsoleApplication.csproj @@ -1,4 +1,4 @@ - + false diff --git a/src/Microsoft.Azure.AppConfiguration.AspNetCore/Microsoft.Azure.AppConfiguration.AspNetCore.csproj b/src/Microsoft.Azure.AppConfiguration.AspNetCore/Microsoft.Azure.AppConfiguration.AspNetCore.csproj index 5c33c144..f11142cc 100644 --- a/src/Microsoft.Azure.AppConfiguration.AspNetCore/Microsoft.Azure.AppConfiguration.AspNetCore.csproj +++ b/src/Microsoft.Azure.AppConfiguration.AspNetCore/Microsoft.Azure.AppConfiguration.AspNetCore.csproj @@ -1,4 +1,4 @@ - + diff --git a/src/Microsoft.Azure.AppConfiguration.Functions.Worker/Microsoft.Azure.AppConfiguration.Functions.Worker.csproj b/src/Microsoft.Azure.AppConfiguration.Functions.Worker/Microsoft.Azure.AppConfiguration.Functions.Worker.csproj index 43d8d181..6ae5ccb4 100644 --- a/src/Microsoft.Azure.AppConfiguration.Functions.Worker/Microsoft.Azure.AppConfiguration.Functions.Worker.csproj +++ b/src/Microsoft.Azure.AppConfiguration.Functions.Worker/Microsoft.Azure.AppConfiguration.Functions.Worker.csproj @@ -1,4 +1,4 @@ - + diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AssemblyInfo.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AssemblyInfo.cs index ded5fff4..f9522baf 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AssemblyInfo.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AssemblyInfo.cs @@ -30,4 +30,4 @@ "c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654" + "753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46" + "ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484c" + -"f7045cc7")] \ No newline at end of file +"f7045cc7")] diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationProvider.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationProvider.cs index 0868ea14..d6613246 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationProvider.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationProvider.cs @@ -125,6 +125,7 @@ public AzureAppConfigurationProvider(IConfigurationClientManager configClientMan requestTracingDisabled = Environment.GetEnvironmentVariable(RequestTracingConstants.RequestTracingDisabledEnvironmentVariable); } catch (SecurityException) { } + _requestTracingEnabled = bool.TryParse(requestTracingDisabled, out bool tracingDisabled) ? !tracingDisabled : true; if (_requestTracingEnabled) @@ -208,7 +209,7 @@ public async Task RefreshAsync(CancellationToken cancellationToken) // // Filter clients based on their backoff status - clients = clients.Where(client => + clients = clients.Where(client => { Uri endpoint = _configClientManager.GetEndpointForClient(client); @@ -320,7 +321,8 @@ await CallWithRequestTracing( refreshAll = true; break; } - } else + } + else { logDebugBuilder.AppendLine(LogHelper.BuildKeyValueReadMessage(change.ChangeType, change.Key, change.Label, endpoint.ToString())); } @@ -697,7 +699,7 @@ private async Task TryInitializeAsync(IEnumerable cli return false; } - + throw; } diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationRefreshOptions.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationRefreshOptions.cs index 5297507c..7522896e 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationRefreshOptions.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationRefreshOptions.cs @@ -14,7 +14,7 @@ public class AzureAppConfigurationRefreshOptions { internal TimeSpan CacheExpirationInterval { get; private set; } = RefreshConstants.DefaultCacheExpirationInterval; internal ISet RefreshRegistrations = new HashSet(); - + /// /// Register the specified individual key-value to be refreshed when the configuration provider's triggers a refresh. /// The instance can be obtained by calling . diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationSource.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationSource.cs index 71a5f480..09544029 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationSource.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationSource.cs @@ -12,7 +12,8 @@ internal class AzureAppConfigurationSource : IConfigurationSource public AzureAppConfigurationSource(Action optionsInitializer, bool optional = false) { - _optionsProvider = () => { + _optionsProvider = () => + { var options = new AzureAppConfigurationOptions(); optionsInitializer(options); return options; diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureKeyVaultReference/AzureKeyVaultKeyValueAdapter.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureKeyVaultReference/AzureKeyVaultKeyValueAdapter.cs index dd5cddbc..9580a1cc 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureKeyVaultReference/AzureKeyVaultKeyValueAdapter.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureKeyVaultReference/AzureKeyVaultKeyValueAdapter.cs @@ -138,4 +138,4 @@ private string ParseSecretReferenceUri(ConfigurationSetting setting) return secretRefUri; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/ConfigurationClientManager.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/ConfigurationClientManager.cs index 9ae71d2a..06f916b0 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/ConfigurationClientManager.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/ConfigurationClientManager.cs @@ -146,7 +146,7 @@ public void RefreshClients() { DateTimeOffset now = DateTimeOffset.UtcNow; - if (_replicaDiscoveryEnabled && + if (_replicaDiscoveryEnabled && now >= _lastFallbackClientRefreshAttempt + MinimalClientRefreshInterval) { _lastFallbackClientRefreshAttempt = now; @@ -262,9 +262,9 @@ private async Task RefreshFallbackClients(CancellationToken cancellationToken) // Honor with the DNS based service discovery protocol, but shuffle the results first to ensure hosts can be picked randomly, // Srv lookup does retrieve trailing dot in the host name, just trim it. - IEnumerable OrderedHosts = srvTargetHosts.Any() ? - srvTargetHosts.ToList().Shuffle().SortSrvRecords().Select(r => $"{r.Target.Value.TrimEnd('.')}") : - Enumerable.Empty(); + IEnumerable OrderedHosts = srvTargetHosts.Any() + ? srvTargetHosts.ToList().Shuffle().SortSrvRecords().Select(r => $"{r.Target.Value.TrimEnd('.')}") + : Enumerable.Empty(); foreach (string host in OrderedHosts) { @@ -274,9 +274,9 @@ private async Task RefreshFallbackClients(CancellationToken cancellationToken) { var targetEndpoint = new Uri($"https://{host}"); - var configClient = _credential == null ? - new ConfigurationClient(ConnectionStringUtils.Build(targetEndpoint, _id, _secret), _clientOptions) : - new ConfigurationClient(targetEndpoint, _credential, _clientOptions); + var configClient = _credential == null + ? new ConfigurationClient(ConnectionStringUtils.Build(targetEndpoint, _id, _secret), _clientOptions) + : new ConfigurationClient(targetEndpoint, _credential, _clientOptions); newDynamicClients.Add(new ConfigurationClientWrapper(targetEndpoint, configClient)); } @@ -320,7 +320,7 @@ internal bool IsValidEndpoint(string hostName) public void Dispose() { - if (!_isDisposed) + if (!_isDisposed) { _cancellationTokenSource.Cancel(); diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Constants/HttpStatusCodes.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Constants/HttpStatusCodes.cs index 76de0b48..823895bd 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Constants/HttpStatusCodes.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Constants/HttpStatusCodes.cs @@ -9,4 +9,4 @@ internal class HttpStatusCodes // This constant is necessary because System.Net.HttpStatusCode.TooManyRequests is only available in netstandard2.1 and higher. public static readonly int TooManyRequests = 429; } -} \ No newline at end of file +} diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Constants/RequestTracingConstants.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Constants/RequestTracingConstants.cs index f1da875b..6ff59fa1 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Constants/RequestTracingConstants.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Constants/RequestTracingConstants.cs @@ -10,7 +10,7 @@ internal class RequestTracingConstants public const string AzureWebAppEnvironmentVariable = "WEBSITE_SITE_NAME"; public const string ContainerAppEnvironmentVariable = "CONTAINER_APP_NAME"; public const string KubernetesEnvironmentVariable = "KUBERNETES_PORT"; - + public const string AspNetCoreEnvironmentVariable = "ASPNETCORE_ENVIRONMENT"; public const string DotNetCoreEnvironmentVariable = "DOTNET_ENVIRONMENT"; public const string DevelopmentEnvironmentName = "Development"; diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Exceptions/KeyVaultReferenceException.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Exceptions/KeyVaultReferenceException.cs index 58046c93..7d549a06 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Exceptions/KeyVaultReferenceException.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Exceptions/KeyVaultReferenceException.cs @@ -20,7 +20,7 @@ public class KeyVaultReferenceException : Exception /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. /// public KeyVaultReferenceException(string message, Exception inner) - :base(string.Empty, inner) + : base(string.Empty, inner) { _message = message; } @@ -29,7 +29,7 @@ public KeyVaultReferenceException(string message, ///Gets a message that describes the current exception. ///Returns The error message that explains the reason for the exception, or an empty string(""). /// - public override string Message => $"{_message} ErrorCode:'{ErrorCode}' Key:'{Key}' Label:'{Label}' Etag:'{Etag}' SecretIdentifier:'{SecretIdentifier}'"; + public override string Message => $"{_message} ErrorCode:'{ErrorCode}' Key:'{Key}' Label:'{Label}' Etag:'{Etag}' SecretIdentifier:'{SecretIdentifier}'"; /// /// The key of the Key Vault reference that caused the exception. @@ -56,5 +56,4 @@ public KeyVaultReferenceException(string message, /// public string ErrorCode { get; set; } } - } diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Extensions/ConfigurationClientExtensions.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Extensions/ConfigurationClientExtensions.cs index 0e378f44..18c03178 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Extensions/ConfigurationClientExtensions.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Extensions/ConfigurationClientExtensions.cs @@ -116,7 +116,7 @@ public static async Task> GetKeyValueChangeCollectio await TracingUtils.CallWithRequestTracing(options.RequestTracingEnabled, RequestType.Watch, options.RequestTracingOptions, async () => { - await foreach(ConfigurationSetting setting in client.GetConfigurationSettingsAsync(selector, cancellationToken).ConfigureAwait(false)) + await foreach (ConfigurationSetting setting in client.GetConfigurationSettingsAsync(selector, cancellationToken).ConfigureAwait(false)) { if (!eTagMap.TryGetValue(setting.Key, out ETag etag) || !etag.Equals(setting.ETag)) { diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Extensions/EventGridEventExtensions.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Extensions/EventGridEventExtensions.cs index 7ac04ca9..ee904324 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Extensions/EventGridEventExtensions.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Extensions/EventGridEventExtensions.cs @@ -89,4 +89,4 @@ public static bool TryCreatePushNotification(this EventGridEvent eventGridEvent, return false; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Extensions/ListExtensions.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Extensions/ListExtensions.cs index 9be9b55a..99024c3c 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Extensions/ListExtensions.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Extensions/ListExtensions.cs @@ -65,4 +65,4 @@ public static void AppendUnique(this List items, T item) items.Add(item); } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/ClientFilter.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/ClientFilter.cs index 80aed990..12145cd7 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/ClientFilter.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/ClientFilter.cs @@ -11,4 +11,4 @@ internal class ClientFilter public JsonElement Parameters { get; set; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureConditions.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureConditions.cs index ec29c199..d1c23003 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureConditions.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureConditions.cs @@ -11,4 +11,4 @@ internal class FeatureConditions public string RequirementType { get; set; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureFilterTracing.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureFilterTracing.cs index 27b59205..deb6db49 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureFilterTracing.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureFilterTracing.cs @@ -29,7 +29,7 @@ internal class FeatureFilterTracing public bool UsesPercentageFilter { get; set; } = false; public bool UsesTimeWindowFilter { get; set; } = false; public bool UsesTargetingFilter { get; set; } = false; - + public bool UsesAnyFeatureFilter() { return UsesCustomFilter || UsesPercentageFilter || UsesTimeWindowFilter || UsesTargetingFilter; diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureFlag.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureFlag.cs index a26fb6cc..aaf38540 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureFlag.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureFlag.cs @@ -12,4 +12,4 @@ internal class FeatureFlag public FeatureConditions Conditions { get; set; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureFlagOptions.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureFlagOptions.cs index 202f4055..c63fddc1 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureFlagOptions.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureFlagOptions.cs @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. // -using Microsoft.Extensions.Configuration.AzureAppConfiguration.Models; using Microsoft.Extensions.Configuration.AzureAppConfiguration.Extensions; +using Microsoft.Extensions.Configuration.AzureAppConfiguration.Models; using System; using System.Collections.Generic; using System.Linq; diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureManagementKeyValueAdapter.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureManagementKeyValueAdapter.cs index 5b0a6a96..058f353c 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureManagementKeyValueAdapter.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/FeatureManagementKeyValueAdapter.cs @@ -264,7 +264,7 @@ private FeatureConditions ParseFeatureConditions(ref Utf8JsonReader reader, stri default: reader.Skip(); - + break; } } diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/JsonFlattener.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/JsonFlattener.cs index 9974a933..fa5983c1 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/JsonFlattener.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/FeatureManagement/JsonFlattener.cs @@ -36,6 +36,7 @@ private void VisitJsonElement(JsonElement element) { VisitJsonProperty(property); } + break; case JsonValueKind.Array: @@ -45,6 +46,7 @@ private void VisitJsonElement(JsonElement element) VisitJsonElement(element[index]); ExitContext(); } + break; case JsonValueKind.String: diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/JsonKeyValueAdapter.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/JsonKeyValueAdapter.cs index 2c11d423..979811d7 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/JsonKeyValueAdapter.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/JsonKeyValueAdapter.cs @@ -16,7 +16,7 @@ namespace Microsoft.Extensions.Configuration.AzureAppConfiguration { internal class JsonKeyValueAdapter : IKeyValueAdapter { - private static readonly IEnumerable ExcludedJsonContentTypes = new[] + private static readonly IEnumerable ExcludedJsonContentTypes = new[] { FeatureManagementConstants.ContentType, KeyVaultConstants.ContentType diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Microsoft.Extensions.Configuration.AzureAppConfiguration.csproj b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Microsoft.Extensions.Configuration.AzureAppConfiguration.csproj index da78f0e9..a2cfca3c 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Microsoft.Extensions.Configuration.AzureAppConfiguration.csproj +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Microsoft.Extensions.Configuration.AzureAppConfiguration.csproj @@ -1,4 +1,5 @@ - + + @@ -50,5 +51,5 @@ true true - + diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/PushNotification.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/PushNotification.cs index e23d8bb4..1690645d 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/PushNotification.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/PushNotification.cs @@ -24,6 +24,5 @@ public class PushNotification /// The Type of Event which triggered the . /// public string EventType { get; set; } - - } -} \ No newline at end of file + } +} diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/SrvLookupClient.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/SrvLookupClient.cs index bcbdff75..74bad0b5 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/SrvLookupClient.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/SrvLookupClient.cs @@ -1,12 +1,12 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. // +using DnsClient; +using DnsClient.Protocol; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; -using DnsClient; -using DnsClient.Protocol; namespace Microsoft.Extensions.Configuration.AzureAppConfiguration { @@ -26,7 +26,7 @@ public SrvLookupClient() public async Task> QueryAsync(string host, CancellationToken cancellationToken) { string originSrvDns = $"{TcpOrigin}.{host}"; - + IEnumerable originRecords = await InternalQueryAsync(originSrvDns, cancellationToken).ConfigureAwait(false); if (originRecords == null || originRecords.Count() == 0) diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/TracingUtils.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/TracingUtils.cs index bbf8511c..2c8d9869 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/TracingUtils.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/TracingUtils.cs @@ -117,7 +117,7 @@ private static string CreateCorrelationContextHeader(RequestType requestType, Re { IList> correlationContextKeyValues = new List>(); IList correlationContextTags = new List(); - + correlationContextKeyValues.Add(new KeyValuePair(RequestTracingConstants.RequestTypeKey, Enum.GetName(typeof(RequestType), requestType))); if (requestTracingOptions.ReplicaCount > 0) @@ -167,7 +167,7 @@ private static string CreateCorrelationContextHeader(RequestType requestType, Re var sb = new StringBuilder(); - foreach (KeyValuePair kvp in correlationContextKeyValues) + foreach (KeyValuePair kvp in correlationContextKeyValues) { if (sb.Length > 0) { diff --git a/tests/Tests.AzureAppConfiguration.AspNetCore/AzureAppConfigurationExtensionsTests.cs b/tests/Tests.AzureAppConfiguration.AspNetCore/AzureAppConfigurationExtensionsTests.cs index 5c093d1a..2d4870f2 100644 --- a/tests/Tests.AzureAppConfiguration.AspNetCore/AzureAppConfigurationExtensionsTests.cs +++ b/tests/Tests.AzureAppConfiguration.AspNetCore/AzureAppConfigurationExtensionsTests.cs @@ -1,4 +1,7 @@ -using Microsoft.AspNetCore.Builder; +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +// +using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Moq; using System; diff --git a/tests/Tests.AzureAppConfiguration.AspNetCore/RefreshMiddlewareTests.cs b/tests/Tests.AzureAppConfiguration.AspNetCore/RefreshMiddlewareTests.cs index 934cd997..de752f03 100644 --- a/tests/Tests.AzureAppConfiguration.AspNetCore/RefreshMiddlewareTests.cs +++ b/tests/Tests.AzureAppConfiguration.AspNetCore/RefreshMiddlewareTests.cs @@ -9,9 +9,7 @@ using Moq; using System.Collections.Generic; using System.Linq; -using System.Threading; using Xunit; -using static Tests.AzureAppConfiguration.AspNetCore.TestHelper; namespace Tests.AzureAppConfiguration.AspNetCore { diff --git a/tests/Tests.AzureAppConfiguration.AspNetCore/TestHelper.cs b/tests/Tests.AzureAppConfiguration.AspNetCore/TestHelper.cs index a67e8127..500f3aa9 100644 --- a/tests/Tests.AzureAppConfiguration.AspNetCore/TestHelper.cs +++ b/tests/Tests.AzureAppConfiguration.AspNetCore/TestHelper.cs @@ -1,4 +1,7 @@ -using Azure; +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +// +using Azure; using Azure.Data.AppConfiguration; using Moq; using System; diff --git a/tests/Tests.AzureAppConfiguration.AspNetCore/Tests.AzureAppConfiguration.AspNetCore.csproj b/tests/Tests.AzureAppConfiguration.AspNetCore/Tests.AzureAppConfiguration.AspNetCore.csproj index a8cd3b51..f15c5eb7 100644 --- a/tests/Tests.AzureAppConfiguration.AspNetCore/Tests.AzureAppConfiguration.AspNetCore.csproj +++ b/tests/Tests.AzureAppConfiguration.AspNetCore/Tests.AzureAppConfiguration.AspNetCore.csproj @@ -1,4 +1,4 @@ - + net6.0;net7.0;net8.0 @@ -24,4 +24,5 @@ + diff --git a/tests/Tests.AzureAppConfiguration.Functions.Worker/Tests.AzureAppConfiguration.Functions.Worker.csproj b/tests/Tests.AzureAppConfiguration.Functions.Worker/Tests.AzureAppConfiguration.Functions.Worker.csproj index f5af5a3f..02f3f7e2 100644 --- a/tests/Tests.AzureAppConfiguration.Functions.Worker/Tests.AzureAppConfiguration.Functions.Worker.csproj +++ b/tests/Tests.AzureAppConfiguration.Functions.Worker/Tests.AzureAppConfiguration.Functions.Worker.csproj @@ -1,4 +1,4 @@ - + net6.0;net7.0;net8.0 diff --git a/tests/Tests.AzureAppConfiguration/Azure.Core.Testing/MockRequest.cs b/tests/Tests.AzureAppConfiguration/Azure.Core.Testing/MockRequest.cs index 443c8acb..d5ad0815 100644 --- a/tests/Tests.AzureAppConfiguration/Azure.Core.Testing/MockRequest.cs +++ b/tests/Tests.AzureAppConfiguration/Azure.Core.Testing/MockRequest.cs @@ -32,6 +32,7 @@ public override RequestContent Content { _headers.Remove("Content-Length"); } + base.Content = value; } } diff --git a/tests/Tests.AzureAppConfiguration/Azure.Core.Testing/TaskExtensions.cs b/tests/Tests.AzureAppConfiguration/Azure.Core.Testing/TaskExtensions.cs index 37d5d55f..ace8ebe2 100644 --- a/tests/Tests.AzureAppConfiguration/Azure.Core.Testing/TaskExtensions.cs +++ b/tests/Tests.AzureAppConfiguration/Azure.Core.Testing/TaskExtensions.cs @@ -27,7 +27,6 @@ public static Task TimeoutAfterDefault(this Task task, return task.TimeoutAfter(DefaultTimeout, filePath, lineNumber); } - public static async Task TimeoutAfter(this Task task, TimeSpan timeout, [CallerFilePath] string filePath = null, [CallerLineNumber] int lineNumber = default) diff --git a/tests/Tests.AzureAppConfiguration/ConnectTests.cs b/tests/Tests.AzureAppConfiguration/ConnectTests.cs index 22a1507a..6a8ddc8d 100644 --- a/tests/Tests.AzureAppConfiguration/ConnectTests.cs +++ b/tests/Tests.AzureAppConfiguration/ConnectTests.cs @@ -7,7 +7,6 @@ using Moq; using System; using System.Collections.Generic; -using System.Linq; using System.Threading; using System.Threading.Tasks; using Xunit; @@ -48,7 +47,6 @@ public void ConnectTests_ThrowsIfConnectNotInvoked() Assert.Throws(action); } - [Fact] public void ConnectTests_UsesParametersFromLatestConnectCall() { diff --git a/tests/Tests.AzureAppConfiguration/FailoverTests.cs b/tests/Tests.AzureAppConfiguration/FailoverTests.cs index e9a7a12a..25a1d6bf 100644 --- a/tests/Tests.AzureAppConfiguration/FailoverTests.cs +++ b/tests/Tests.AzureAppConfiguration/FailoverTests.cs @@ -72,7 +72,7 @@ public async Task FailOverTests_ReturnsAllClientsIfAllBackedOff() }); options.ReplicaDiscoveryEnabled = false; - + refresher = options.GetRefresher(); }); @@ -210,7 +210,7 @@ public async Task FailOverTests_BackoffStateIsUpdatedOnSuccessfulRequest() // Wait for client 1 backoff to end Thread.Sleep(2500); - + await refresher.RefreshAsync(); // The first client should have been called now with refresh after the backoff time ends diff --git a/tests/Tests.AzureAppConfiguration/FeatureManagementTests.cs b/tests/Tests.AzureAppConfiguration/FeatureManagementTests.cs index abcb7595..2b6a70a2 100644 --- a/tests/Tests.AzureAppConfiguration/FeatureManagementTests.cs +++ b/tests/Tests.AzureAppConfiguration/FeatureManagementTests.cs @@ -316,7 +316,7 @@ public class FeatureManagementTests eTag: new ETag("c3c231fd-39a0-4cb6-3237-4614474b92c1")) }; - List _featureFlagCollection = new List + List _featureFlagCollection = new List { ConfigurationModelFactory.ConfigurationSetting( key: FeatureManagementConstants.FeatureFlagMarker + "App1_Feature1", @@ -521,7 +521,6 @@ public async Task WatchesFeatureFlags() Assert.Equal("SuperUsers", config["FeatureManagement:MyFeature2:EnabledFor:0:Name"]); } - [Fact] public async Task SkipRefreshIfCacheNotExpired() { @@ -950,7 +949,7 @@ public void MultipleCallsToUseFeatureFlags() .Returns(() => { return new MockAsyncPageable(_featureFlagCollection.Where(s => - (s.Key.StartsWith(FeatureManagementConstants.FeatureFlagMarker + prefix1) && s.Label == label1) || + (s.Key.StartsWith(FeatureManagementConstants.FeatureFlagMarker + prefix1) && s.Label == label1) || (s.Key.StartsWith(FeatureManagementConstants.FeatureFlagMarker + prefix2) && s.Label == label2)).ToList()); }); @@ -1285,6 +1284,7 @@ public async Task ValidateCorrectFeatureFlagLoggedIfModifiedOrRemovedDuringRefre { informationalInvocation += s; } + if (args.Level == EventLevel.Verbose) { verboseInvocation += s; @@ -1467,6 +1467,7 @@ public async Task MapTransformFeatureFlagWithRefresh() } "; } + return new ValueTask(setting); }); refresher = options.GetRefresher(); diff --git a/tests/Tests.AzureAppConfiguration/KeyVaultReferenceTests.cs b/tests/Tests.AzureAppConfiguration/KeyVaultReferenceTests.cs index 9d4ce1e5..d8c832bf 100644 --- a/tests/Tests.AzureAppConfiguration/KeyVaultReferenceTests.cs +++ b/tests/Tests.AzureAppConfiguration/KeyVaultReferenceTests.cs @@ -186,7 +186,7 @@ public void NotSecretIdentifierURI() { configuration = builder.AddAzureAppConfiguration(options => { - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);; + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); options.ConfigureKeyVault(kv => kv.Register(mockSecretClient.Object)); }).Build(); }); @@ -212,7 +212,7 @@ public void UseSecret() var configuration = new ConfigurationBuilder() .AddAzureAppConfiguration(options => { - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);; + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); options.ConfigureKeyVault(kv => kv.Register(mockSecretClient.Object)); }) .Build(); @@ -237,7 +237,7 @@ public void UseCertificate() var configuration = new ConfigurationBuilder() .AddAzureAppConfiguration(options => { - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);; + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); options.ConfigureKeyVault(kv => kv.Register(mockSecretClient.Object)); }) .Build(); @@ -262,7 +262,7 @@ public void ThrowsWhenSecretNotFound() { new ConfigurationBuilder().AddAzureAppConfiguration(options => { - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);; + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); options.ConfigureKeyVault(kv => kv.Register(mockSecretClient.Object)); }).Build(); }); @@ -287,7 +287,7 @@ public void DisabledSecretIdentifier() { new ConfigurationBuilder().AddAzureAppConfiguration(options => { - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);; + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); options.ConfigureKeyVault(kv => kv.Register(mockSecretClient.Object)); }).Build(); }); @@ -309,7 +309,7 @@ public void WrongContentType() var configuration = new ConfigurationBuilder() .AddAzureAppConfiguration(options => { - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);; + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); options.ConfigureKeyVault(kv => kv.Register(mockSecretClient.Object)); }) .Build(); @@ -364,14 +364,13 @@ public void CancellationToken() { startupOptions.Timeout = TimeSpan.FromSeconds(5); }); - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);; + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); options.ConfigureKeyVault(kv => kv.Register(mockSecretClient.Object)); }) .Build(); }); } - [Fact] public void HasNoAccessToKeyVault() { @@ -389,7 +388,7 @@ public void HasNoAccessToKeyVault() { new ConfigurationBuilder().AddAzureAppConfiguration(options => { - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);; + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); options.ConfigureKeyVault(kv => kv.Register(mockSecretClient.Object)); }) .Build(); @@ -418,7 +417,7 @@ public void RegisterMultipleClients() var configuration = new ConfigurationBuilder() .AddAzureAppConfiguration(options => { - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);; + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); options.ConfigureKeyVault(kv => kv.Register(mockSecretClient1.Object) .Register(mockSecretClient2.Object)); }) @@ -441,7 +440,7 @@ public void ServerRequestIsMadeWhenDefaultCredentialIsSet() { new ConfigurationBuilder().AddAzureAppConfiguration(options => { - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);; + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); options.ConfigureKeyVault(kv => kv.SetCredential(new DefaultAzureCredential())); }) .Build(); @@ -469,7 +468,7 @@ public void ThrowsWhenNoMatchingSecretClientIsFound() new ConfigurationBuilder() .AddAzureAppConfiguration(options => { - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);; + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); options.ConfigureKeyVault(kv => kv.Register(mockSecretClient1.Object).Register(mockSecretClient2.Object)); }) .Build(); @@ -492,7 +491,7 @@ public void ThrowsWhenConfigureKeyVaultIsMissing() new ConfigurationBuilder() .AddAzureAppConfiguration(options => { - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);; + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); }) .Build(); }); @@ -515,7 +514,7 @@ public void DoesNotThrowKeyVaultExceptionWhenProviderIsOptional() new ConfigurationBuilder() .AddAzureAppConfiguration(options => { - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);; + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); options.Adapters = new List { mockKeyValueAdapter.Object }; }, optional: true) .Build(); @@ -532,7 +531,7 @@ public void CallsSecretResolverCallbackWhenNoMatchingSecretClientIsFound() IConfiguration config = new ConfigurationBuilder() .AddAzureAppConfiguration(options => { - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);; + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); options.ConfigureKeyVault(kv => { kv.SetSecretResolver((secretUri) => @@ -558,7 +557,7 @@ public void ThrowsWhenBothDefaultCredentialAndSecretResolverCallbackAreSet() { new ConfigurationBuilder().AddAzureAppConfiguration(options => { - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);; + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); options.ConfigureKeyVault(kv => { kv.SetSecretResolver((secretUri) => @@ -588,7 +587,7 @@ public void ThrowsWhenSecretResolverIsNull() { new ConfigurationBuilder().AddAzureAppConfiguration(options => { - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);; + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); options.ConfigureKeyVault(kv => { kv.SetSecretResolver(null); @@ -609,7 +608,7 @@ public void LastKeyVaultOptionsWinWithMultipleConfigureKeyVaultCalls() IConfiguration config = new ConfigurationBuilder() .AddAzureAppConfiguration(options => { - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);; + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); options.ConfigureKeyVault(kv => { kv.SetCredential(new DefaultAzureCredential()); @@ -644,7 +643,7 @@ public void DontUseSecretResolverCallbackWhenMatchingSecretClientIsPresent() var configuration = new ConfigurationBuilder() .AddAzureAppConfiguration(options => { - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);; + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); options.ConfigureKeyVault(kv => { kv.SetSecretResolver((secretUri) => @@ -672,7 +671,7 @@ public void ThrowsWhenSecretRefreshIntervalIsTooShort() { new ConfigurationBuilder().AddAzureAppConfiguration(options => { - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);; + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); options.ConfigureKeyVault(kv => { kv.SetSecretRefreshInterval(_kv.Key, TimeSpan.FromMilliseconds(10)); @@ -721,7 +720,7 @@ Response GetIfChanged(ConfigurationSetting setting, bool o var config = new ConfigurationBuilder() .AddAzureAppConfiguration(options => { - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);; + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); options.ConfigureKeyVault(kv => { @@ -794,7 +793,7 @@ Response GetIfChanged(ConfigurationSetting setting, bool o var config = new ConfigurationBuilder() .AddAzureAppConfiguration(options => { - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);; + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); options.ConfigureKeyVault(kv => { kv.Register(mockSecretClient.Object); @@ -847,7 +846,7 @@ public async Task SecretIsReloadedFromKeyVaultWhenCacheExpires() var config = new ConfigurationBuilder() .AddAzureAppConfiguration(options => { - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);; + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); options.ConfigureKeyVault(kv => { kv.Register(mockSecretClient.Object); @@ -890,7 +889,7 @@ public async Task SecretsWithDefaultRefreshInterval() var config = new ConfigurationBuilder() .AddAzureAppConfiguration(options => { - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);; + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); options.ConfigureKeyVault(kv => { kv.Register(mockSecretClient.Object); @@ -936,7 +935,7 @@ public async Task SecretsWithDifferentRefreshIntervals() var config = new ConfigurationBuilder() .AddAzureAppConfiguration(options => { - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);; + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); options.ConfigureKeyVault(kv => { kv.Register(mockSecretClient.Object); @@ -962,7 +961,6 @@ public async Task SecretsWithDifferentRefreshIntervals() mockSecretClient.Verify(client => client.GetSecretAsync(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(3)); } - [Fact] public void ThrowsWhenInvalidKeyVaultSecretReferenceJson() { diff --git a/tests/Tests.AzureAppConfiguration/LoggingTests.cs b/tests/Tests.AzureAppConfiguration/LoggingTests.cs index 489bb78e..04ddf3d9 100644 --- a/tests/Tests.AzureAppConfiguration/LoggingTests.cs +++ b/tests/Tests.AzureAppConfiguration/LoggingTests.cs @@ -9,7 +9,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.AzureAppConfiguration; using Microsoft.Extensions.Configuration.AzureAppConfiguration.AzureKeyVault; -using Microsoft.Extensions.Configuration.AzureAppConfiguration.Extensions; using Moq; using System; using System.Collections.Generic; @@ -132,7 +131,7 @@ public async Task ValidateUnauthorizedExceptionLoggedDuringRefresh() Assert.Equal("TestValue1", config["TestKey1"]); FirstKeyValue.Value = "newValue1"; - + Thread.Sleep(CacheExpirationTime); await refresher.TryRefreshAsync(); @@ -505,6 +504,7 @@ public async Task ValidateCorrectKeyValueLoggedDuringRefresh() { informationalInvocation += s; } + if (args.Level == EventLevel.Verbose) { verboseInvocation += s; @@ -558,6 +558,7 @@ public async Task ValidateCorrectKeyVaultSecretLoggedDuringRefresh() { informationalInvocation += s; } + if (args.Level == EventLevel.Verbose) { verboseInvocation += s; diff --git a/tests/Tests.AzureAppConfiguration/MapTests.cs b/tests/Tests.AzureAppConfiguration/MapTests.cs index ea5b45ca..88fdaa6e 100644 --- a/tests/Tests.AzureAppConfiguration/MapTests.cs +++ b/tests/Tests.AzureAppConfiguration/MapTests.cs @@ -1,19 +1,22 @@ -using Microsoft.Extensions.Configuration.AzureAppConfiguration; +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +// +using Azure; +using Azure.Core.Diagnostics; +using Azure.Core.Testing; +using Azure.Data.AppConfiguration; +using Azure.Security.KeyVault.Secrets; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Configuration.AzureAppConfiguration; +using Microsoft.Extensions.Configuration.AzureAppConfiguration.AzureKeyVault; +using Moq; using System; using System.Collections.Generic; -using Xunit; -using Azure.Data.AppConfiguration; -using Azure; -using Microsoft.Extensions.Configuration.AzureAppConfiguration.AzureKeyVault; +using System.Diagnostics.Tracing; using System.Linq; -using Azure.Core.Testing; -using Moq; using System.Threading; using System.Threading.Tasks; -using Azure.Security.KeyVault.Secrets; -using Azure.Core.Diagnostics; -using System.Diagnostics.Tracing; +using Xunit; namespace Tests.AzureAppConfiguration { @@ -71,6 +74,7 @@ public void MapTransformKeyValue() { setting.Value += " mapped"; } + return new ValueTask(setting); }).Map((setting) => { @@ -82,6 +86,7 @@ public void MapTransformKeyValue() { setting.Value += " second"; } + return new ValueTask(setting); }); }) @@ -113,16 +118,17 @@ public void MapTransformKeyVaultValueBeforeAdapters() options.ConfigureKeyVault(kv => kv.Register(mockSecretClient.Object)); options.Map((setting) => { - if (setting.ContentType != KeyVaultConstants.ContentType + "; charset=utf-8") - { - setting.Value = @" + if (setting.ContentType != KeyVaultConstants.ContentType + "; charset=utf-8") + { + setting.Value = @" { ""uri"":""https://keyvault-theclassics.vault.azure.net/certificates/TestCertificate"" }"; - setting.ContentType = KeyVaultConstants.ContentType + "; charset=utf-8"; - } - return new ValueTask(setting); - }); + setting.ContentType = KeyVaultConstants.ContentType + "; charset=utf-8"; + } + + return new ValueTask(setting); + }); }) .Build(); @@ -152,6 +158,7 @@ public async Task MapTransformWithRefresh() { setting.Value += " mapped"; } + return new ValueTask(setting); }).Map((setting) => { @@ -163,6 +170,7 @@ public async Task MapTransformWithRefresh() { setting.Value += " second"; } + return new ValueTask(setting); }); @@ -205,6 +213,7 @@ public async Task MapTransformSettingKeyWithRefresh() { setting.Key = "newTestKey1"; } + return new ValueTask(setting); }).Map((setting) => { @@ -212,6 +221,7 @@ public async Task MapTransformSettingKeyWithRefresh() { setting.Value += " changed"; } + return new ValueTask(setting); }); refresher = options.GetRefresher(); @@ -255,6 +265,7 @@ public async Task MapTransformSettingLabelWithRefresh() { setting.Label = "newLabel"; } + return new ValueTask(setting); }).Map((setting) => { @@ -262,6 +273,7 @@ public async Task MapTransformSettingLabelWithRefresh() { setting.Value += " changed"; } + return new ValueTask(setting); }); refresher = options.GetRefresher(); @@ -303,6 +315,7 @@ public async Task MapTransformSettingCreateDuplicateKeyWithRefresh() { setting.Key = "TestKey2"; } + return new ValueTask(setting); }).Map((setting) => { @@ -310,6 +323,7 @@ public async Task MapTransformSettingCreateDuplicateKeyWithRefresh() { setting.Value += " changed"; } + return new ValueTask(setting); }); refresher = options.GetRefresher(); @@ -356,6 +370,7 @@ public async Task MapCreateNewSettingWithRefresh() eTag: new ETag("changed"), contentType: "text"); } + return new ValueTask(setting); }); refresher = options.GetRefresher(); @@ -402,6 +417,7 @@ public void MapResolveKeyVaultReferenceThrowsExceptionInAdapter() { setting.Value = _secretValue; } + return new ValueTask(setting); }); refresher = options.GetRefresher(); @@ -426,7 +442,6 @@ public void MapAsyncResolveKeyVaultReference() .Returns((string name, string version, CancellationToken cancellationToken) => Task.FromResult((Response)new MockResponse(new KeyVaultSecret(name, _secretValue)))); - var config = new ConfigurationBuilder() .AddAzureAppConfiguration(options => { @@ -440,6 +455,7 @@ public void MapAsyncResolveKeyVaultReference() setting.Value = secret.Value; setting.ContentType = "text"; } + return setting; }); refresher = options.GetRefresher(); @@ -466,6 +482,7 @@ public async Task MapTransformSettingKeyWithLogAndRefresh() { informationalInvocation += s; } + if (args.Level == EventLevel.Verbose) { verboseInvocation += s; @@ -487,6 +504,7 @@ public async Task MapTransformSettingKeyWithLogAndRefresh() { setting.Key = "newTestKey1"; } + return new ValueTask(setting); }).Map((setting) => { @@ -494,6 +512,7 @@ public async Task MapTransformSettingKeyWithLogAndRefresh() { setting.Value += " changed"; } + return new ValueTask(setting); }); refresher = options.GetRefresher(); diff --git a/tests/Tests.AzureAppConfiguration/MockedConfigurationClientManager.cs b/tests/Tests.AzureAppConfiguration/MockedConfigurationClientManager.cs index 7e6c03e1..0216d1be 100644 --- a/tests/Tests.AzureAppConfiguration/MockedConfigurationClientManager.cs +++ b/tests/Tests.AzureAppConfiguration/MockedConfigurationClientManager.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. // - using Azure.Data.AppConfiguration; using Microsoft.Extensions.Configuration.AzureAppConfiguration; using System; @@ -63,7 +62,8 @@ public IEnumerable GetClients() { var result = new List(); - foreach (var client in _clients) { + foreach (var client in _clients) + { result.Add(client.Client); } diff --git a/tests/Tests.AzureAppConfiguration/PushRefreshTests.cs b/tests/Tests.AzureAppConfiguration/PushRefreshTests.cs index 304a7e02..38b8c70f 100644 --- a/tests/Tests.AzureAppConfiguration/PushRefreshTests.cs +++ b/tests/Tests.AzureAppConfiguration/PushRefreshTests.cs @@ -19,58 +19,58 @@ namespace Tests.AzureAppConfiguration { public class PushRefreshTests - { + { static readonly Uri PrimaryResourceUri = new Uri(TestHelpers.PrimaryConfigStoreEndpoint.ToString() + "/kv/searchQuery1"); static readonly Uri SecondaryResourceUri = new Uri(TestHelpers.SecondaryConfigStoreEndpoint.ToString() + "/kv/searchQuery2"); List _kvCollection = new List - { - ConfigurationModelFactory.ConfigurationSetting( - key: "TestKey1", - label: "label", - value: "TestValue1", - eTag: new ETag("0a76e3d7-7ec1-4e37-883c-9ea6d0d89e63"), - contentType: "text"), - - ConfigurationModelFactory.ConfigurationSetting( - key: "TestKey2", - label: "label", - value: "TestValue2", - eTag: new ETag("31c38369-831f-4bf1-b9ad-79db56c8b989"), - contentType: "text"), - - ConfigurationModelFactory.ConfigurationSetting( - key: "TestKey3", - label: "label", - value: "TestValue3", - eTag: new ETag("bb203f2b-c113-44fc-995d-b933c2143339"), - contentType: "text"), - - ConfigurationModelFactory.ConfigurationSetting( - key: "TestKeyWithMultipleLabels", - label: "label1", - value: "TestValueForLabel1", - eTag: new ETag("bb203f2b-c113-44fc-995d-b933c2143339"), - contentType: "text"), - - ConfigurationModelFactory.ConfigurationSetting( - key: "TestKeyWithMultipleLabels", - label: "label2", - value: "TestValueForLabel2", - eTag: new ETag("bb203f2b-c113-44fc-995d-b933c2143339"), - contentType: "text") - }; + { + ConfigurationModelFactory.ConfigurationSetting( + key: "TestKey1", + label: "label", + value: "TestValue1", + eTag: new ETag("0a76e3d7-7ec1-4e37-883c-9ea6d0d89e63"), + contentType: "text"), + + ConfigurationModelFactory.ConfigurationSetting( + key: "TestKey2", + label: "label", + value: "TestValue2", + eTag: new ETag("31c38369-831f-4bf1-b9ad-79db56c8b989"), + contentType: "text"), + + ConfigurationModelFactory.ConfigurationSetting( + key: "TestKey3", + label: "label", + value: "TestValue3", + eTag: new ETag("bb203f2b-c113-44fc-995d-b933c2143339"), + contentType: "text"), + + ConfigurationModelFactory.ConfigurationSetting( + key: "TestKeyWithMultipleLabels", + label: "label1", + value: "TestValueForLabel1", + eTag: new ETag("bb203f2b-c113-44fc-995d-b933c2143339"), + contentType: "text"), + + ConfigurationModelFactory.ConfigurationSetting( + key: "TestKeyWithMultipleLabels", + label: "label2", + value: "TestValueForLabel2", + eTag: new ETag("bb203f2b-c113-44fc-995d-b933c2143339"), + contentType: "text") + }; List _pushNotificationList = new List { new PushNotification { ResourceUri = PrimaryResourceUri, - EventType = "eventType.KeyValueModified", + EventType = "eventType.KeyValueModified", SyncToken = "SyncToken1;sn=001", }, new PushNotification { ResourceUri = PrimaryResourceUri, - EventType = "eventType.KeyValueModified", + EventType = "eventType.KeyValueModified", SyncToken = "SyncToken2", }, new PushNotification { @@ -114,12 +114,12 @@ public class PushRefreshTests }, new PushNotification { ResourceUri = SecondaryResourceUri, - EventType = null, + EventType = null, SyncToken = "SyncToken2" }, new PushNotification { ResourceUri = PrimaryResourceUri, - EventType = "eventType.KeyValueDeleted", + EventType = "eventType.KeyValueDeleted", SyncToken = null }, new PushNotification { @@ -134,13 +134,13 @@ public class PushRefreshTests } }; - Dictionary _eventGridEvents = new Dictionary - { + Dictionary _eventGridEvents = new Dictionary + { { "sn;Vxujfidne", new EventGridEvent( "https://store1.resource.io/kv/searchQuery1", - "Microsoft.AppConfiguration.KeyValueModified", "2", + "Microsoft.AppConfiguration.KeyValueModified", "2", BinaryData.FromString("{\"key\":\"searchQuery1\",\"etag\":\"etagValue1\",\"syncToken\":\"sn;Vxujfidne\"}") ) }, @@ -158,7 +158,7 @@ public class PushRefreshTests "sn;Ttylmable", new EventGridEvent( "https://store1.resource.io/kv/searchQuery2", - "Microsoft.AppConfiguration.KeyValueDeleted", "2", + "Microsoft.AppConfiguration.KeyValueDeleted", "2", BinaryData.FromString("{\"key\":\"searchQuery1\",\"etag\":\"etagValue1\",\"syncToken\":\"sn;Ttylmable\"}") ) }, @@ -167,7 +167,7 @@ public class PushRefreshTests "sn;CRAle3342", new EventGridEvent( "https://store2.resource.io/kv/searchQuery2", - "Microsoft.AppConfiguration.KeyValueModified", "2", + "Microsoft.AppConfiguration.KeyValueModified", "2", BinaryData.FromString("{\"key\":\"searchQuery1\",\"etag\":\"etagValue1\",\"syncToken\":\"sn;CRAle3342\"}") ) }, @@ -185,25 +185,25 @@ public class PushRefreshTests Dictionary _invalidFormatEventGridEvents = new Dictionary { - { - "sn;Vxujfidne", - new EventGridEvent( - "https://store1.resource.io/kv/searchQuery1", - "Microsoft.AppConfiguration.KeyValueModified", "2", - BinaryData.FromString("\"key\":\"searchQuery1\",\"etag\":\"etagValue1\",\"syncToken\":\"sn;Vxujfidne\"}") - ) - }, - - { - "sn;AxRty78B", - new EventGridEvent( - "https://store1.resource.io/kv/searchQuery1", - "Microsoft.AppConfiguration.KeyValueModified", "2", - BinaryData.FromString("{\"key\":\"searchQuery1\",\"etag\":\"etagValue1\",\"syncToken\":\"sn;Vxujfidne\"") - ) - }, - - { + { + "sn;Vxujfidne", + new EventGridEvent( + "https://store1.resource.io/kv/searchQuery1", + "Microsoft.AppConfiguration.KeyValueModified", "2", + BinaryData.FromString("\"key\":\"searchQuery1\",\"etag\":\"etagValue1\",\"syncToken\":\"sn;Vxujfidne\"}") + ) + }, + + { + "sn;AxRty78B", + new EventGridEvent( + "https://store1.resource.io/kv/searchQuery1", + "Microsoft.AppConfiguration.KeyValueModified", "2", + BinaryData.FromString("{\"key\":\"searchQuery1\",\"etag\":\"etagValue1\",\"syncToken\":\"sn;Vxujfidne\"") + ) + }, + + { "sn;Ttylmable", new EventGridEvent( "https://store1.resource.io/kv/searchQuery2", @@ -227,18 +227,18 @@ public class PushRefreshTests [Fact] public void ValidatePushNotificationCreation() { - foreach (KeyValuePair eventGridAndSync in _eventGridEvents) + foreach (KeyValuePair eventGridAndSync in _eventGridEvents) { - string syncToken = eventGridAndSync.Key; - EventGridEvent eventGridEvent = eventGridAndSync.Value; + string syncToken = eventGridAndSync.Key; + EventGridEvent eventGridEvent = eventGridAndSync.Value; - Assert.True(eventGridEvent.TryCreatePushNotification(out PushNotification pushNotification)); + Assert.True(eventGridEvent.TryCreatePushNotification(out PushNotification pushNotification)); Assert.NotNull(pushNotification); Assert.Equal(eventGridEvent.EventType, pushNotification.EventType); Assert.Equal(eventGridEvent.Subject, pushNotification.ResourceUri.OriginalString); Assert.Equal(syncToken, pushNotification.SyncToken); } - } + } [Fact] public void InvalidPushNotificationCreation() @@ -252,145 +252,143 @@ public void InvalidPushNotificationCreation() } [Fact] - public void ProcessPushNotificationThrowsArgumentExceptions() + public void ProcessPushNotificationThrowsArgumentExceptions() { - var mockResponse = new Mock(); - var mockClient = GetMockConfigurationClient(); - - IConfigurationRefresher refresher = null; - - var config = new ConfigurationBuilder() - .AddAzureAppConfiguration(options => - { - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); - options.Select("*"); - options.ConfigureRefresh(refreshOptions => - { - refreshOptions.Register("TestKey1", "label") - .SetCacheExpiration(TimeSpan.FromDays(30)); - }); - refresher = options.GetRefresher(); - }) - .Build(); - - foreach (PushNotification invalidPushNotification in _invalidPushNotificationList) + var mockResponse = new Mock(); + var mockClient = GetMockConfigurationClient(); + + IConfigurationRefresher refresher = null; + + var config = new ConfigurationBuilder() + .AddAzureAppConfiguration(options => + { + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); + options.Select("*"); + options.ConfigureRefresh(refreshOptions => + { + refreshOptions.Register("TestKey1", "label") + .SetCacheExpiration(TimeSpan.FromDays(30)); + }); + refresher = options.GetRefresher(); + }) + .Build(); + + foreach (PushNotification invalidPushNotification in _invalidPushNotificationList) { - Action action = () => refresher.ProcessPushNotification(invalidPushNotification); - Assert.Throws(action); - } - - PushNotification nullPushNotification = null; - - Action nullAction = () => refresher.ProcessPushNotification(nullPushNotification); - Assert.Throws(nullAction); - } - - [Fact] - public async Task SyncTokenUpdatesCorrectNumberOfTimes() - { - // Arrange - var mockResponse = new Mock(); - var mockClient = GetMockConfigurationClient(); - - IConfigurationRefresher refresher = null; - var clientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); - - var config = new ConfigurationBuilder() - .AddAzureAppConfiguration(options => - { - options.ClientManager = clientManager; - options.Select("*"); - options.ConfigureRefresh(refreshOptions => - { - refreshOptions.Register("TestKey1", "label") - .SetCacheExpiration(TimeSpan.FromDays(30)); - }); - refresher = options.GetRefresher(); - }) - .Build(); - - foreach (PushNotification pushNotification in _pushNotificationList) - { - refresher.ProcessPushNotification(pushNotification, TimeSpan.FromSeconds(0)); - await refresher.RefreshAsync(); - } - - var validNotificationKVWatcherCount = 8; - var validEndpointCount = 4; - - mockClient.Verify(c => c.GetConfigurationSettingAsync(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(validNotificationKVWatcherCount)); - Assert.Equal(_pushNotificationList.Count, clientManager.UpdateSyncTokenCalled); - mockClient.Verify(c => c.UpdateSyncToken(It.IsAny()), Times.Exactly(validEndpointCount)); - } - - [Fact] - public async Task RefreshAsyncUpdatesConfig() - { - // Arrange - var mockResponse = new Mock(); - var mockClient = GetMockConfigurationClient(); - - IConfigurationRefresher refresher = null; - - var config = new ConfigurationBuilder() - .AddAzureAppConfiguration(options => - { - options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object);; - options.Select("*"); - options.ConfigureRefresh(refreshOptions => - { - refreshOptions.Register("TestKey1", "label") - .SetCacheExpiration(TimeSpan.FromDays(30)); - }); - refresher = options.GetRefresher(); - }) - .Build(); - - - Assert.Equal("TestValue1", config["TestKey1"]); - FirstKeyValue.Value = "newValue1"; - - refresher.ProcessPushNotification(_pushNotificationList.First(), TimeSpan.FromSeconds(0)); - await refresher.RefreshAsync(); - - Assert.Equal("newValue1", config["TestKey1"]); - } - - private Mock GetMockConfigurationClient() - { - var mockResponse = new Mock(); - var mockClient = new Mock(MockBehavior.Strict); - - Response GetTestKey(string key, string label, CancellationToken cancellationToken) - { - return Response.FromValue(TestHelpers.CloneSetting(_kvCollection.FirstOrDefault(s => s.Key == key && s.Label == label)), mockResponse.Object); - } - - Response GetIfChanged(ConfigurationSetting setting, bool onlyIfChanged, CancellationToken cancellationToken) - { - var newSetting = _kvCollection.FirstOrDefault(s => (s.Key == setting.Key && s.Label == setting.Label)); - var unchanged = (newSetting.Key == setting.Key && newSetting.Label == setting.Label && newSetting.Value == setting.Value); - var response = new MockResponse(unchanged ? 304 : 200); - return Response.FromValue(newSetting, response); - } - - // We don't actually select KV based on SettingSelector, we just return a deep copy of _kvCollection - mockClient.Setup(c => c.GetConfigurationSettingsAsync(It.IsAny(), It.IsAny())) - .Returns(() => - { - return new MockAsyncPageable(_kvCollection.Select(setting => TestHelpers.CloneSetting(setting)).ToList()); - }); - - mockClient.Setup(c => c.GetConfigurationSettingAsync(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync((Func>)GetTestKey); - - mockClient.Setup(c => c.GetConfigurationSettingAsync(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync((Func>)GetIfChanged); - - mockClient.Setup(c => c.UpdateSyncToken(It.IsAny())); - - return mockClient; - } - } + Action action = () => refresher.ProcessPushNotification(invalidPushNotification); + Assert.Throws(action); + } + + PushNotification nullPushNotification = null; + + Action nullAction = () => refresher.ProcessPushNotification(nullPushNotification); + Assert.Throws(nullAction); + } + [Fact] + public async Task SyncTokenUpdatesCorrectNumberOfTimes() + { + // Arrange + var mockResponse = new Mock(); + var mockClient = GetMockConfigurationClient(); + + IConfigurationRefresher refresher = null; + var clientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); + + var config = new ConfigurationBuilder() + .AddAzureAppConfiguration(options => + { + options.ClientManager = clientManager; + options.Select("*"); + options.ConfigureRefresh(refreshOptions => + { + refreshOptions.Register("TestKey1", "label") + .SetCacheExpiration(TimeSpan.FromDays(30)); + }); + refresher = options.GetRefresher(); + }) + .Build(); + + foreach (PushNotification pushNotification in _pushNotificationList) + { + refresher.ProcessPushNotification(pushNotification, TimeSpan.FromSeconds(0)); + await refresher.RefreshAsync(); + } + + var validNotificationKVWatcherCount = 8; + var validEndpointCount = 4; + + mockClient.Verify(c => c.GetConfigurationSettingAsync(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(validNotificationKVWatcherCount)); + Assert.Equal(_pushNotificationList.Count, clientManager.UpdateSyncTokenCalled); + mockClient.Verify(c => c.UpdateSyncToken(It.IsAny()), Times.Exactly(validEndpointCount)); + } + + [Fact] + public async Task RefreshAsyncUpdatesConfig() + { + // Arrange + var mockResponse = new Mock(); + var mockClient = GetMockConfigurationClient(); + + IConfigurationRefresher refresher = null; + + var config = new ConfigurationBuilder() + .AddAzureAppConfiguration(options => + { + options.ClientManager = TestHelpers.CreateMockedConfigurationClientManager(mockClient.Object); + options.Select("*"); + options.ConfigureRefresh(refreshOptions => + { + refreshOptions.Register("TestKey1", "label") + .SetCacheExpiration(TimeSpan.FromDays(30)); + }); + refresher = options.GetRefresher(); + }) + .Build(); + + Assert.Equal("TestValue1", config["TestKey1"]); + FirstKeyValue.Value = "newValue1"; + + refresher.ProcessPushNotification(_pushNotificationList.First(), TimeSpan.FromSeconds(0)); + await refresher.RefreshAsync(); + + Assert.Equal("newValue1", config["TestKey1"]); + } + + private Mock GetMockConfigurationClient() + { + var mockResponse = new Mock(); + var mockClient = new Mock(MockBehavior.Strict); + + Response GetTestKey(string key, string label, CancellationToken cancellationToken) + { + return Response.FromValue(TestHelpers.CloneSetting(_kvCollection.FirstOrDefault(s => s.Key == key && s.Label == label)), mockResponse.Object); + } + + Response GetIfChanged(ConfigurationSetting setting, bool onlyIfChanged, CancellationToken cancellationToken) + { + var newSetting = _kvCollection.FirstOrDefault(s => (s.Key == setting.Key && s.Label == setting.Label)); + var unchanged = (newSetting.Key == setting.Key && newSetting.Label == setting.Label && newSetting.Value == setting.Value); + var response = new MockResponse(unchanged ? 304 : 200); + return Response.FromValue(newSetting, response); + } + + // We don't actually select KV based on SettingSelector, we just return a deep copy of _kvCollection + mockClient.Setup(c => c.GetConfigurationSettingsAsync(It.IsAny(), It.IsAny())) + .Returns(() => + { + return new MockAsyncPageable(_kvCollection.Select(setting => TestHelpers.CloneSetting(setting)).ToList()); + }); + + mockClient.Setup(c => c.GetConfigurationSettingAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync((Func>)GetTestKey); + + mockClient.Setup(c => c.GetConfigurationSettingAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync((Func>)GetIfChanged); + + mockClient.Setup(c => c.UpdateSyncToken(It.IsAny())); + + return mockClient; + } + } } diff --git a/tests/Tests.AzureAppConfiguration/RefreshTests.cs b/tests/Tests.AzureAppConfiguration/RefreshTests.cs index 298fa4b8..25c88f99 100644 --- a/tests/Tests.AzureAppConfiguration/RefreshTests.cs +++ b/tests/Tests.AzureAppConfiguration/RefreshTests.cs @@ -83,10 +83,10 @@ Response GetIfChanged(ConfigurationSetting setting, bool o // Load all settings except the one registered for refresh - this test is to ensure that it will be loaded later mockClient.Setup(c => c.GetConfigurationSettingsAsync(It.IsAny(), It.IsAny())) .Returns(new MockAsyncPageable(keyValueCollection.Where(s => s.Key != "TestKey1" && s.Label != "label").ToList())); - + mockClient.Setup(c => c.GetConfigurationSettingAsync(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync((Func>)GetTestKey); - + mockClient.Setup(c => c.GetConfigurationSettingAsync(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync((Func>)GetIfChanged); @@ -101,7 +101,7 @@ Response GetIfChanged(ConfigurationSetting setting, bool o }); }) .Build(); - + Assert.Equal("TestValue1", config["TestKey1"]); } @@ -1049,9 +1049,9 @@ public void RefreshTests_RefreshIsCancelled() Thread.Sleep(1500); using var cancellationSource = new CancellationTokenSource(); - cancellationSource.Cancel(); + cancellationSource.Cancel(); Action action = () => refresher.RefreshAsync(cancellationSource.Token).Wait(); - var exception = Assert.Throws(action); + var exception = Assert.Throws(action); Assert.IsType(exception.InnerException); Assert.Equal("TestValue1", config["TestKey1"]); } @@ -1133,7 +1133,7 @@ Response GetIfChanged(ConfigurationSetting setting, bool o mockClient.Setup(c => c.GetConfigurationSettingAsync(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync((Func>)GetTestKey); - + mockClient.Setup(c => c.GetConfigurationSettingAsync(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync((Func>)GetIfChanged); @@ -1169,10 +1169,10 @@ Response GetIfChanged(ConfigurationSetting setting, bool o mockClient.Setup(c => c.GetConfigurationSettingsAsync(It.IsAny(), It.IsAny())) .Returns((Func)GetTestKeys); - + mockClient.Setup(c => c.GetConfigurationSettingAsync(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync((Func>)GetTestKey); - + mockClient.Setup(c => c.GetConfigurationSettingAsync(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync((Func>)GetIfChanged); diff --git a/tests/Tests.AzureAppConfiguration/TestHelper.cs b/tests/Tests.AzureAppConfiguration/TestHelper.cs index 477b4429..bc7989b2 100644 --- a/tests/Tests.AzureAppConfiguration/TestHelper.cs +++ b/tests/Tests.AzureAppConfiguration/TestHelper.cs @@ -84,8 +84,10 @@ static public void SerializeSetting(ref Utf8JsonWriter json, ConfigurationSettin { json.WriteString(tag.Key, tag.Value); } + json.WriteEndObject(); } + if (setting.ETag != default) json.WriteString("etag", setting.ETag.ToString()); if (setting.LastModified.HasValue) @@ -103,6 +105,7 @@ static public void SerializeBatch(ref Utf8JsonWriter json, ConfigurationSetting[ { SerializeSetting(ref json, item); } + json.WriteEndArray(); json.WriteEndObject(); } diff --git a/tests/Tests.AzureAppConfiguration/Tests.AzureAppConfiguration.csproj b/tests/Tests.AzureAppConfiguration/Tests.AzureAppConfiguration.csproj index 9b0f17c0..8849645f 100644 --- a/tests/Tests.AzureAppConfiguration/Tests.AzureAppConfiguration.csproj +++ b/tests/Tests.AzureAppConfiguration/Tests.AzureAppConfiguration.csproj @@ -1,4 +1,4 @@ - + net48;net6.0;net7.0;net8.0 @@ -39,4 +39,5 @@ Always + diff --git a/tests/Tests.AzureAppConfiguration/Tests.cs b/tests/Tests.AzureAppConfiguration/Tests.cs index c3b27124..30010f7d 100644 --- a/tests/Tests.AzureAppConfiguration/Tests.cs +++ b/tests/Tests.AzureAppConfiguration/Tests.cs @@ -240,7 +240,7 @@ public void TestUserAgentHeader() // 5. Contains the runtime information (target framework, OS description etc.) in the format set by the SDK // 6. Does not contain any additional components string userAgentRegex = @"^Microsoft\.Extensions\.Configuration\.AzureAppConfiguration/\d+\.\d+\.\d+(\+[a-z0-9]+)?(-preview(\.\d+)?)?,azsdk-net-Data.AppConfiguration/[.+\w-]+ \([.;\w\s]+\)$"; - + var response = new MockResponse(200); response.SetContent(SerializationHelpers.Serialize(_kvCollectionPageOne.ToArray(), TestHelpers.SerializeBatch));