Merge pull request #14438 from dotnet-maestro-bot/merge/release/3.1-to-master
[automated] Merge branch 'release/3.1' => 'master'
This commit is contained in:
commit
cd2983bf41
|
|
@ -55,6 +55,7 @@ parameters:
|
||||||
artifacts: []
|
artifacts: []
|
||||||
buildDirectory: ''
|
buildDirectory: ''
|
||||||
buildScript: ''
|
buildScript: ''
|
||||||
|
installTar: true
|
||||||
installNodeJs: true
|
installNodeJs: true
|
||||||
installJdk: true
|
installJdk: true
|
||||||
timeoutInMinutes: 180
|
timeoutInMinutes: 180
|
||||||
|
|
@ -151,6 +152,9 @@ jobs:
|
||||||
Write-Host "##vso[task.setvariable variable=SeleniumProcessTrackingFolder]$(BuildDirectory)\artifacts\tmp\selenium\"
|
Write-Host "##vso[task.setvariable variable=SeleniumProcessTrackingFolder]$(BuildDirectory)\artifacts\tmp\selenium\"
|
||||||
./eng/scripts/InstallGoogleChrome.ps1
|
./eng/scripts/InstallGoogleChrome.ps1
|
||||||
displayName: Install Chrome
|
displayName: Install Chrome
|
||||||
|
- ${{ if and(eq(parameters.installTar, 'true'), eq(parameters.agentOs, 'Windows')) }}:
|
||||||
|
- powershell: ./eng/scripts/InstallTar.ps1
|
||||||
|
displayName: Find or install Tar
|
||||||
|
|
||||||
- ${{ parameters.beforeBuild }}
|
- ${{ parameters.beforeBuild }}
|
||||||
|
|
||||||
|
|
|
||||||
18
build.ps1
18
build.ps1
|
|
@ -307,6 +307,8 @@ if (-not $foundJdk -and $RunBuild -and ($All -or $BuildJava) -and -not $NoBuildJ
|
||||||
# Initialize global variables need to be set before the import of Arcade is imported
|
# Initialize global variables need to be set before the import of Arcade is imported
|
||||||
$restore = $RunRestore
|
$restore = $RunRestore
|
||||||
|
|
||||||
|
# Though VS Code may indicate $nodeReuse, $warnAsError and $msbuildEngine are unused, tools.ps1 uses them.
|
||||||
|
|
||||||
# Disable node reuse - Workaround perpetual issues in node reuse and custom task assemblies
|
# Disable node reuse - Workaround perpetual issues in node reuse and custom task assemblies
|
||||||
$nodeReuse = $false
|
$nodeReuse = $false
|
||||||
$env:MSBUILDDISABLENODEREUSE=1
|
$env:MSBUILDDISABLENODEREUSE=1
|
||||||
|
|
@ -328,10 +330,10 @@ if ($CI) {
|
||||||
}
|
}
|
||||||
|
|
||||||
# tools.ps1 corrupts global state, so reset these values in case they carried over from a previous build
|
# tools.ps1 corrupts global state, so reset these values in case they carried over from a previous build
|
||||||
rm variable:global:_BuildTool -ea Ignore
|
Remove-Item variable:global:_BuildTool -ea Ignore
|
||||||
rm variable:global:_DotNetInstallDir -ea Ignore
|
Remove-Item variable:global:_DotNetInstallDir -ea Ignore
|
||||||
rm variable:global:_ToolsetBuildProj -ea Ignore
|
Remove-Item variable:global:_ToolsetBuildProj -ea Ignore
|
||||||
rm variable:global:_MSBuildExe -ea Ignore
|
Remove-Item variable:global:_MSBuildExe -ea Ignore
|
||||||
|
|
||||||
# Import Arcade
|
# Import Arcade
|
||||||
. "$PSScriptRoot/eng/common/tools.ps1"
|
. "$PSScriptRoot/eng/common/tools.ps1"
|
||||||
|
|
@ -391,10 +393,10 @@ finally {
|
||||||
}
|
}
|
||||||
|
|
||||||
# tools.ps1 corrupts global state, so reset these values so they don't carry between invocations of build.ps1
|
# tools.ps1 corrupts global state, so reset these values so they don't carry between invocations of build.ps1
|
||||||
rm variable:global:_BuildTool -ea Ignore
|
Remove-Item variable:global:_BuildTool -ea Ignore
|
||||||
rm variable:global:_DotNetInstallDir -ea Ignore
|
Remove-Item variable:global:_DotNetInstallDir -ea Ignore
|
||||||
rm variable:global:_ToolsetBuildProj -ea Ignore
|
Remove-Item variable:global:_ToolsetBuildProj -ea Ignore
|
||||||
rm variable:global:_MSBuildExe -ea Ignore
|
Remove-Item variable:global:_MSBuildExe -ea Ignore
|
||||||
|
|
||||||
if ($DumpProcesses -or $ci) {
|
if ($DumpProcesses -or $ci) {
|
||||||
Stop-Job -Name DumpProcesses
|
Stop-Job -Name DumpProcesses
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ Building ASP.NET Core on Windows requires:
|
||||||
```ps1
|
```ps1
|
||||||
PS> ./eng/scripts/InstallJdk.ps1
|
PS> ./eng/scripts/InstallJdk.ps1
|
||||||
```
|
```
|
||||||
|
* Chrome - Selenium-based tests require a version of Chrome to be installed. Download and install it from [https://www.google.com/chrome]
|
||||||
|
|
||||||
### macOS/Linux
|
### macOS/Linux
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<Project>
|
<Project>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||||
<AspNetCoreBaselineVersion>2.2.6</AspNetCoreBaselineVersion>
|
<AspNetCoreBaselineVersion>2.2.7</AspNetCoreBaselineVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<!-- Package: dotnet-dev-certs-->
|
<!-- Package: dotnet-dev-certs-->
|
||||||
<PropertyGroup Condition=" '$(PackageId)' == 'dotnet-dev-certs' ">
|
<PropertyGroup Condition=" '$(PackageId)' == 'dotnet-dev-certs' ">
|
||||||
|
|
@ -77,12 +77,12 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- Package: Microsoft.AspNetCore.AspNetCoreModule-->
|
<!-- Package: Microsoft.AspNetCore.AspNetCoreModule-->
|
||||||
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.AspNetCoreModule' ">
|
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.AspNetCoreModule' ">
|
||||||
<BaselinePackageVersion>2.2.6</BaselinePackageVersion>
|
<BaselinePackageVersion>2.2.7</BaselinePackageVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.AspNetCoreModule' AND '$(TargetFramework)' == 'netcoreapp2.2' " />
|
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.AspNetCoreModule' AND '$(TargetFramework)' == 'netcoreapp2.2' " />
|
||||||
<!-- Package: Microsoft.AspNetCore.AspNetCoreModuleV2-->
|
<!-- Package: Microsoft.AspNetCore.AspNetCoreModuleV2-->
|
||||||
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.AspNetCoreModuleV2' ">
|
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.AspNetCoreModuleV2' ">
|
||||||
<BaselinePackageVersion>2.2.6</BaselinePackageVersion>
|
<BaselinePackageVersion>2.2.7</BaselinePackageVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.AspNetCoreModuleV2' AND '$(TargetFramework)' == 'netcoreapp2.2' " />
|
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.AspNetCoreModuleV2' AND '$(TargetFramework)' == 'netcoreapp2.2' " />
|
||||||
<!-- Package: Microsoft.AspNetCore.Authentication.Abstractions-->
|
<!-- Package: Microsoft.AspNetCore.Authentication.Abstractions-->
|
||||||
|
|
@ -303,10 +303,11 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- Package: Microsoft.AspNetCore.DataProtection.AzureStorage-->
|
<!-- Package: Microsoft.AspNetCore.DataProtection.AzureStorage-->
|
||||||
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.AzureStorage' ">
|
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.AzureStorage' ">
|
||||||
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
|
<BaselinePackageVersion>2.2.7</BaselinePackageVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.AzureStorage' AND '$(TargetFramework)' == 'netstandard2.0' ">
|
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.AzureStorage' AND '$(TargetFramework)' == 'netstandard2.0' ">
|
||||||
<BaselinePackageReference Include="Microsoft.AspNetCore.DataProtection" Version="[2.2.0, )" />
|
<BaselinePackageReference Include="Microsoft.AspNetCore.DataProtection" Version="[2.2.0, )" />
|
||||||
|
<BaselinePackageReference Include="Microsoft.Data.OData" Version="[5.8.4, )" />
|
||||||
<BaselinePackageReference Include="WindowsAzure.Storage" Version="[8.1.4, )" />
|
<BaselinePackageReference Include="WindowsAzure.Storage" Version="[8.1.4, )" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- Package: Microsoft.AspNetCore.DataProtection.EntityFrameworkCore-->
|
<!-- Package: Microsoft.AspNetCore.DataProtection.EntityFrameworkCore-->
|
||||||
|
|
@ -434,21 +435,21 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- Package: Microsoft.AspNetCore.Hosting-->
|
<!-- Package: Microsoft.AspNetCore.Hosting-->
|
||||||
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Hosting' ">
|
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Hosting' ">
|
||||||
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
|
<BaselinePackageVersion>2.2.7</BaselinePackageVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Hosting' AND '$(TargetFramework)' == 'netstandard2.0' ">
|
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Hosting' AND '$(TargetFramework)' == 'netstandard2.0' ">
|
||||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="[2.2.0, )" />
|
<BaselinePackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="[2.2.0, )" />
|
||||||
<BaselinePackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="[2.2.0, )" />
|
|
||||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Http" Version="[2.2.0, )" />
|
<BaselinePackageReference Include="Microsoft.AspNetCore.Http" Version="[2.2.0, )" />
|
||||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="[2.2.0, )" />
|
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="[2.2.0, )" />
|
||||||
<BaselinePackageReference Include="Microsoft.Extensions.Configuration" Version="[2.2.0, )" />
|
<BaselinePackageReference Include="Microsoft.Extensions.Configuration" Version="[2.2.0, )" />
|
||||||
<BaselinePackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="[2.2.0, )" />
|
<BaselinePackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="[2.2.4, )" />
|
||||||
<BaselinePackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="[2.2.0, )" />
|
<BaselinePackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="[2.2.0, )" />
|
||||||
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection" Version="[2.2.0, )" />
|
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection" Version="[2.2.0, )" />
|
||||||
<BaselinePackageReference Include="Microsoft.Extensions.FileProviders.Physical" Version="[2.2.0, )" />
|
<BaselinePackageReference Include="Microsoft.Extensions.FileProviders.Physical" Version="[2.2.0, )" />
|
||||||
|
<BaselinePackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="[2.2.0, )" />
|
||||||
<BaselinePackageReference Include="Microsoft.Extensions.Logging" Version="[2.2.0, )" />
|
<BaselinePackageReference Include="Microsoft.Extensions.Logging" Version="[2.2.0, )" />
|
||||||
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[2.2.0, )" />
|
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[2.2.0, )" />
|
||||||
<BaselinePackageReference Include="System.Diagnostics.DiagnosticSource" Version="[4.5.0, )" />
|
<BaselinePackageReference Include="System.Diagnostics.DiagnosticSource" Version="[4.5.1, )" />
|
||||||
<BaselinePackageReference Include="System.Reflection.Metadata" Version="[1.6.0, )" />
|
<BaselinePackageReference Include="System.Reflection.Metadata" Version="[1.6.0, )" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- Package: Microsoft.AspNetCore.Html.Abstractions-->
|
<!-- Package: Microsoft.AspNetCore.Html.Abstractions-->
|
||||||
|
|
@ -1197,12 +1198,12 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- Package: Microsoft.AspNetCore.SpaServices-->
|
<!-- Package: Microsoft.AspNetCore.SpaServices-->
|
||||||
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SpaServices' ">
|
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SpaServices' ">
|
||||||
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
|
<BaselinePackageVersion>2.2.7</BaselinePackageVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SpaServices' AND '$(TargetFramework)' == 'netstandard2.0' ">
|
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SpaServices' AND '$(TargetFramework)' == 'netstandard2.0' ">
|
||||||
<BaselinePackageReference Include="Microsoft.AspNetCore.NodeServices" Version="[2.2.0, )" />
|
|
||||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Mvc.TagHelpers" Version="[2.2.0, )" />
|
<BaselinePackageReference Include="Microsoft.AspNetCore.Mvc.TagHelpers" Version="[2.2.0, )" />
|
||||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" Version="[2.2.0, )" />
|
<BaselinePackageReference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" Version="[2.2.0, )" />
|
||||||
|
<BaselinePackageReference Include="Microsoft.AspNetCore.NodeServices" Version="[2.2.0, )" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- Package: Microsoft.AspNetCore.StaticFiles-->
|
<!-- Package: Microsoft.AspNetCore.StaticFiles-->
|
||||||
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.StaticFiles' ">
|
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.StaticFiles' ">
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ This file contains a list of all the packages and their versions which were rele
|
||||||
build of ASP.NET Core 2.2.x. Update this list when preparing for a new patch.
|
build of ASP.NET Core 2.2.x. Update this list when preparing for a new patch.
|
||||||
|
|
||||||
-->
|
-->
|
||||||
<Baseline Version="2.2.6">
|
<Baseline Version="2.2.7">
|
||||||
<Package Id="dotnet-dev-certs" Version="2.2.0" />
|
<Package Id="dotnet-dev-certs" Version="2.2.0" />
|
||||||
<Package Id="dotnet-sql-cache" Version="2.2.0" />
|
<Package Id="dotnet-sql-cache" Version="2.2.0" />
|
||||||
<Package Id="dotnet-user-secrets" Version="2.2.0" />
|
<Package Id="dotnet-user-secrets" Version="2.2.0" />
|
||||||
|
|
@ -12,8 +12,8 @@ build of ASP.NET Core 2.2.x. Update this list when preparing for a new patch.
|
||||||
<Package Id="Microsoft.AspNetCore.Antiforgery" Version="2.2.0" />
|
<Package Id="Microsoft.AspNetCore.Antiforgery" Version="2.2.0" />
|
||||||
<Package Id="Microsoft.AspNetCore.ApiAuthorization.IdentityServer" Version="2.2.0-preview-35687" />
|
<Package Id="Microsoft.AspNetCore.ApiAuthorization.IdentityServer" Version="2.2.0-preview-35687" />
|
||||||
<Package Id="Microsoft.AspNetCore.ApplicationInsights.HostingStartup" Version="2.2.0" />
|
<Package Id="Microsoft.AspNetCore.ApplicationInsights.HostingStartup" Version="2.2.0" />
|
||||||
<Package Id="Microsoft.AspNetCore.AspNetCoreModule" Version="2.2.6" />
|
<Package Id="Microsoft.AspNetCore.AspNetCoreModule" Version="2.2.7" />
|
||||||
<Package Id="Microsoft.AspNetCore.AspNetCoreModuleV2" Version="2.2.6" />
|
<Package Id="Microsoft.AspNetCore.AspNetCoreModuleV2" Version="2.2.7" />
|
||||||
<Package Id="Microsoft.AspNetCore.Authentication.Abstractions" Version="2.2.0" />
|
<Package Id="Microsoft.AspNetCore.Authentication.Abstractions" Version="2.2.0" />
|
||||||
<Package Id="Microsoft.AspNetCore.Authentication.AzureAD.UI" Version="2.2.0" />
|
<Package Id="Microsoft.AspNetCore.Authentication.AzureAD.UI" Version="2.2.0" />
|
||||||
<Package Id="Microsoft.AspNetCore.Authentication.AzureADB2C.UI" Version="2.2.0" />
|
<Package Id="Microsoft.AspNetCore.Authentication.AzureADB2C.UI" Version="2.2.0" />
|
||||||
|
|
@ -39,7 +39,7 @@ build of ASP.NET Core 2.2.x. Update this list when preparing for a new patch.
|
||||||
<Package Id="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="2.2.0" />
|
<Package Id="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="2.2.0" />
|
||||||
<Package Id="Microsoft.AspNetCore.DataProtection.Abstractions" Version="2.2.0" />
|
<Package Id="Microsoft.AspNetCore.DataProtection.Abstractions" Version="2.2.0" />
|
||||||
<Package Id="Microsoft.AspNetCore.DataProtection.AzureKeyVault" Version="2.2.0" />
|
<Package Id="Microsoft.AspNetCore.DataProtection.AzureKeyVault" Version="2.2.0" />
|
||||||
<Package Id="Microsoft.AspNetCore.DataProtection.AzureStorage" Version="2.2.0" />
|
<Package Id="Microsoft.AspNetCore.DataProtection.AzureStorage" Version="2.2.7" />
|
||||||
<Package Id="Microsoft.AspNetCore.DataProtection.EntityFrameworkCore" Version="2.2.0" />
|
<Package Id="Microsoft.AspNetCore.DataProtection.EntityFrameworkCore" Version="2.2.0" />
|
||||||
<Package Id="Microsoft.AspNetCore.DataProtection.Extensions" Version="2.2.0" />
|
<Package Id="Microsoft.AspNetCore.DataProtection.Extensions" Version="2.2.0" />
|
||||||
<Package Id="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="2.2.5" />
|
<Package Id="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="2.2.5" />
|
||||||
|
|
@ -53,7 +53,7 @@ build of ASP.NET Core 2.2.x. Update this list when preparing for a new patch.
|
||||||
<Package Id="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.2.0" />
|
<Package Id="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.2.0" />
|
||||||
<Package Id="Microsoft.AspNetCore.Hosting.Server.Abstractions" Version="2.2.0" />
|
<Package Id="Microsoft.AspNetCore.Hosting.Server.Abstractions" Version="2.2.0" />
|
||||||
<Package Id="Microsoft.AspNetCore.Hosting.WindowsServices" Version="2.2.0" />
|
<Package Id="Microsoft.AspNetCore.Hosting.WindowsServices" Version="2.2.0" />
|
||||||
<Package Id="Microsoft.AspNetCore.Hosting" Version="2.2.0" />
|
<Package Id="Microsoft.AspNetCore.Hosting" Version="2.2.7" />
|
||||||
<Package Id="Microsoft.AspNetCore.Html.Abstractions" Version="2.2.0" />
|
<Package Id="Microsoft.AspNetCore.Html.Abstractions" Version="2.2.0" />
|
||||||
<Package Id="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
|
<Package Id="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
|
||||||
<Package Id="Microsoft.AspNetCore.Http.Connections.Client" Version="1.1.0" />
|
<Package Id="Microsoft.AspNetCore.Http.Connections.Client" Version="1.1.0" />
|
||||||
|
|
@ -122,7 +122,7 @@ build of ASP.NET Core 2.2.x. Update this list when preparing for a new patch.
|
||||||
<Package Id="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="1.1.5" />
|
<Package Id="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="1.1.5" />
|
||||||
<Package Id="Microsoft.AspNetCore.SignalR" Version="1.1.0" />
|
<Package Id="Microsoft.AspNetCore.SignalR" Version="1.1.0" />
|
||||||
<Package Id="Microsoft.AspNetCore.SpaServices.Extensions" Version="2.2.0" />
|
<Package Id="Microsoft.AspNetCore.SpaServices.Extensions" Version="2.2.0" />
|
||||||
<Package Id="Microsoft.AspNetCore.SpaServices" Version="2.2.0" />
|
<Package Id="Microsoft.AspNetCore.SpaServices" Version="2.2.7" />
|
||||||
<Package Id="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" />
|
<Package Id="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" />
|
||||||
<Package Id="Microsoft.AspNetCore.TestHost" Version="2.2.0" />
|
<Package Id="Microsoft.AspNetCore.TestHost" Version="2.2.0" />
|
||||||
<Package Id="Microsoft.AspNetCore.WebSockets" Version="2.2.1" />
|
<Package Id="Microsoft.AspNetCore.WebSockets" Version="2.2.1" />
|
||||||
|
|
|
||||||
|
|
@ -29,10 +29,6 @@ Later on, this will be checked using this condition:
|
||||||
java:signalr;
|
java:signalr;
|
||||||
</PackagesInPatch>
|
</PackagesInPatch>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(VersionPrefix)' == '2.2.3' ">
|
|
||||||
<PackagesInPatch>
|
|
||||||
</PackagesInPatch>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(VersionPrefix)' == '2.2.4' ">
|
<PropertyGroup Condition=" '$(VersionPrefix)' == '2.2.4' ">
|
||||||
<PackagesInPatch>
|
<PackagesInPatch>
|
||||||
@aspnet/signalr;
|
@aspnet/signalr;
|
||||||
|
|
@ -70,4 +66,8 @@ Later on, this will be checked using this condition:
|
||||||
Microsoft.AspNetCore.SpaServices;
|
Microsoft.AspNetCore.SpaServices;
|
||||||
</PackagesInPatch>
|
</PackagesInPatch>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(VersionPrefix)' == '2.2.8' ">
|
||||||
|
<PackagesInPatch>
|
||||||
|
</PackagesInPatch>
|
||||||
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Finds or installs the Tar command on this system.
|
||||||
|
.DESCRIPTION
|
||||||
|
This script searches for Tar on this system. If not found, downloads and extracts Git to use its tar.exe. Prefers
|
||||||
|
global installation locations even if Git has been downloaded into this repo.
|
||||||
|
.PARAMETER GitVersion
|
||||||
|
The version of the Git to install. If not set, the default value is read from global.json.
|
||||||
|
.PARAMETER Force
|
||||||
|
Overwrite the existing installation if one exists in this repo and Tar isn't installed globally.
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[string]$GitVersion,
|
||||||
|
[switch]$Force
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
$ProgressPreference = 'SilentlyContinue' # Workaround PowerShell/PowerShell#2138
|
||||||
|
|
||||||
|
Set-StrictMode -Version 1
|
||||||
|
|
||||||
|
# Find tar. If not found, install Git to get it.
|
||||||
|
$repoRoot = (Join-Path $PSScriptRoot "..\.." -Resolve)
|
||||||
|
$installDir = "$repoRoot\.tools\Git\win-x64"
|
||||||
|
$tarCommand = "$installDir\usr\bin\tar.exe"
|
||||||
|
$finalCommand = "$repoRoot\.tools\tar.exe"
|
||||||
|
|
||||||
|
Write-Host "Windows version and other information..."
|
||||||
|
cmd.exe /c ver
|
||||||
|
systeminfo.exe
|
||||||
|
Write-Host "Processor Architecture: $env:PROCESSOR_ARCHITECTURE"
|
||||||
|
|
||||||
|
Write-Host "Checking $env:SystemRoot\System32\tar.exe"
|
||||||
|
Get-ChildItem "$env:SystemRoot\System32\ta*.exe"
|
||||||
|
if (Test-Path "$env:SystemRoot\System32\tar.exe") {
|
||||||
|
Write-Host "Found $env:SystemRoot\System32\tar.exe"
|
||||||
|
$tarCommand = "$env:SystemRoot\System32\tar.exe"
|
||||||
|
}
|
||||||
|
elseif (Test-Path "$env:ProgramFiles\Git\usr\bin\tar.exe") {
|
||||||
|
$tarCommand = "$env:ProgramFiles\Git\usr\bin\tar.exe"
|
||||||
|
}
|
||||||
|
elseif (Test-Path "${env:ProgramFiles(x86)}\Git\usr\bin\tar.exe") {
|
||||||
|
$tarCommand = "${env:ProgramFiles(x86)}\Git\usr\bin\tar.exe"
|
||||||
|
}
|
||||||
|
elseif (Test-Path "$env:AGENT_HOMEDIRECTORY\externals\git\usr\bin\tar.exe") {
|
||||||
|
$tarCommand = "$env:AGENT_HOMEDIRECTORY\externals\git\usr\bin\tar.exe"
|
||||||
|
}
|
||||||
|
elseif ((Test-Path $tarCommand) -And (-Not $Force)) {
|
||||||
|
Write-Verbose "Repo-local Git installation and $tarCommand already exist, skipping Git install."
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (-not $GitVersion) {
|
||||||
|
$globalJson = Get-Content "$repoRoot\global.json" | ConvertFrom-Json
|
||||||
|
$GitVersion = $globalJson.tools.Git
|
||||||
|
}
|
||||||
|
|
||||||
|
$Uri = "https://netcorenativeassets.blob.core.windows.net/resource-packages/external/windows/git/Git-${GitVersion}-64-bit.zip"
|
||||||
|
|
||||||
|
Import-Module -Name (Join-Path $PSScriptRoot "..\common\native\CommonLibrary.psm1" -Resolve)
|
||||||
|
$InstallStatus = CommonLibrary\DownloadAndExtract -Uri $Uri -InstallDirectory "$installDir\" -Force:$Force -Verbose
|
||||||
|
|
||||||
|
if ($InstallStatus -Eq $False) {
|
||||||
|
Write-Error "Installation failed"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
New-Item "$repoRoot\.tools\" -ErrorAction SilentlyContinue -ItemType Directory
|
||||||
|
Copy-Item "$tarCommand" "$finalCommand" -Verbose
|
||||||
|
Write-Host "Tar now available at '$finalCommand'"
|
||||||
|
|
||||||
|
if ($tarCommand -like '*\Git\*') {
|
||||||
|
$null >.\.tools\tar.fromGit
|
||||||
|
}
|
||||||
|
|
@ -61,15 +61,21 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
<_GenApiFile>$([MSBuild]::NormalizePath('$(ArtifactsDir)', 'log', 'GenAPI.rsp'))</_GenApiFile>
|
||||||
<_GenAPICommand Condition="'$(MSBuildRuntimeType)' == 'core'">"$(DotNetTool)" --roll-forward-on-no-candidate-fx 2 "$(_GenAPIPath)"</_GenAPICommand>
|
<_GenAPICommand Condition="'$(MSBuildRuntimeType)' == 'core'">"$(DotNetTool)" --roll-forward-on-no-candidate-fx 2 "$(_GenAPIPath)"</_GenAPICommand>
|
||||||
<_GenAPICmd>$(_GenAPICommand)</_GenAPICmd>
|
<_GenAPICmd>$(_GenAPICommand) @"$(_GenApiFile)"</_GenAPICmd>
|
||||||
<_GenAPICmd>$(_GenAPICmd) "$(TargetPath)"</_GenAPICmd>
|
<_GenApiArguments><![CDATA[
|
||||||
<_GenAPICmd>$(_GenAPICmd) --lib-path "@(_ReferencePathDirectories)"</_GenAPICmd>
|
"$(TargetPath)"
|
||||||
<_GenAPICmd>$(_GenAPICmd) --out "$(_RefSourceFileOutputPath)"</_GenAPICmd>
|
--lib-path "@(_ReferencePathDirectories, '%3B')"
|
||||||
<_GenAPICmd>$(_GenAPICmd) --header-file "$(RepoRoot)/eng/LicenseHeader.txt"</_GenAPICmd>
|
--out "$(_RefSourceFileOutputPath)"
|
||||||
<_GenAPICmd>$(_GenAPICmd) --exclude-api-list "$(RepoRoot)/eng/GenAPI.exclusions.txt"</_GenAPICmd>
|
--header-file "$(RepoRoot)/eng/LicenseHeader.txt"
|
||||||
|
--exclude-api-list "$(RepoRoot)/eng/GenAPI.exclusions.txt"
|
||||||
|
]]>
|
||||||
|
</_GenApiArguments>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<WriteLinesToFile File="$(_GenApiFile)" Lines="$(_GenApiArguments)" Overwrite="true" />
|
||||||
|
|
||||||
<MakeDir Directories="$(_RefSourceOutputPath)" />
|
<MakeDir Directories="$(_RefSourceOutputPath)" />
|
||||||
<Message Importance="High" Text="Generating $(_RefSourceFileOutputPath)" />
|
<Message Importance="High" Text="Generating $(_RefSourceFileOutputPath)" />
|
||||||
<Exec Command="$(_GenAPICmd)" />
|
<Exec Command="$(_GenAPICmd)" />
|
||||||
|
|
@ -96,4 +102,4 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"$(MicrosoftNETCoreAppRuntimeVersion)"
|
"$(MicrosoftNETCoreAppRuntimeVersion)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"Git": "2.22.0",
|
||||||
"jdk": "11.0.3",
|
"jdk": "11.0.3",
|
||||||
"vs": {
|
"vs": {
|
||||||
"version": "16.0",
|
"version": "16.0",
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ namespace Ignitor
|
||||||
|
|
||||||
public Task<CapturedRenderBatch> PrepareForNextBatch(TimeSpan? timeout)
|
public Task<CapturedRenderBatch> PrepareForNextBatch(TimeSpan? timeout)
|
||||||
{
|
{
|
||||||
if (NextBatchReceived?.Completion != null)
|
if (NextBatchReceived != null && !NextBatchReceived.Disposed)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Invalid state previous task not completed");
|
throw new InvalidOperationException("Invalid state previous task not completed");
|
||||||
}
|
}
|
||||||
|
|
@ -100,7 +100,7 @@ namespace Ignitor
|
||||||
|
|
||||||
public Task<CapturedJSInteropCall> PrepareForNextJSInterop(TimeSpan? timeout)
|
public Task<CapturedJSInteropCall> PrepareForNextJSInterop(TimeSpan? timeout)
|
||||||
{
|
{
|
||||||
if (NextJSInteropReceived?.Completion != null)
|
if (NextJSInteropReceived != null && !NextJSInteropReceived.Disposed)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Invalid state previous task not completed");
|
throw new InvalidOperationException("Invalid state previous task not completed");
|
||||||
}
|
}
|
||||||
|
|
@ -112,7 +112,7 @@ namespace Ignitor
|
||||||
|
|
||||||
public Task<string> PrepareForNextDotNetInterop(TimeSpan? timeout)
|
public Task<string> PrepareForNextDotNetInterop(TimeSpan? timeout)
|
||||||
{
|
{
|
||||||
if (NextDotNetInteropCompletionReceived?.Completion != null)
|
if (NextDotNetInteropCompletionReceived != null && !NextDotNetInteropCompletionReceived.Disposed)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Invalid state previous task not completed");
|
throw new InvalidOperationException("Invalid state previous task not completed");
|
||||||
}
|
}
|
||||||
|
|
@ -124,7 +124,7 @@ namespace Ignitor
|
||||||
|
|
||||||
public Task<string> PrepareForNextCircuitError(TimeSpan? timeout)
|
public Task<string> PrepareForNextCircuitError(TimeSpan? timeout)
|
||||||
{
|
{
|
||||||
if (NextErrorReceived?.Completion != null)
|
if (NextErrorReceived != null && !NextErrorReceived.Disposed)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Invalid state previous task not completed");
|
throw new InvalidOperationException("Invalid state previous task not completed");
|
||||||
}
|
}
|
||||||
|
|
@ -136,7 +136,7 @@ namespace Ignitor
|
||||||
|
|
||||||
public Task<Exception> PrepareForNextDisconnect(TimeSpan? timeout)
|
public Task<Exception> PrepareForNextDisconnect(TimeSpan? timeout)
|
||||||
{
|
{
|
||||||
if (NextDisconnect?.Completion != null)
|
if (NextDisconnect != null && !NextDisconnect.Disposed)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Invalid state previous task not completed");
|
throw new InvalidOperationException("Invalid state previous task not completed");
|
||||||
}
|
}
|
||||||
|
|
@ -499,56 +499,6 @@ namespace Ignitor
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class CancellableOperation<TResult>
|
|
||||||
{
|
|
||||||
public CancellableOperation(TimeSpan? timeout)
|
|
||||||
{
|
|
||||||
Timeout = timeout;
|
|
||||||
Initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
public TimeSpan? Timeout { get; }
|
|
||||||
|
|
||||||
public TaskCompletionSource<TResult> Completion { get; set; }
|
|
||||||
|
|
||||||
public CancellationTokenSource Cancellation { get; set; }
|
|
||||||
|
|
||||||
public CancellationTokenRegistration CancellationRegistration { get; set; }
|
|
||||||
|
|
||||||
private void Initialize()
|
|
||||||
{
|
|
||||||
Completion = new TaskCompletionSource<TResult>(TaskContinuationOptions.RunContinuationsAsynchronously);
|
|
||||||
Completion.Task.ContinueWith(
|
|
||||||
(task, state) =>
|
|
||||||
{
|
|
||||||
var operation = (CancellableOperation<TResult>)state;
|
|
||||||
operation.Dispose();
|
|
||||||
},
|
|
||||||
this,
|
|
||||||
TaskContinuationOptions.ExecuteSynchronously); // We need to execute synchronously to clean-up before anything else continues
|
|
||||||
if (Timeout != null && Timeout != System.Threading.Timeout.InfiniteTimeSpan && Timeout != TimeSpan.MaxValue)
|
|
||||||
{
|
|
||||||
Cancellation = new CancellationTokenSource(Timeout.Value);
|
|
||||||
CancellationRegistration = Cancellation.Token.Register(
|
|
||||||
(self) =>
|
|
||||||
{
|
|
||||||
var operation = (CancellableOperation<TResult>)self;
|
|
||||||
operation.Completion.TrySetCanceled(operation.Cancellation.Token);
|
|
||||||
operation.Cancellation.Dispose();
|
|
||||||
operation.CancellationRegistration.Dispose();
|
|
||||||
},
|
|
||||||
this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Dispose()
|
|
||||||
{
|
|
||||||
Completion = null;
|
|
||||||
Cancellation.Dispose();
|
|
||||||
CancellationRegistration.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string[] ReadMarkers(string content)
|
private string[] ReadMarkers(string content)
|
||||||
{
|
{
|
||||||
content = content.Replace("\r\n", "").Replace("\n", "");
|
content = content.Replace("\r\n", "").Replace("\n", "");
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Ignitor
|
||||||
|
{
|
||||||
|
internal class CancellableOperation<TResult>
|
||||||
|
{
|
||||||
|
public CancellableOperation(TimeSpan? timeout)
|
||||||
|
{
|
||||||
|
Timeout = timeout;
|
||||||
|
|
||||||
|
Completion = new TaskCompletionSource<TResult>(TaskContinuationOptions.RunContinuationsAsynchronously);
|
||||||
|
Completion.Task.ContinueWith(
|
||||||
|
(task, state) =>
|
||||||
|
{
|
||||||
|
var operation = (CancellableOperation<TResult>)state;
|
||||||
|
operation.Dispose();
|
||||||
|
},
|
||||||
|
this,
|
||||||
|
TaskContinuationOptions.ExecuteSynchronously); // We need to execute synchronously to clean-up before anything else continues
|
||||||
|
|
||||||
|
if (Timeout != null && Timeout != System.Threading.Timeout.InfiniteTimeSpan && Timeout != TimeSpan.MaxValue)
|
||||||
|
{
|
||||||
|
Cancellation = new CancellationTokenSource(Timeout.Value);
|
||||||
|
CancellationRegistration = Cancellation.Token.Register(
|
||||||
|
(self) =>
|
||||||
|
{
|
||||||
|
var operation = (CancellableOperation<TResult>)self;
|
||||||
|
operation.Completion.TrySetCanceled(operation.Cancellation.Token);
|
||||||
|
operation.Cancellation.Dispose();
|
||||||
|
operation.CancellationRegistration.Dispose();
|
||||||
|
},
|
||||||
|
this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TimeSpan? Timeout { get; }
|
||||||
|
|
||||||
|
public TaskCompletionSource<TResult> Completion { get; }
|
||||||
|
|
||||||
|
public CancellationTokenSource Cancellation { get; }
|
||||||
|
|
||||||
|
public CancellationTokenRegistration CancellationRegistration { get; }
|
||||||
|
|
||||||
|
public bool Disposed { get; private set; }
|
||||||
|
|
||||||
|
private void Dispose()
|
||||||
|
{
|
||||||
|
if (Disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Disposed = true;
|
||||||
|
Completion.TrySetCanceled(Cancellation.Token);
|
||||||
|
Cancellation.Dispose();
|
||||||
|
CancellationRegistration.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -171,14 +171,26 @@ This package is an internal implementation of the .NET Core SDK and is not meant
|
||||||
Inputs="@(RefPackContent)"
|
Inputs="@(RefPackContent)"
|
||||||
Outputs="$(ZipArchiveOutputPath);$(TarArchiveOutputPath)"
|
Outputs="$(ZipArchiveOutputPath);$(TarArchiveOutputPath)"
|
||||||
Condition="'$(IsPackable)' == 'true'">
|
Condition="'$(IsPackable)' == 'true'">
|
||||||
|
<PropertyGroup>
|
||||||
|
<_TarCommand>tar</_TarCommand>
|
||||||
|
<_TarCommand Condition="Exists('$(RepoRoot).tools\tar.exe')">$(RepoRoot).tools\tar.exe</_TarCommand>
|
||||||
|
|
||||||
|
<!-- For the tar packed with git, transform e.g. "C:\root\AspNetCore\File.tar.gz" to "/C/root/AspNetCore/File.tar.gz". -->
|
||||||
|
<_TarArchiveOutputPath>$(TarArchiveOutputPath)</_TarArchiveOutputPath>
|
||||||
|
<_TarArchiveOutputPath
|
||||||
|
Condition="Exists('$(repoRoot)\.tools\tar.fromGit')">/$(TarArchiveOutputPath.Replace('\','/').Replace(':',''))</_TarArchiveOutputPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ZipDirectory
|
<ZipDirectory
|
||||||
SourceDirectory="$(TargetingPackLayoutRoot)"
|
SourceDirectory="$(TargetingPackLayoutRoot)"
|
||||||
DestinationFile="$(ZipArchiveOutputPath)"
|
DestinationFile="$(ZipArchiveOutputPath)"
|
||||||
Overwrite="true" />
|
Overwrite="true" />
|
||||||
|
|
||||||
<!-- Requires Windows 10 version 1803 or newer -->
|
<!-- Requires Windows 10 version 1803 or newer -->
|
||||||
<Exec
|
<Message Importance="High" Text="Executing: $(_TarCommand) -czf $(_TarArchiveOutputPath) ." />
|
||||||
Command="tar -czf $(TarArchiveOutputPath) ."
|
<Exec Command="$(_TarCommand) -czf $(_TarArchiveOutputPath) ."
|
||||||
WorkingDirectory="$(TargetingPackLayoutRoot)" />
|
WorkingDirectory="$(TargetingPackLayoutRoot)" />
|
||||||
|
|
||||||
<Message Importance="High" Text="$(MSBuildProjectName) -> $(TarArchiveOutputPath)" />
|
<Message Importance="High" Text="$(MSBuildProjectName) -> $(TarArchiveOutputPath)" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ namespace Microsoft.AspNetCore.E2ETesting
|
||||||
var instance = await SeleniumStandaloneServer.GetInstanceAsync(output);
|
var instance = await SeleniumStandaloneServer.GetInstanceAsync(output);
|
||||||
|
|
||||||
var attempt = 0;
|
var attempt = 0;
|
||||||
var maxAttempts = 3;
|
const int maxAttempts = 3;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
@ -132,18 +132,16 @@ namespace Microsoft.AspNetCore.E2ETesting
|
||||||
|
|
||||||
return (driver, logs);
|
return (driver, logs);
|
||||||
}
|
}
|
||||||
catch
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
if (attempt >= maxAttempts)
|
output.WriteLine($"Error initializing RemoteWebDriver: {ex.Message}");
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Couldn't create a Selenium remote driver client. The server is irresponsive");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
attempt++;
|
attempt++;
|
||||||
|
|
||||||
} while (attempt < maxAttempts);
|
} while (attempt < maxAttempts);
|
||||||
|
|
||||||
// We will never get here. Keeping the compiler happy.
|
throw new InvalidOperationException("Couldn't create a Selenium remote driver client. The server is irresponsive");
|
||||||
throw new InvalidOperationException("Couldn't create a Selenium remote driver client. The server is unresponsive");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ namespace Microsoft.Extensions.ApiDescription.Client
|
||||||
public void Execute_ReturnsExpectedItem()
|
public void Execute_ReturnsExpectedItem()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
string input = "Identity=../files/azureMonitor.json|ClassName=azureMonitorClient|" +
|
var input = "Identity=../files/azureMonitor.json|ClassName=azureMonitorClient|" +
|
||||||
"CodeGenerator=NSwagCSharp|Namespace=ConsoleClient|Options=|OutputPath=" +
|
"CodeGenerator=NSwagCSharp|Namespace=ConsoleClient|Options=|OutputPath=" +
|
||||||
"C:\\dd\\dnx\\AspNetCore\\artifacts\\obj\\ConsoleClient\\azureMonitorClient.cs|" +
|
"C:\\dd\\dnx\\AspNetCore\\artifacts\\obj\\ConsoleClient\\azureMonitorClient.cs|" +
|
||||||
"OriginalItemSpec=../files/azureMonitor.json|FirstForGenerator=true";
|
"OriginalItemSpec=../files/azureMonitor.json|FirstForGenerator=true";
|
||||||
|
|
@ -22,8 +22,8 @@ namespace Microsoft.Extensions.ApiDescription.Client
|
||||||
Input = input,
|
Input = input,
|
||||||
};
|
};
|
||||||
|
|
||||||
string expectedIdentity = "../files/azureMonitor.json";
|
var expectedIdentity = "../files/azureMonitor.json";
|
||||||
IDictionary<string, string> expectedMetadata = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
var expectedMetadata = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
||||||
{
|
{
|
||||||
{ "ClassName", "azureMonitorClient" },
|
{ "ClassName", "azureMonitorClient" },
|
||||||
{ "CodeGenerator", "NSwagCSharp" },
|
{ "CodeGenerator", "NSwagCSharp" },
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ namespace Microsoft.Extensions.ApiDescription.Client
|
||||||
OutputDirectory = "obj",
|
OutputDirectory = "obj",
|
||||||
};
|
};
|
||||||
|
|
||||||
IDictionary<string, string> expectedMetadata = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
var expectedMetadata = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
||||||
{
|
{
|
||||||
{ "ClassName", "NSwagClient" },
|
{ "ClassName", "NSwagClient" },
|
||||||
{ "CodeGenerator", "NSwagCSharp" },
|
{ "CodeGenerator", "NSwagCSharp" },
|
||||||
|
|
@ -85,7 +85,7 @@ namespace Microsoft.Extensions.ApiDescription.Client
|
||||||
OutputDirectory = "obj",
|
OutputDirectory = "obj",
|
||||||
};
|
};
|
||||||
|
|
||||||
IDictionary<string, string> expectedMetadata = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
var expectedMetadata = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
||||||
{
|
{
|
||||||
{ "ClassName", className },
|
{ "ClassName", className },
|
||||||
{ "CodeGenerator", "NSwagCSharp" },
|
{ "CodeGenerator", "NSwagCSharp" },
|
||||||
|
|
@ -143,7 +143,7 @@ namespace Microsoft.Extensions.ApiDescription.Client
|
||||||
OutputDirectory = "obj",
|
OutputDirectory = "obj",
|
||||||
};
|
};
|
||||||
|
|
||||||
IDictionary<string, string> expectedMetadata = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
var expectedMetadata = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
||||||
{
|
{
|
||||||
{ "ClassName", "NSwagClient" },
|
{ "ClassName", "NSwagClient" },
|
||||||
{ "CodeGenerator", "NSwagCSharp" },
|
{ "CodeGenerator", "NSwagCSharp" },
|
||||||
|
|
@ -201,7 +201,7 @@ namespace Microsoft.Extensions.ApiDescription.Client
|
||||||
OutputDirectory = "bin",
|
OutputDirectory = "bin",
|
||||||
};
|
};
|
||||||
|
|
||||||
IDictionary<string, string> expectedMetadata = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
var expectedMetadata = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
||||||
{
|
{
|
||||||
{ "ClassName", className },
|
{ "ClassName", className },
|
||||||
{ "CodeGenerator", "NSwagCSharp" },
|
{ "CodeGenerator", "NSwagCSharp" },
|
||||||
|
|
@ -351,7 +351,7 @@ namespace Microsoft.Extensions.ApiDescription.Client
|
||||||
OutputDirectory = "bin",
|
OutputDirectory = "bin",
|
||||||
};
|
};
|
||||||
|
|
||||||
IDictionary<string, string> expectedMetadata = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
var expectedMetadata = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
||||||
{
|
{
|
||||||
{ "ClassName", className },
|
{ "ClassName", className },
|
||||||
{ "CodeGenerator", "NSwagCSharp" },
|
{ "CodeGenerator", "NSwagCSharp" },
|
||||||
|
|
@ -414,7 +414,7 @@ namespace Microsoft.Extensions.ApiDescription.Client
|
||||||
OutputDirectory = "bin",
|
OutputDirectory = "bin",
|
||||||
};
|
};
|
||||||
|
|
||||||
IDictionary<string, string> expectedMetadata = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
var expectedMetadata = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
||||||
{
|
{
|
||||||
{ "ClassName", className },
|
{ "ClassName", className },
|
||||||
{ "CodeGenerator", "NSwagCSharp" },
|
{ "CodeGenerator", "NSwagCSharp" },
|
||||||
|
|
@ -481,7 +481,7 @@ namespace Microsoft.Extensions.ApiDescription.Client
|
||||||
OutputDirectory = "obj",
|
OutputDirectory = "obj",
|
||||||
};
|
};
|
||||||
|
|
||||||
IDictionary<string, string> expectedMetadata1 = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
var expectedMetadata1 = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
||||||
{
|
{
|
||||||
{ "ClassName", className12 },
|
{ "ClassName", className12 },
|
||||||
{ "CodeGenerator", codeGenerator13 },
|
{ "CodeGenerator", codeGenerator13 },
|
||||||
|
|
@ -496,7 +496,7 @@ namespace Microsoft.Extensions.ApiDescription.Client
|
||||||
$"OutputPath={outputPath1}|ClassName={className12}|Namespace={@namespace}"
|
$"OutputPath={outputPath1}|ClassName={className12}|Namespace={@namespace}"
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
IDictionary<string, string> expectedMetadata2 = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
var expectedMetadata2 = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
||||||
{
|
{
|
||||||
{ "ClassName", className12 },
|
{ "ClassName", className12 },
|
||||||
{ "CodeGenerator", codeGenerator2 },
|
{ "CodeGenerator", codeGenerator2 },
|
||||||
|
|
@ -511,7 +511,7 @@ namespace Microsoft.Extensions.ApiDescription.Client
|
||||||
$"OutputPath={outputPath2}|ClassName={className12}|Namespace={@namespace}"
|
$"OutputPath={outputPath2}|ClassName={className12}|Namespace={@namespace}"
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
IDictionary<string, string> expectedMetadata3 = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
var expectedMetadata3 = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
||||||
{
|
{
|
||||||
{ "ClassName", className3 },
|
{ "ClassName", className3 },
|
||||||
{ "CodeGenerator", codeGenerator13 },
|
{ "CodeGenerator", codeGenerator13 },
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,314 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.Build.Framework;
|
||||||
|
using Microsoft.Build.Utilities;
|
||||||
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.ApiDescription.Client
|
||||||
|
{
|
||||||
|
// ItemSpec values always have '\\' converted to '/' on input when running on non-Windows. It is not possible to
|
||||||
|
// retrieve the original (unconverted) item spec value. In other respects, item spec values are treated identically
|
||||||
|
// to custom metadata values.
|
||||||
|
//
|
||||||
|
// ITaskItem members aka the implicitly-implemented methods and properties in TaskItem expect _escaped_ values on
|
||||||
|
// input and return _literal_ values. This includes TaskItem constructors and CloneCustomMetadata() (which returns
|
||||||
|
// a new dictionary containing literal values). TaskItem stores all values in their escaped form.
|
||||||
|
//
|
||||||
|
// Added ITaskItem2 members e.g. CloneCustomMetadataEscaped(), GetMetadataValueEscaped(...) and
|
||||||
|
// EvaluatedIncludeEscaped return escaped values. Of all TaskItem methods, only SetMetadataValueLiteral(...)
|
||||||
|
// accepts a literal input value.
|
||||||
|
//
|
||||||
|
// Metadata names are never escaped.
|
||||||
|
//
|
||||||
|
// MetadataSerializer expects literal values on input.
|
||||||
|
public class MetadataSerializerTest
|
||||||
|
{
|
||||||
|
// Maps literal to escaped values.
|
||||||
|
public static TheoryData<string, string> EscapedValuesMapping { get; } = new TheoryData<string, string>
|
||||||
|
{
|
||||||
|
{ "No escaping necessary for =.", "No escaping necessary for =." },
|
||||||
|
{ "Value needs escaping? (yes)", "Value needs escaping%3f %28yes%29" },
|
||||||
|
{ "$ comes earlier; @ comes later.", "%24 comes earlier%3b %40 comes later." },
|
||||||
|
{
|
||||||
|
"A '%' *character* needs escaping %-escaping.",
|
||||||
|
"A %27%25%27 %2acharacter%2a needs escaping %25-escaping."
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
public static TheoryData<string> EscapedValues
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var result = new TheoryData<string>();
|
||||||
|
foreach (var entry in EscapedValuesMapping)
|
||||||
|
{
|
||||||
|
result.Add((string)entry[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TheoryData<string> LiteralValues
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var result = new TheoryData<string>();
|
||||||
|
foreach (var entry in EscapedValuesMapping)
|
||||||
|
{
|
||||||
|
result.Add((string)entry[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(LiteralValues))]
|
||||||
|
public void SetMetadata_UpdatesTaskAsExpected(string value)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var item = new TaskItem("My Identity");
|
||||||
|
var key = "My key";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
MetadataSerializer.SetMetadata(item, key, value);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(value, item.GetMetadata(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(EscapedValuesMapping))]
|
||||||
|
public void SetMetadata_UpdatesTaskAsExpected_WithLegacyItem(string value, string escapedValue)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var item = new Mock<ITaskItem>(MockBehavior.Strict);
|
||||||
|
var key = "My key";
|
||||||
|
item.Setup(i => i.SetMetadata(key, escapedValue)).Verifiable();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
MetadataSerializer.SetMetadata(item.Object, key, value);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
item.Verify(i => i.SetMetadata(key, escapedValue), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DeserializeMetadata_ReturnsExpectedTask()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var identity = "../files/azureMonitor.json";
|
||||||
|
var input = $"Identity={identity}|ClassName=azureMonitorClient|" +
|
||||||
|
"CodeGenerator=NSwagCSharp|FirstForGenerator=true|Namespace=ConsoleClient|" +
|
||||||
|
"Options=|OriginalItemSpec=../files/azureMonitor.json|" +
|
||||||
|
"OutputPath=C:\\dd\\dnx\\AspNetCore\\artifacts\\obj\\ConsoleClient\\azureMonitorClient.cs";
|
||||||
|
|
||||||
|
var expectedMetadata = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
||||||
|
{
|
||||||
|
{ "ClassName", "azureMonitorClient" },
|
||||||
|
{ "CodeGenerator", "NSwagCSharp" },
|
||||||
|
{ "FirstForGenerator", "true" },
|
||||||
|
{ "Namespace", "ConsoleClient" },
|
||||||
|
{ "Options", "" },
|
||||||
|
{ "OriginalItemSpec", identity },
|
||||||
|
{ "OutputPath", "C:\\dd\\dnx\\AspNetCore\\artifacts\\obj\\ConsoleClient\\azureMonitorClient.cs" },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var item = MetadataSerializer.DeserializeMetadata(input);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(identity, item.ItemSpec);
|
||||||
|
var metadata = Assert.IsAssignableFrom<IDictionary<string, string>>(item.CloneCustomMetadata());
|
||||||
|
|
||||||
|
// The dictionary CloneCustomMetadata returns doesn't provide a useful KeyValuePair enumerator.
|
||||||
|
var orderedMetadata = new SortedDictionary<string, string>(StringComparer.Ordinal);
|
||||||
|
foreach (var key in metadata.Keys)
|
||||||
|
{
|
||||||
|
orderedMetadata.Add(key, metadata[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.Equal(expectedMetadata, orderedMetadata);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(EscapedValuesMapping))]
|
||||||
|
public void DeserializeMetadata_ReturnsExpectedTask_WhenEscaping(string value, string escapedValue)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var identity = "../files/azureMonitor.json";
|
||||||
|
var input = $"Identity={identity}|Value={escapedValue}";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var item = MetadataSerializer.DeserializeMetadata(input);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(identity, item.ItemSpec);
|
||||||
|
Assert.Equal(value, item.GetMetadata("Value"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(EscapedValuesMapping))]
|
||||||
|
public void DeserializeMetadata_ReturnsExpectedTask_WhenEscapingIdentity(string value, string escapedValue)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var input = $"Identity={escapedValue}|Value=a value";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var item = MetadataSerializer.DeserializeMetadata(input);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(value, item.ItemSpec);
|
||||||
|
Assert.Equal("a value", item.GetMetadata("Value"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SerializeMetadata_ReturnsExpectedString()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var identity = "../files/azureMonitor.json";
|
||||||
|
var metadata = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
||||||
|
{
|
||||||
|
{ "ClassName", "azureMonitorClient" },
|
||||||
|
{ "CodeGenerator", "NSwagCSharp" },
|
||||||
|
{ "FirstForGenerator", "true" },
|
||||||
|
{ "Namespace", "ConsoleClient" },
|
||||||
|
{ "Options", "" },
|
||||||
|
{ "OriginalItemSpec", identity },
|
||||||
|
{ "OutputPath", "C:\\dd\\dnx\\AspNetCore\\artifacts\\obj\\ConsoleClient\\azureMonitorClient.cs" },
|
||||||
|
};
|
||||||
|
|
||||||
|
var input = new TaskItem(identity, metadata);
|
||||||
|
var expectedResult = $"Identity={identity}|ClassName=azureMonitorClient|" +
|
||||||
|
"CodeGenerator=NSwagCSharp|FirstForGenerator=true|Namespace=ConsoleClient|" +
|
||||||
|
"Options=|OriginalItemSpec=../files/azureMonitor.json|" +
|
||||||
|
"OutputPath=C:\\dd\\dnx\\AspNetCore\\artifacts\\obj\\ConsoleClient\\azureMonitorClient.cs";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = MetadataSerializer.SerializeMetadata(input);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expectedResult, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(EscapedValues))]
|
||||||
|
public void SerializeMetadata_ReturnsExpectedString_WhenEscaping(string escapedValue)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var identity = "../files/azureMonitor.json";
|
||||||
|
var expectedResult = $"Identity={identity}|Value={escapedValue}";
|
||||||
|
var metadata = new SortedDictionary<string, string>(StringComparer.Ordinal) { { "Value", escapedValue } };
|
||||||
|
var input = new TaskItem(identity, metadata);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = MetadataSerializer.SerializeMetadata(input);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expectedResult, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(EscapedValues))]
|
||||||
|
public void SerializeMetadata_ReturnsExpectedString_WhenEscapingIdentity(string escapedValue)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var metadata = new SortedDictionary<string, string>(StringComparer.Ordinal) { { "Value", "a value" } };
|
||||||
|
var expectedResult = $"Identity={escapedValue}|Value=a value";
|
||||||
|
var input = new TaskItem(escapedValue, metadata);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = MetadataSerializer.SerializeMetadata(input);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expectedResult, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SerializeMetadata_ReturnsExpectedString_WithLegacyItem()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var identity = "../files/azureMonitor.json";
|
||||||
|
var metadata = new SortedDictionary<string, string>(StringComparer.Ordinal)
|
||||||
|
{
|
||||||
|
{ "ClassName", "azureMonitorClient" },
|
||||||
|
{ "CodeGenerator", "NSwagCSharp" },
|
||||||
|
{ "FirstForGenerator", "true" },
|
||||||
|
{ "Namespace", "ConsoleClient" },
|
||||||
|
{ "Options", "" },
|
||||||
|
{ "OriginalItemSpec", identity },
|
||||||
|
{ "OutputPath", "C:\\dd\\dnx\\AspNetCore\\artifacts\\obj\\ConsoleClient\\azureMonitorClient.cs" },
|
||||||
|
};
|
||||||
|
|
||||||
|
var input = new Mock<ITaskItem>(MockBehavior.Strict);
|
||||||
|
input.SetupGet(i => i.ItemSpec).Returns(identity).Verifiable();
|
||||||
|
input.Setup(i => i.CloneCustomMetadata()).Returns(metadata).Verifiable();
|
||||||
|
|
||||||
|
var expectedResult = $"Identity={identity}|ClassName=azureMonitorClient|" +
|
||||||
|
"CodeGenerator=NSwagCSharp|FirstForGenerator=true|Namespace=ConsoleClient|" +
|
||||||
|
"Options=|OriginalItemSpec=../files/azureMonitor.json|" +
|
||||||
|
"OutputPath=C:\\dd\\dnx\\AspNetCore\\artifacts\\obj\\ConsoleClient\\azureMonitorClient.cs";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = MetadataSerializer.SerializeMetadata(input.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expectedResult, result);
|
||||||
|
input.VerifyGet(i => i.ItemSpec, Times.Once);
|
||||||
|
input.Verify(i => i.CloneCustomMetadata(), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(EscapedValuesMapping))]
|
||||||
|
public void SerializeMetadata_ReturnsExpectedString_WithLegacyItem_WhenEscaping(
|
||||||
|
string value,
|
||||||
|
string escapedValue)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var identity = "../files/azureMonitor.json";
|
||||||
|
var metadata = new SortedDictionary<string, string>(StringComparer.Ordinal) { { "Value", value } };
|
||||||
|
var input = new Mock<ITaskItem>(MockBehavior.Strict);
|
||||||
|
input.SetupGet(i => i.ItemSpec).Returns(identity).Verifiable();
|
||||||
|
input.Setup(i => i.CloneCustomMetadata()).Returns(metadata).Verifiable();
|
||||||
|
|
||||||
|
var expectedResult = $"Identity={identity}|Value={escapedValue}";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = MetadataSerializer.SerializeMetadata(input.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expectedResult, result);
|
||||||
|
input.VerifyGet(i => i.ItemSpec, Times.Once);
|
||||||
|
input.Verify(i => i.CloneCustomMetadata(), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(EscapedValuesMapping))]
|
||||||
|
public void SerializeMetadata_ReturnsExpectedString_WithLegacyItem_WhenEscapingIdentity(
|
||||||
|
string value,
|
||||||
|
string escapedValue)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var metadata = new SortedDictionary<string, string>(StringComparer.Ordinal) { { "Value", "a value" } };
|
||||||
|
var input = new Mock<ITaskItem>(MockBehavior.Strict);
|
||||||
|
input.SetupGet(i => i.ItemSpec).Returns(value).Verifiable();
|
||||||
|
input.Setup(i => i.CloneCustomMetadata()).Returns(metadata).Verifiable();
|
||||||
|
|
||||||
|
var expectedResult = $"Identity={escapedValue}|Value=a value";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = MetadataSerializer.SerializeMetadata(input.Object);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expectedResult, result);
|
||||||
|
input.VerifyGet(i => i.ItemSpec, Times.Once);
|
||||||
|
input.Verify(i => i.CloneCustomMetadata(), Times.Once);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,9 +6,12 @@ using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Build.Evaluation;
|
using Microsoft.Build.Evaluation;
|
||||||
using Microsoft.DotNet.Openapi.Tools;
|
using Microsoft.DotNet.Openapi.Tools;
|
||||||
|
|
@ -240,13 +243,13 @@ namespace Microsoft.DotNet.OpenApi.Commands
|
||||||
|
|
||||||
internal async Task DownloadToFileAsync(string url, string destinationPath, bool overwrite)
|
internal async Task DownloadToFileAsync(string url, string destinationPath, bool overwrite)
|
||||||
{
|
{
|
||||||
using var response = await _httpClient.GetResponseAsync(url);
|
using var response = await RetryRequest(() => _httpClient.GetResponseAsync(url));
|
||||||
await WriteToFileAsync(await response.Stream, destinationPath, overwrite);
|
await WriteToFileAsync(await response.Stream, destinationPath, overwrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal async Task<string> DownloadGivenOption(string url, CommandOption fileOption)
|
internal async Task<string> DownloadGivenOption(string url, CommandOption fileOption)
|
||||||
{
|
{
|
||||||
using var response = await _httpClient.GetResponseAsync(url);
|
using var response = await RetryRequest(() => _httpClient.GetResponseAsync(url));
|
||||||
|
|
||||||
if (response.IsSuccessCode())
|
if (response.IsSuccessCode())
|
||||||
{
|
{
|
||||||
|
|
@ -272,6 +275,56 @@ namespace Microsoft.DotNet.OpenApi.Commands
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retries every 1 sec for 60 times by default.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="retryBlock"></param>
|
||||||
|
/// <param name="logger"></param>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
|
/// <param name="retryCount"></param>
|
||||||
|
private static async Task<IHttpResponseMessageWrapper> RetryRequest(
|
||||||
|
Func<Task<IHttpResponseMessageWrapper>> retryBlock,
|
||||||
|
CancellationToken cancellationToken = default,
|
||||||
|
int retryCount = 60)
|
||||||
|
{
|
||||||
|
for (var retry = 0; retry < retryCount; retry++)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
throw new OperationCanceledException("Failed to connect, retry canceled.", cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var response = await retryBlock().ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (response.StatusCode == HttpStatusCode.ServiceUnavailable)
|
||||||
|
{
|
||||||
|
// Automatically retry on 503. May be application is still booting.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return response; // Went through successfully
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
if (retry == retryCount - 1)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (exception is HttpRequestException || exception is WebException)
|
||||||
|
{
|
||||||
|
await Task.Delay(1 * 1000); //Wait for a while before retry.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new OperationCanceledException("Failed to connect, retry limit exceeded.");
|
||||||
|
}
|
||||||
|
|
||||||
private string GetUniqueFileName(string directory, string fileName, string extension)
|
private string GetUniqueFileName(string directory, string fileName, string extension)
|
||||||
{
|
{
|
||||||
var uniqueName = fileName;
|
var uniqueName = fileName;
|
||||||
|
|
|
||||||
|
|
@ -440,8 +440,8 @@ namespace Microsoft.DotNet.OpenApi.Add.Tests
|
||||||
var url = BrokenUrl;
|
var url = BrokenUrl;
|
||||||
var run = app.Execute(new[] { "add", "url", url });
|
var run = app.Execute(new[] { "add", "url", url });
|
||||||
|
|
||||||
Assert.Equal(_error.ToString(), $"The given url returned 'NotFound', " +
|
Assert.Equal($"The given url returned 'NotFound', " +
|
||||||
"indicating failure. The url might be wrong, or there might be a networking issue."+Environment.NewLine);
|
"indicating failure. The url might be wrong, or there might be a networking issue."+Environment.NewLine, _error.ToString());
|
||||||
Assert.Equal(1, run);
|
Assert.Equal(1, run);
|
||||||
|
|
||||||
var expectedJsonName = "dingos.json";
|
var expectedJsonName = "dingos.json";
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue