Merge branch 'release/3.1' into merge/release/3.0-to-release/3.1\n\nCommit migrated from 9df988bece
This commit is contained in:
commit
2cad3cc344
|
|
@ -1,15 +1,15 @@
|
||||||
<!-- This file is automatically generated. -->
|
<!-- This file is automatically generated. -->
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netstandard2.0;netcoreapp3.0</TargetFrameworks>
|
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
||||||
<Compile Include="Microsoft.Extensions.Configuration.KeyPerFile.netstandard2.0.cs" />
|
<Compile Include="Microsoft.Extensions.Configuration.KeyPerFile.netstandard2.0.cs" />
|
||||||
<Reference Include="Microsoft.Extensions.Configuration" />
|
<Reference Include="Microsoft.Extensions.Configuration" />
|
||||||
<Reference Include="Microsoft.Extensions.FileProviders.Physical" />
|
<Reference Include="Microsoft.Extensions.FileProviders.Physical" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
|
<ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'">
|
||||||
<Compile Include="Microsoft.Extensions.Configuration.KeyPerFile.netcoreapp3.0.cs" />
|
<Compile Include="Microsoft.Extensions.Configuration.KeyPerFile.netcoreapp.cs" />
|
||||||
<Reference Include="Microsoft.Extensions.Configuration" />
|
<Reference Include="Microsoft.Extensions.Configuration" />
|
||||||
<Reference Include="Microsoft.Extensions.FileProviders.Physical" />
|
<Reference Include="Microsoft.Extensions.FileProviders.Physical" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Description>Configuration provider that uses files in a directory for Microsoft.Extensions.Configuration.</Description>
|
<Description>Configuration provider that uses files in a directory for Microsoft.Extensions.Configuration.</Description>
|
||||||
<TargetFrameworks>netstandard2.0;netcoreapp3.0</TargetFrameworks>
|
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks>
|
||||||
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">netcoreapp3.0</TargetFrameworks>
|
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">$(DefaultNetCoreTargetFramework)</TargetFrameworks>
|
||||||
<IsPackable>true</IsPackable>
|
<IsPackable>true</IsPackable>
|
||||||
<IsShipping>true</IsShipping>
|
<IsShipping>true</IsShipping>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks>
|
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net472</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
<!-- This file is automatically generated. -->
|
<!-- This file is automatically generated. -->
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netstandard2.0;netcoreapp3.0</TargetFrameworks>
|
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
||||||
<Compile Include="Microsoft.Extensions.FileProviders.Embedded.netstandard2.0.cs" />
|
<Compile Include="Microsoft.Extensions.FileProviders.Embedded.netstandard2.0.cs" />
|
||||||
<Reference Include="Microsoft.Extensions.FileProviders.Abstractions" />
|
<Reference Include="Microsoft.Extensions.FileProviders.Abstractions" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
|
<ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'">
|
||||||
<Compile Include="Microsoft.Extensions.FileProviders.Embedded.netcoreapp3.0.cs" />
|
<Compile Include="Microsoft.Extensions.FileProviders.Embedded.netcoreapp.cs" />
|
||||||
<Reference Include="Microsoft.Extensions.FileProviders.Abstractions" />
|
<Reference Include="Microsoft.Extensions.FileProviders.Abstractions" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<RootNamespace>Microsoft.Extensions.FileProviders</RootNamespace>
|
<RootNamespace>Microsoft.Extensions.FileProviders</RootNamespace>
|
||||||
<Description>File provider for files in embedded resources for Microsoft.Extensions.FileProviders.</Description>
|
<Description>File provider for files in embedded resources for Microsoft.Extensions.FileProviders.</Description>
|
||||||
<TargetFrameworks>netstandard2.0;netcoreapp3.0</TargetFrameworks>
|
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks>
|
||||||
<NuspecFile>$(MSBuildProjectName).multitarget.nuspec</NuspecFile>
|
<NuspecFile>$(MSBuildProjectName).multitarget.nuspec</NuspecFile>
|
||||||
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">netcoreapp3.0</TargetFrameworks>
|
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">$(DefaultNetCoreTargetFramework)</TargetFrameworks>
|
||||||
<NuspecFile Condition="'$(DotNetBuildFromSource)' == 'true'">$(MSBuildProjectName).netcoreapp3.0.nuspec</NuspecFile>
|
<NuspecFile Condition="'$(DotNetBuildFromSource)' == 'true'">$(MSBuildProjectName).netcoreapp.nuspec</NuspecFile>
|
||||||
<IsPackable>true</IsPackable>
|
<IsPackable>true</IsPackable>
|
||||||
<IsShipping>true</IsShipping>
|
<IsShipping>true</IsShipping>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
@ -27,9 +27,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<NuspecProperty Include="AssemblyName=$(AssemblyName)" />
|
<NuspecProperty Include="AssemblyName=$(AssemblyName)" />
|
||||||
<NuspecProperty Include="OutputBinary=$(OutputPath)**\$(AssemblyName).dll" />
|
<NuspecProperty Include="OutputPath=$(OutputPath)" />
|
||||||
<NuspecProperty Include="OutputSymbol=$(OutputPath)**\$(AssemblyName).pdb" />
|
|
||||||
<NuspecProperty Include="OutputDocumentation=$(OutputPath)**\$(AssemblyName).xml" />
|
|
||||||
<NuspecProperty Include="TaskAssemblyNetStandard=$(ArtifactsDir)bin\$(AssemblyName).Manifest.Task\$(Configuration)\netstandard2.0\$(AssemblyName).Manifest.Task.dll"/>
|
<NuspecProperty Include="TaskAssemblyNetStandard=$(ArtifactsDir)bin\$(AssemblyName).Manifest.Task\$(Configuration)\netstandard2.0\$(AssemblyName).Manifest.Task.dll"/>
|
||||||
<NuspecProperty Include="TaskSymbolNetStandard=$(ArtifactsDir)bin\$(AssemblyName).Manifest.Task\$(Configuration)\netstandard2.0\$(AssemblyName).Manifest.Task.pdb" Condition="'$(DebugType)'!='embedded'"/>
|
<NuspecProperty Include="TaskSymbolNetStandard=$(ArtifactsDir)bin\$(AssemblyName).Manifest.Task\$(Configuration)\netstandard2.0\$(AssemblyName).Manifest.Task.pdb" Condition="'$(DebugType)'!='embedded'"/>
|
||||||
<NuspecProperty Include="PackageIcon=$(PackageIconFullPath)" />
|
<NuspecProperty Include="PackageIcon=$(PackageIconFullPath)" />
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<metadata>
|
<metadata>
|
||||||
$CommonMetadataElements$
|
$CommonMetadataElements$
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<group targetFramework=".NETCoreApp3.0">
|
<group targetFramework=".NETCoreApp3.1">
|
||||||
<dependency id="Microsoft.Extensions.FileProviders.Abstractions" version="$version$" exclude="Build,Analyzers" />
|
<dependency id="Microsoft.Extensions.FileProviders.Abstractions" version="$version$" exclude="Build,Analyzers" />
|
||||||
</group>
|
</group>
|
||||||
<group targetFramework=".NETStandard2.0">
|
<group targetFramework=".NETStandard2.0">
|
||||||
|
|
@ -14,9 +14,9 @@
|
||||||
</metadata>
|
</metadata>
|
||||||
|
|
||||||
<files>
|
<files>
|
||||||
<file src="$OutputBinary$" target="lib\" />
|
<file src="$OutputPath$**\$AssemblyName$.dll" target="lib\" />
|
||||||
<file src="$OutputSymbol$" target="lib\" />
|
<file src="$OutputPath$**\$AssemblyName$.pdb" target="lib\" />
|
||||||
<file src="$OutputDocumentation$" target="lib\" />
|
<file src="$OutputPath$**\$AssemblyName$.xml" target="lib\" />
|
||||||
<file src="build\**\*" target="build\" />
|
<file src="build\**\*" target="build\" />
|
||||||
<file src="buildMultiTargeting\**\*" target="buildMultiTargeting\" />
|
<file src="buildMultiTargeting\**\*" target="buildMultiTargeting\" />
|
||||||
<file src="$PackageIcon$" target="" />
|
<file src="$PackageIcon$" target="" />
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<metadata>
|
<metadata>
|
||||||
$CommonMetadataElements$
|
$CommonMetadataElements$
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<group targetFramework=".NETCoreApp3.0">
|
<group targetFramework=".NETCoreApp3.1">
|
||||||
<dependency id="Microsoft.Extensions.FileProviders.Abstractions" version="$version$" exclude="Build,Analyzers" />
|
<dependency id="Microsoft.Extensions.FileProviders.Abstractions" version="$version$" exclude="Build,Analyzers" />
|
||||||
</group>
|
</group>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
@ -11,9 +11,9 @@
|
||||||
</metadata>
|
</metadata>
|
||||||
|
|
||||||
<files>
|
<files>
|
||||||
<file src="$OutputBinary$" target="lib\" />
|
<file src="$OutputPath$**\$AssemblyName$.dll" target="lib\" />
|
||||||
<file src="$OutputSymbol$" target="lib\" />
|
<file src="$OutputPath$**\$AssemblyName$.pdb" target="lib\" />
|
||||||
<file src="$OutputDocumentation$" target="lib\" />
|
<file src="$OutputPath$**\$AssemblyName$.xml" target="lib\" />
|
||||||
<file src="build\**\*" target="build\" />
|
<file src="build\**\*" target="build\" />
|
||||||
<file src="buildMultiTargeting\**\*" target="buildMultiTargeting\" />
|
<file src="buildMultiTargeting\**\*" target="buildMultiTargeting\" />
|
||||||
<file src="$PackageIcon$" target="" />
|
<file src="$PackageIcon$" target="" />
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks>
|
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net472</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
<!-- This file is automatically generated. -->
|
<!-- This file is automatically generated. -->
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netstandard2.0;netcoreapp3.0</TargetFrameworks>
|
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
||||||
<Compile Include="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions.netstandard2.0.cs" />
|
<Compile Include="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions.netstandard2.0.cs" />
|
||||||
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
|
<ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'">
|
||||||
<Compile Include="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions.netcoreapp3.0.cs" />
|
<Compile Include="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions.netcoreapp.cs" />
|
||||||
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ Commonly Used Types
|
||||||
Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck
|
Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck
|
||||||
</Description>
|
</Description>
|
||||||
<RootNamespace>Microsoft.Extensions.Diagnostics.HealthChecks</RootNamespace>
|
<RootNamespace>Microsoft.Extensions.Diagnostics.HealthChecks</RootNamespace>
|
||||||
<TargetFrameworks>netstandard2.0;netcoreapp3.0</TargetFrameworks>
|
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks>
|
||||||
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">netcoreapp3.0</TargetFrameworks>
|
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">$(DefaultNetCoreTargetFramework)</TargetFrameworks>
|
||||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<PackageTags>diagnostics;healthchecks</PackageTags>
|
<PackageTags>diagnostics;healthchecks</PackageTags>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<!-- This file is automatically generated. -->
|
<!-- This file is automatically generated. -->
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netstandard2.0;netcoreapp3.0</TargetFrameworks>
|
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
||||||
<Compile Include="Microsoft.Extensions.Diagnostics.HealthChecks.netstandard2.0.cs" />
|
<Compile Include="Microsoft.Extensions.Diagnostics.HealthChecks.netstandard2.0.cs" />
|
||||||
|
|
@ -9,8 +9,8 @@
|
||||||
<Reference Include="Microsoft.Extensions.Hosting.Abstractions" />
|
<Reference Include="Microsoft.Extensions.Hosting.Abstractions" />
|
||||||
<Reference Include="Microsoft.Extensions.Options" />
|
<Reference Include="Microsoft.Extensions.Options" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
|
<ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'">
|
||||||
<Compile Include="Microsoft.Extensions.Diagnostics.HealthChecks.netcoreapp3.0.cs" />
|
<Compile Include="Microsoft.Extensions.Diagnostics.HealthChecks.netcoreapp.cs" />
|
||||||
<Reference Include="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions" />
|
<Reference Include="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions" />
|
||||||
<Reference Include="Microsoft.Extensions.Hosting.Abstractions" />
|
<Reference Include="Microsoft.Extensions.Hosting.Abstractions" />
|
||||||
<Reference Include="Microsoft.Extensions.Options" />
|
<Reference Include="Microsoft.Extensions.Options" />
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ Commonly Used Types:
|
||||||
Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckService
|
Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckService
|
||||||
Microsoft.Extensions.Diagnostics.HealthChecks.IHealthChecksBuilder
|
Microsoft.Extensions.Diagnostics.HealthChecks.IHealthChecksBuilder
|
||||||
</Description>
|
</Description>
|
||||||
<TargetFrameworks>netstandard2.0;netcoreapp3.0</TargetFrameworks>
|
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks>
|
||||||
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">netcoreapp3.0</TargetFrameworks>
|
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">$(DefaultNetCoreTargetFramework)</TargetFrameworks>
|
||||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<PackageTags>diagnostics;healthchecks</PackageTags>
|
<PackageTags>diagnostics;healthchecks</PackageTags>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<Import Project="$(RepoRoot)src\Logging\Logging.Testing\src\build\Microsoft.Extensions.Logging.Testing.props" />
|
<Import Project="$(RepoRoot)src\Logging\Logging.Testing\src\build\Microsoft.Extensions.Logging.Testing.props" />
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks>
|
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net472</TargetFrameworks>
|
||||||
<RootNamespace>Microsoft.Extensions.Diagnostics.HealthChecks</RootNamespace>
|
<RootNamespace>Microsoft.Extensions.Diagnostics.HealthChecks</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
<!-- This file is automatically generated. -->
|
<!-- This file is automatically generated. -->
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netstandard2.0;netcoreapp3.0</TargetFrameworks>
|
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
||||||
<Compile Include="Microsoft.JSInterop.netstandard2.0.cs" />
|
<Compile Include="Microsoft.JSInterop.netstandard2.0.cs" />
|
||||||
<Reference Include="System.Text.Json" />
|
<Reference Include="System.Text.Json" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
|
<ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'">
|
||||||
<Compile Include="Microsoft.JSInterop.netcoreapp3.0.cs" />
|
<Compile Include="Microsoft.JSInterop.netcoreapp.cs" />
|
||||||
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Microsoft.JSInterop
|
namespace Microsoft.JSInterop
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -15,6 +17,11 @@ namespace Microsoft.JSInterop
|
||||||
/// <returns>An instance of <see cref="DotNetObjectReference{TValue}" />.</returns>
|
/// <returns>An instance of <see cref="DotNetObjectReference{TValue}" />.</returns>
|
||||||
public static DotNetObjectReference<TValue> Create<TValue>(TValue value) where TValue : class
|
public static DotNetObjectReference<TValue> Create<TValue>(TValue value) where TValue : class
|
||||||
{
|
{
|
||||||
|
if (value is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(value));
|
||||||
|
}
|
||||||
|
|
||||||
return new DotNetObjectReference<TValue>(value);
|
return new DotNetObjectReference<TValue>(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,9 @@ namespace Microsoft.JSInterop.Infrastructure
|
||||||
private static readonly ConcurrentDictionary<AssemblyKey, IReadOnlyDictionary<string, (MethodInfo, Type[])>> _cachedMethodsByAssembly
|
private static readonly ConcurrentDictionary<AssemblyKey, IReadOnlyDictionary<string, (MethodInfo, Type[])>> _cachedMethodsByAssembly
|
||||||
= new ConcurrentDictionary<AssemblyKey, IReadOnlyDictionary<string, (MethodInfo, Type[])>>();
|
= new ConcurrentDictionary<AssemblyKey, IReadOnlyDictionary<string, (MethodInfo, Type[])>>();
|
||||||
|
|
||||||
|
private static readonly ConcurrentDictionary<Type, IReadOnlyDictionary<string, (MethodInfo, Type[])>> _cachedMethodsByType
|
||||||
|
= new ConcurrentDictionary<Type, IReadOnlyDictionary<string, (MethodInfo, Type[])>>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Receives a call from JS to .NET, locating and invoking the specified method.
|
/// Receives a call from JS to .NET, locating and invoking the specified method.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -129,9 +132,12 @@ namespace Microsoft.JSInterop.Infrastructure
|
||||||
var methodIdentifier = callInfo.MethodIdentifier;
|
var methodIdentifier = callInfo.MethodIdentifier;
|
||||||
|
|
||||||
AssemblyKey assemblyKey;
|
AssemblyKey assemblyKey;
|
||||||
|
MethodInfo methodInfo;
|
||||||
|
Type[] parameterTypes;
|
||||||
if (objectReference is null)
|
if (objectReference is null)
|
||||||
{
|
{
|
||||||
assemblyKey = new AssemblyKey(assemblyName);
|
assemblyKey = new AssemblyKey(assemblyName);
|
||||||
|
(methodInfo, parameterTypes) = GetCachedMethodInfo(assemblyKey, methodIdentifier);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -147,11 +153,9 @@ namespace Microsoft.JSInterop.Infrastructure
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
assemblyKey = new AssemblyKey(objectReference.Value.GetType().Assembly);
|
(methodInfo, parameterTypes) = GetCachedMethodInfo(objectReference, methodIdentifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
var (methodInfo, parameterTypes) = GetCachedMethodInfo(assemblyKey, methodIdentifier);
|
|
||||||
|
|
||||||
var suppliedArgs = ParseArguments(jsRuntime, methodIdentifier, argsJson, parameterTypes);
|
var suppliedArgs = ParseArguments(jsRuntime, methodIdentifier, argsJson, parameterTypes);
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
@ -301,7 +305,47 @@ namespace Microsoft.JSInterop.Infrastructure
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"The assembly '{assemblyKey.AssemblyName}' does not contain a public method with [{nameof(JSInvokableAttribute)}(\"{methodIdentifier}\")].");
|
throw new ArgumentException($"The assembly '{assemblyKey.AssemblyName}' does not contain a public invokable method with [{nameof(JSInvokableAttribute)}(\"{methodIdentifier}\")].");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static (MethodInfo methodInfo, Type[] parameterTypes) GetCachedMethodInfo(IDotNetObjectReference objectReference, string methodIdentifier)
|
||||||
|
{
|
||||||
|
var type = objectReference.Value.GetType();
|
||||||
|
var assemblyMethods = _cachedMethodsByType.GetOrAdd(type, ScanTypeForCallableMethods);
|
||||||
|
if (assemblyMethods.TryGetValue(methodIdentifier, out var result))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"The type '{type.Name}' does not contain a public invokable method with [{nameof(JSInvokableAttribute)}(\"{methodIdentifier}\")].");
|
||||||
|
}
|
||||||
|
|
||||||
|
static Dictionary<string, (MethodInfo, Type[])> ScanTypeForCallableMethods(Type type)
|
||||||
|
{
|
||||||
|
var result = new Dictionary<string, (MethodInfo, Type[])>(StringComparer.Ordinal);
|
||||||
|
var invokableMethods = type
|
||||||
|
.GetMethods(BindingFlags.Public | BindingFlags.Instance)
|
||||||
|
.Where(method => !method.ContainsGenericParameters && method.IsDefined(typeof(JSInvokableAttribute), inherit: false));
|
||||||
|
|
||||||
|
foreach (var method in invokableMethods)
|
||||||
|
{
|
||||||
|
var identifier = method.GetCustomAttribute<JSInvokableAttribute>(false).Identifier ?? method.Name;
|
||||||
|
var parameterTypes = method.GetParameters().Select(p => p.ParameterType).ToArray();
|
||||||
|
|
||||||
|
if (result.ContainsKey(identifier))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"The type {type.Name} contains more than one " +
|
||||||
|
$"[JSInvokable] method with identifier '{identifier}'. All [JSInvokable] methods within the same " +
|
||||||
|
$"type must have different identifiers. You can pass a custom identifier as a parameter to " +
|
||||||
|
$"the [JSInvokable] attribute.");
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Add(identifier, (method, parameterTypes));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -312,35 +356,22 @@ namespace Microsoft.JSInterop.Infrastructure
|
||||||
var result = new Dictionary<string, (MethodInfo, Type[])>(StringComparer.Ordinal);
|
var result = new Dictionary<string, (MethodInfo, Type[])>(StringComparer.Ordinal);
|
||||||
var invokableMethods = GetRequiredLoadedAssembly(assemblyKey)
|
var invokableMethods = GetRequiredLoadedAssembly(assemblyKey)
|
||||||
.GetExportedTypes()
|
.GetExportedTypes()
|
||||||
.SelectMany(type => type.GetMethods(
|
.SelectMany(type => type.GetMethods(BindingFlags.Public | BindingFlags.Static))
|
||||||
BindingFlags.Public |
|
.Where(method => !method.ContainsGenericParameters && method.IsDefined(typeof(JSInvokableAttribute), inherit: false));
|
||||||
BindingFlags.DeclaredOnly |
|
|
||||||
BindingFlags.Instance |
|
|
||||||
BindingFlags.Static))
|
|
||||||
.Where(method => method.IsDefined(typeof(JSInvokableAttribute), inherit: false));
|
|
||||||
foreach (var method in invokableMethods)
|
foreach (var method in invokableMethods)
|
||||||
{
|
{
|
||||||
var identifier = method.GetCustomAttribute<JSInvokableAttribute>(false).Identifier ?? method.Name;
|
var identifier = method.GetCustomAttribute<JSInvokableAttribute>(false).Identifier ?? method.Name;
|
||||||
var parameterTypes = method.GetParameters().Select(p => p.ParameterType).ToArray();
|
var parameterTypes = method.GetParameters().Select(p => p.ParameterType).ToArray();
|
||||||
|
|
||||||
try
|
if (result.ContainsKey(identifier))
|
||||||
{
|
{
|
||||||
result.Add(identifier, (method, parameterTypes));
|
throw new InvalidOperationException($"The assembly '{assemblyKey.AssemblyName}' contains more than one " +
|
||||||
}
|
$"[JSInvokable] method with identifier '{identifier}'. All [JSInvokable] methods within the same " +
|
||||||
catch (ArgumentException)
|
$"assembly must have different identifiers. You can pass a custom identifier as a parameter to " +
|
||||||
{
|
$"the [JSInvokable] attribute.");
|
||||||
if (result.ContainsKey(identifier))
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"The assembly '{assemblyKey.AssemblyName}' contains more than one " +
|
|
||||||
$"[JSInvokable] method with identifier '{identifier}'. All [JSInvokable] methods within the same " +
|
|
||||||
$"assembly must have different identifiers. You can pass a custom identifier as a parameter to " +
|
|
||||||
$"the [JSInvokable] attribute.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result.Add(identifier, (method, parameterTypes));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netstandard2.0;netcoreapp3.0</TargetFrameworks>
|
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks>
|
||||||
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">netcoreapp3.0</TargetFrameworks>
|
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">$(DefaultNetCoreTargetFramework)</TargetFrameworks>
|
||||||
<Description>Abstractions and features for interop between .NET and JavaScript code.</Description>
|
<Description>Abstractions and features for interop between .NET and JavaScript code.</Description>
|
||||||
<PackageTags>javascript;interop</PackageTags>
|
<PackageTags>javascript;interop</PackageTags>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.ExceptionServices;
|
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
@ -70,7 +69,7 @@ namespace Microsoft.JSInterop.Infrastructure
|
||||||
DotNetDispatcher.Invoke(new TestJSRuntime(), new DotNetInvocationInfo(thisAssemblyName, methodIdentifier, default, default), null);
|
DotNetDispatcher.Invoke(new TestJSRuntime(), new DotNetInvocationInfo(thisAssemblyName, methodIdentifier, default, default), null);
|
||||||
});
|
});
|
||||||
|
|
||||||
Assert.Equal($"The assembly '{thisAssemblyName}' does not contain a public method with [JSInvokableAttribute(\"{methodIdentifier}\")].", ex.Message);
|
Assert.Equal($"The assembly '{thisAssemblyName}' does not contain a public invokable method with [JSInvokableAttribute(\"{methodIdentifier}\")].", ex.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -355,6 +354,78 @@ namespace Microsoft.JSInterop.Infrastructure
|
||||||
Assert.Equal("MY STRING", resultDto.StringVal);
|
Assert.Equal("MY STRING", resultDto.StringVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanInvokeNonGenericInstanceMethodOnGenericType()
|
||||||
|
{
|
||||||
|
var jsRuntime = new TestJSRuntime();
|
||||||
|
var targetInstance = new GenericType<int>();
|
||||||
|
jsRuntime.Invoke<object>("_setup",
|
||||||
|
DotNetObjectReference.Create(targetInstance));
|
||||||
|
var argsJson = "[\"hello world\"]";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var resultJson = DotNetDispatcher.Invoke(jsRuntime, new DotNetInvocationInfo(null, nameof(GenericType<int>.EchoStringParameter), 1, default), argsJson);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal("\"hello world\"", resultJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanInvokeMethodsThatAcceptGenericParametersOnGenericTypes()
|
||||||
|
{
|
||||||
|
var jsRuntime = new TestJSRuntime();
|
||||||
|
var targetInstance = new GenericType<string>();
|
||||||
|
jsRuntime.Invoke<object>("_setup",
|
||||||
|
DotNetObjectReference.Create(targetInstance));
|
||||||
|
var argsJson = "[\"hello world\"]";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var resultJson = DotNetDispatcher.Invoke(jsRuntime, new DotNetInvocationInfo(null, nameof(GenericType<string>.EchoParameter), 1, default), argsJson);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal("\"hello world\"", resultJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CannotInvokeStaticOpenGenericMethods()
|
||||||
|
{
|
||||||
|
var methodIdentifier = "StaticGenericMethod";
|
||||||
|
var jsRuntime = new TestJSRuntime();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var ex = Assert.Throws<ArgumentException>(() => DotNetDispatcher.Invoke(jsRuntime, new DotNetInvocationInfo(thisAssemblyName, methodIdentifier, 0, default), "[7]"));
|
||||||
|
Assert.Contains($"The assembly '{thisAssemblyName}' does not contain a public invokable method with [{nameof(JSInvokableAttribute)}(\"{methodIdentifier}\")].", ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CannotInvokeInstanceOpenGenericMethods()
|
||||||
|
{
|
||||||
|
var methodIdentifier = "InstanceGenericMethod";
|
||||||
|
var targetInstance = new GenericType<int>();
|
||||||
|
var jsRuntime = new TestJSRuntime();
|
||||||
|
jsRuntime.Invoke<object>("_setup",
|
||||||
|
DotNetObjectReference.Create(targetInstance));
|
||||||
|
var argsJson = "[\"hello world\"]";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var ex = Assert.Throws<ArgumentException>(() => DotNetDispatcher.Invoke(jsRuntime, new DotNetInvocationInfo(null, methodIdentifier, 1, default), argsJson));
|
||||||
|
Assert.Contains($"The type 'GenericType`1' does not contain a public invokable method with [{nameof(JSInvokableAttribute)}(\"{methodIdentifier}\")].", ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CannotInvokeMethodsWithGenericParameters_IfTypesDoNotMatch()
|
||||||
|
{
|
||||||
|
var jsRuntime = new TestJSRuntime();
|
||||||
|
var targetInstance = new GenericType<int>();
|
||||||
|
jsRuntime.Invoke<object>("_setup",
|
||||||
|
DotNetObjectReference.Create(targetInstance));
|
||||||
|
var argsJson = "[\"hello world\"]";
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
Assert.Throws<JsonException>(() =>
|
||||||
|
DotNetDispatcher.Invoke(jsRuntime, new DotNetInvocationInfo(null, nameof(GenericType<int>.EchoParameter), 1, default), argsJson));
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CannotInvokeWithFewerNumberOfParameters()
|
public void CannotInvokeWithFewerNumberOfParameters()
|
||||||
{
|
{
|
||||||
|
|
@ -790,6 +861,18 @@ namespace Microsoft.JSInterop.Infrastructure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class GenericType<TValue>
|
||||||
|
{
|
||||||
|
[JSInvokable] public string EchoStringParameter(string input) => input;
|
||||||
|
[JSInvokable] public TValue EchoParameter(TValue input) => input;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GenericMethodClass
|
||||||
|
{
|
||||||
|
[JSInvokable("StaticGenericMethod")] public static string StaticGenericMethod<TValue>(TValue input) => input.ToString();
|
||||||
|
[JSInvokable("InstanceGenericMethod")] public string GenericMethod<TValue>(TValue input) => input.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
public class TestJSRuntime : JSInProcessRuntime
|
public class TestJSRuntime : JSInProcessRuntime
|
||||||
{
|
{
|
||||||
private TaskCompletionSource<object> _nextInvocationTcs = new TaskCompletionSource<object>();
|
private TaskCompletionSource<object> _nextInvocationTcs = new TaskCompletionSource<object>();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks>
|
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net472</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
<!-- This file is automatically generated. -->
|
<!-- This file is automatically generated. -->
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netstandard2.0;netcoreapp3.0</TargetFrameworks>
|
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
||||||
<Compile Include="Microsoft.Extensions.Localization.Abstractions.netstandard2.0.cs" />
|
<Compile Include="Microsoft.Extensions.Localization.Abstractions.netstandard2.0.cs" />
|
||||||
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
|
<ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'">
|
||||||
<Compile Include="Microsoft.Extensions.Localization.Abstractions.netcoreapp3.0.cs" />
|
<Compile Include="Microsoft.Extensions.Localization.Abstractions.netcoreapp.cs" />
|
||||||
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@
|
||||||
Commonly used types:
|
Commonly used types:
|
||||||
Microsoft.Extensions.Localization.IStringLocalizer
|
Microsoft.Extensions.Localization.IStringLocalizer
|
||||||
Microsoft.Extensions.Localization.IStringLocalizer<T></Description>
|
Microsoft.Extensions.Localization.IStringLocalizer<T></Description>
|
||||||
<TargetFrameworks>netstandard2.0;netcoreapp3.0</TargetFrameworks>
|
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks>
|
||||||
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">netcoreapp3.0</TargetFrameworks>
|
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">$(DefaultNetCoreTargetFramework)</TargetFrameworks>
|
||||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<PackageTags>localization</PackageTags>
|
<PackageTags>localization</PackageTags>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<!-- This file is automatically generated. -->
|
<!-- This file is automatically generated. -->
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netstandard2.0;netcoreapp3.0</TargetFrameworks>
|
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
||||||
<Compile Include="Microsoft.Extensions.Localization.netstandard2.0.cs" />
|
<Compile Include="Microsoft.Extensions.Localization.netstandard2.0.cs" />
|
||||||
|
|
@ -10,8 +10,8 @@
|
||||||
<Reference Include="Microsoft.Extensions.Localization.Abstractions" />
|
<Reference Include="Microsoft.Extensions.Localization.Abstractions" />
|
||||||
<Reference Include="Microsoft.Extensions.Logging.Abstractions" />
|
<Reference Include="Microsoft.Extensions.Logging.Abstractions" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
|
<ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'">
|
||||||
<Compile Include="Microsoft.Extensions.Localization.netcoreapp3.0.cs" />
|
<Compile Include="Microsoft.Extensions.Localization.netcoreapp.cs" />
|
||||||
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||||
<Reference Include="Microsoft.Extensions.Options" />
|
<Reference Include="Microsoft.Extensions.Options" />
|
||||||
<Reference Include="Microsoft.Extensions.Localization.Abstractions" />
|
<Reference Include="Microsoft.Extensions.Localization.Abstractions" />
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Product>Microsoft .NET Extensions</Product>
|
<Product>Microsoft .NET Extensions</Product>
|
||||||
<Description>Application localization services and default implementation based on ResourceManager to load localized assembly resources.</Description>
|
<Description>Application localization services and default implementation based on ResourceManager to load localized assembly resources.</Description>
|
||||||
<TargetFrameworks>netstandard2.0;netcoreapp3.0</TargetFrameworks>
|
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks>
|
||||||
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">netcoreapp3.0</TargetFrameworks>
|
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">$(DefaultNetCoreTargetFramework)</TargetFrameworks>
|
||||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<PackageTags>localization</PackageTags>
|
<PackageTags>localization</PackageTags>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks>
|
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net472</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks>
|
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net472</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -402,7 +402,7 @@ namespace Microsoft.Extensions.Internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NETCOREAPP3_0
|
#if NETCOREAPP
|
||||||
return _constructor.Invoke(BindingFlags.DoNotWrapExceptions, binder: null, parameters: _parameterValues, culture: null);
|
return _constructor.Invoke(BindingFlags.DoNotWrapExceptions, binder: null, parameters: _parameterValues, culture: null);
|
||||||
#else
|
#else
|
||||||
try
|
try
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,12 @@ namespace BenchmarkDotNet.Attributes
|
||||||
Add(Job.Core
|
Add(Job.Core
|
||||||
#if NETCOREAPP2_1
|
#if NETCOREAPP2_1
|
||||||
.With(CsProjCoreToolchain.From(NetCoreAppSettings.NetCoreApp21))
|
.With(CsProjCoreToolchain.From(NetCoreAppSettings.NetCoreApp21))
|
||||||
#else
|
#elif NETCOREAPP3_0
|
||||||
.With(CsProjCoreToolchain.From(new NetCoreAppSettings("netcoreapp3.0", null, ".NET Core 3.0")))
|
.With(CsProjCoreToolchain.From(new NetCoreAppSettings("netcoreapp3.0", null, ".NET Core 3.0")))
|
||||||
|
#elif NETCOREAPP3_1
|
||||||
|
.With(CsProjCoreToolchain.From(new NetCoreAppSettings("netcoreapp3.1", null, ".NET Core 3.1")))
|
||||||
|
#else
|
||||||
|
#error Target frameworks need to be updated.
|
||||||
#endif
|
#endif
|
||||||
.With(new GcMode { Server = true })
|
.With(new GcMode { Server = true })
|
||||||
.With(RunStrategy.Throughput));
|
.With(RunStrategy.Throughput));
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
#if NETCOREAPP3_0
|
#if NETCOREAPP
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks>
|
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net472</TargetFrameworks>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks>
|
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net472</TargetFrameworks>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks>
|
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net472</TargetFrameworks>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks>
|
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net472</TargetFrameworks>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks>
|
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net472</TargetFrameworks>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks>
|
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net472</TargetFrameworks>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks>
|
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net472</TargetFrameworks>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks>
|
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net472</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
// 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 Microsoft.AspNetCore.Testing
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines a lifecycle for attributes or classes that want to know about tests starting
|
||||||
|
/// or ending. Implement this on a test class, or attribute at the method/class/assembly level.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Requires defining <see cref="AspNetTestFramework"/> as the test framework.
|
||||||
|
/// </remarks>
|
||||||
|
public interface ITestMethodLifecycle
|
||||||
|
{
|
||||||
|
Task OnTestStartAsync(TestContext context, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
Task OnTestEndAsync(TestContext context, Exception exception, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
// 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.ComponentModel;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Testing
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Runs a test multiple times to stress flaky tests that are believed to be fixed.
|
||||||
|
/// This can be used on an assembly, class, or method name. Requires using the AspNetCore test framework.
|
||||||
|
/// </summary>
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly, AllowMultiple = false)]
|
||||||
|
public class RepeatAttribute : Attribute
|
||||||
|
{
|
||||||
|
public RepeatAttribute(int runCount = 10)
|
||||||
|
{
|
||||||
|
RunCount = runCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The number of times to run a test.
|
||||||
|
/// </summary>
|
||||||
|
public int RunCount { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
// 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.Threading;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Testing
|
||||||
|
{
|
||||||
|
public class RepeatContext
|
||||||
|
{
|
||||||
|
private static AsyncLocal<RepeatContext> _current = new AsyncLocal<RepeatContext>();
|
||||||
|
|
||||||
|
public static RepeatContext Current
|
||||||
|
{
|
||||||
|
get => _current.Value;
|
||||||
|
internal set => _current.Value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RepeatContext(int limit)
|
||||||
|
{
|
||||||
|
Limit = limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Limit { get; }
|
||||||
|
|
||||||
|
public int CurrentIteration { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Testing
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Used to specify that <see cref="TestFileOutputContext.TestClassName"/> should used the
|
||||||
|
/// unqualified class name. This is needed when a fully-qualified class name exceeds
|
||||||
|
/// max path for logging.
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Assembly, AllowMultiple = false)]
|
||||||
|
public class ShortClassNameAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
// 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.Reflection;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Testing
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides access to contextual information about the running tests. Get access by
|
||||||
|
/// implementing <see cref="ITestMethodLifecycle"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Requires defining <see cref="AspNetTestFramework"/> as the test framework.
|
||||||
|
/// </remarks>
|
||||||
|
public sealed class TestContext
|
||||||
|
{
|
||||||
|
private Lazy<TestFileOutputContext> _files;
|
||||||
|
|
||||||
|
public TestContext(
|
||||||
|
Type testClass,
|
||||||
|
object[] constructorArguments,
|
||||||
|
MethodInfo testMethod,
|
||||||
|
object[] methodArguments,
|
||||||
|
ITestOutputHelper output)
|
||||||
|
{
|
||||||
|
TestClass = testClass;
|
||||||
|
ConstructorArguments = constructorArguments;
|
||||||
|
TestMethod = testMethod;
|
||||||
|
MethodArguments = methodArguments;
|
||||||
|
Output = output;
|
||||||
|
|
||||||
|
_files = new Lazy<TestFileOutputContext>(() => new TestFileOutputContext(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type TestClass { get; }
|
||||||
|
public MethodInfo TestMethod { get; }
|
||||||
|
public object[] ConstructorArguments { get; }
|
||||||
|
public object[] MethodArguments { get; }
|
||||||
|
public ITestOutputHelper Output { get; }
|
||||||
|
public TestFileOutputContext FileOutput => _files.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,140 @@
|
||||||
|
// 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.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Testing
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides access to file storage for the running test. Get access by
|
||||||
|
/// implementing <see cref="ITestMethodLifecycle"/>, and accessing <see cref="TestContext.FileOutput"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Requires defining <see cref="AspNetTestFramework"/> as the test framework.
|
||||||
|
/// </remarks>
|
||||||
|
public sealed class TestFileOutputContext
|
||||||
|
{
|
||||||
|
private static char[] InvalidFileChars = new char[]
|
||||||
|
{
|
||||||
|
'\"', '<', '>', '|', '\0',
|
||||||
|
(char)1, (char)2, (char)3, (char)4, (char)5, (char)6, (char)7, (char)8, (char)9, (char)10,
|
||||||
|
(char)11, (char)12, (char)13, (char)14, (char)15, (char)16, (char)17, (char)18, (char)19, (char)20,
|
||||||
|
(char)21, (char)22, (char)23, (char)24, (char)25, (char)26, (char)27, (char)28, (char)29, (char)30,
|
||||||
|
(char)31, ':', '*', '?', '\\', '/', ' ', (char)127
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly TestContext _parent;
|
||||||
|
|
||||||
|
public TestFileOutputContext(TestContext parent)
|
||||||
|
{
|
||||||
|
_parent = parent;
|
||||||
|
|
||||||
|
TestName = GetTestMethodName(parent.TestMethod, parent.MethodArguments);
|
||||||
|
TestClassName = GetTestClassName(parent.TestClass);
|
||||||
|
|
||||||
|
AssemblyOutputDirectory = GetAssemblyBaseDirectory(_parent.TestClass.Assembly);
|
||||||
|
if (!string.IsNullOrEmpty(AssemblyOutputDirectory))
|
||||||
|
{
|
||||||
|
TestClassOutputDirectory = Path.Combine(AssemblyOutputDirectory, TestClassName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string TestName { get; }
|
||||||
|
|
||||||
|
public string TestClassName { get; }
|
||||||
|
|
||||||
|
public string AssemblyOutputDirectory { get; }
|
||||||
|
|
||||||
|
public string TestClassOutputDirectory { get; }
|
||||||
|
|
||||||
|
public string GetUniqueFileName(string prefix, string extension)
|
||||||
|
{
|
||||||
|
if (prefix == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(prefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extension != null && !extension.StartsWith(".", StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("The extension must start with '.' if one is provided.", nameof(extension));
|
||||||
|
}
|
||||||
|
|
||||||
|
var path = Path.Combine(TestClassOutputDirectory, $"{prefix}{extension}");
|
||||||
|
|
||||||
|
var i = 1;
|
||||||
|
while (File.Exists(path))
|
||||||
|
{
|
||||||
|
path = Path.Combine(TestClassOutputDirectory, $"{prefix}{i++}{extension}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the output directory without appending the TFM or assembly name.
|
||||||
|
public static string GetOutputDirectory(Assembly assembly)
|
||||||
|
{
|
||||||
|
var attribute = assembly.GetCustomAttributes().OfType<TestOutputDirectoryAttribute>().FirstOrDefault();
|
||||||
|
return attribute?.BaseDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetAssemblyBaseDirectory(Assembly assembly, string baseDirectory = null)
|
||||||
|
{
|
||||||
|
var attribute = assembly.GetCustomAttributes().OfType<TestOutputDirectoryAttribute>().FirstOrDefault();
|
||||||
|
baseDirectory = baseDirectory ?? attribute?.BaseDirectory;
|
||||||
|
if (string.IsNullOrEmpty(baseDirectory))
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Path.Combine(baseDirectory, assembly.GetName().Name, attribute.TargetFramework);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetTestClassName(Type type)
|
||||||
|
{
|
||||||
|
var shortNameAttribute =
|
||||||
|
type.GetCustomAttribute<ShortClassNameAttribute>() ??
|
||||||
|
type.Assembly.GetCustomAttribute<ShortClassNameAttribute>();
|
||||||
|
var name = shortNameAttribute == null ? type.FullName : type.Name;
|
||||||
|
|
||||||
|
// Try to shorten the class name using the assembly name
|
||||||
|
var assemblyName = type.Assembly.GetName().Name;
|
||||||
|
if (name.StartsWith(assemblyName + "."))
|
||||||
|
{
|
||||||
|
name = name.Substring(assemblyName.Length + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetTestMethodName(MethodInfo method, object[] arguments)
|
||||||
|
{
|
||||||
|
var name = arguments.Aggregate(method.Name, (a, b) => $"{a}-{(b ?? "null")}");
|
||||||
|
return RemoveIllegalFileChars(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string RemoveIllegalFileChars(string s)
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
|
foreach (var c in s)
|
||||||
|
{
|
||||||
|
if (InvalidFileChars.Contains(c))
|
||||||
|
{
|
||||||
|
if (sb.Length > 0 && sb[sb.Length - 1] != '_')
|
||||||
|
{
|
||||||
|
sb.Append('_');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.Append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Testing
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false, Inherited = true)]
|
||||||
|
public class TestOutputDirectoryAttribute : Attribute
|
||||||
|
{
|
||||||
|
public TestOutputDirectoryAttribute(string targetFramework, string baseDirectory = null)
|
||||||
|
{
|
||||||
|
TargetFramework = targetFramework;
|
||||||
|
BaseDirectory = baseDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string BaseDirectory { get; }
|
||||||
|
public string TargetFramework { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
// 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 System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
using Xunit.Sdk;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Testing
|
||||||
|
{
|
||||||
|
public class AspNetTestAssemblyRunner : XunitTestAssemblyRunner
|
||||||
|
{
|
||||||
|
private readonly Dictionary<Type, object> _assemblyFixtureMappings = new Dictionary<Type, object>();
|
||||||
|
|
||||||
|
public AspNetTestAssemblyRunner(
|
||||||
|
ITestAssembly testAssembly,
|
||||||
|
IEnumerable<IXunitTestCase> testCases,
|
||||||
|
IMessageSink diagnosticMessageSink,
|
||||||
|
IMessageSink executionMessageSink,
|
||||||
|
ITestFrameworkExecutionOptions executionOptions)
|
||||||
|
: base(testAssembly, testCases, diagnosticMessageSink, executionMessageSink, executionOptions)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task AfterTestAssemblyStartingAsync()
|
||||||
|
{
|
||||||
|
await base.AfterTestAssemblyStartingAsync();
|
||||||
|
|
||||||
|
// Find all the AssemblyFixtureAttributes on the test assembly
|
||||||
|
Aggregator.Run(() =>
|
||||||
|
{
|
||||||
|
var fixturesAttributes = ((IReflectionAssemblyInfo)TestAssembly.Assembly)
|
||||||
|
.Assembly
|
||||||
|
.GetCustomAttributes(typeof(AssemblyFixtureAttribute), false)
|
||||||
|
.Cast<AssemblyFixtureAttribute>()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
// Instantiate all the fixtures
|
||||||
|
foreach (var fixtureAttribute in fixturesAttributes)
|
||||||
|
{
|
||||||
|
var ctorWithDiagnostics = fixtureAttribute.FixtureType.GetConstructor(new[] { typeof(IMessageSink) });
|
||||||
|
if (ctorWithDiagnostics != null)
|
||||||
|
{
|
||||||
|
_assemblyFixtureMappings[fixtureAttribute.FixtureType] = Activator.CreateInstance(fixtureAttribute.FixtureType, DiagnosticMessageSink);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_assemblyFixtureMappings[fixtureAttribute.FixtureType] = Activator.CreateInstance(fixtureAttribute.FixtureType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Task BeforeTestAssemblyFinishedAsync()
|
||||||
|
{
|
||||||
|
// Dispose fixtures
|
||||||
|
foreach (var disposable in _assemblyFixtureMappings.Values.OfType<IDisposable>())
|
||||||
|
{
|
||||||
|
Aggregator.Run(disposable.Dispose);
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.BeforeTestAssemblyFinishedAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Task<RunSummary> RunTestCollectionAsync(
|
||||||
|
IMessageBus messageBus,
|
||||||
|
ITestCollection testCollection,
|
||||||
|
IEnumerable<IXunitTestCase> testCases,
|
||||||
|
CancellationTokenSource cancellationTokenSource)
|
||||||
|
=> new AspNetTestCollectionRunner(
|
||||||
|
_assemblyFixtureMappings,
|
||||||
|
testCollection,
|
||||||
|
testCases,
|
||||||
|
DiagnosticMessageSink,
|
||||||
|
messageBus,
|
||||||
|
TestCaseOrderer,
|
||||||
|
new ExceptionAggregator(Aggregator),
|
||||||
|
cancellationTokenSource).RunAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
// 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 System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
using Xunit.Sdk;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Testing
|
||||||
|
{
|
||||||
|
internal class AspNetTestCaseRunner : XunitTestCaseRunner
|
||||||
|
{
|
||||||
|
public AspNetTestCaseRunner(
|
||||||
|
IXunitTestCase testCase,
|
||||||
|
string displayName,
|
||||||
|
string skipReason,
|
||||||
|
object[] constructorArguments,
|
||||||
|
object[] testMethodArguments,
|
||||||
|
IMessageBus messageBus,
|
||||||
|
ExceptionAggregator aggregator,
|
||||||
|
CancellationTokenSource cancellationTokenSource)
|
||||||
|
: base(testCase, displayName, skipReason, constructorArguments, testMethodArguments, messageBus, aggregator, cancellationTokenSource)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override XunitTestRunner CreateTestRunner(ITest test, IMessageBus messageBus, Type testClass, object[] constructorArguments, MethodInfo testMethod, object[] testMethodArguments, string skipReason, IReadOnlyList<BeforeAfterTestAttribute> beforeAfterAttributes, ExceptionAggregator aggregator, CancellationTokenSource cancellationTokenSource)
|
||||||
|
{
|
||||||
|
return new AspNetTestRunner(test, messageBus, testClass, constructorArguments, testMethod, testMethodArguments, skipReason, beforeAfterAttributes, aggregator, cancellationTokenSource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
// 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 System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
using Xunit.Sdk;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Testing
|
||||||
|
{
|
||||||
|
internal class AspNetTestClassRunner : XunitTestClassRunner
|
||||||
|
{
|
||||||
|
public AspNetTestClassRunner(
|
||||||
|
ITestClass testClass,
|
||||||
|
IReflectionTypeInfo @class,
|
||||||
|
IEnumerable<IXunitTestCase> testCases,
|
||||||
|
IMessageSink diagnosticMessageSink,
|
||||||
|
IMessageBus messageBus,
|
||||||
|
ITestCaseOrderer testCaseOrderer,
|
||||||
|
ExceptionAggregator aggregator,
|
||||||
|
CancellationTokenSource cancellationTokenSource,
|
||||||
|
IDictionary<Type, object> collectionFixtureMappings)
|
||||||
|
: base(testClass, @class, testCases, diagnosticMessageSink, messageBus, testCaseOrderer, aggregator, cancellationTokenSource, collectionFixtureMappings)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Task<RunSummary> RunTestMethodAsync(ITestMethod testMethod, IReflectionMethodInfo method, IEnumerable<IXunitTestCase> testCases, object[] constructorArguments)
|
||||||
|
{
|
||||||
|
var runner = new AspNetTestMethodRunner(
|
||||||
|
testMethod,
|
||||||
|
Class,
|
||||||
|
method,
|
||||||
|
testCases,
|
||||||
|
DiagnosticMessageSink,
|
||||||
|
MessageBus,
|
||||||
|
new ExceptionAggregator(Aggregator),
|
||||||
|
CancellationTokenSource,
|
||||||
|
constructorArguments);
|
||||||
|
return runner.RunAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
// 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 System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
using Xunit.Sdk;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Testing
|
||||||
|
{
|
||||||
|
public class AspNetTestCollectionRunner : XunitTestCollectionRunner
|
||||||
|
{
|
||||||
|
private readonly IDictionary<Type, object> _assemblyFixtureMappings;
|
||||||
|
private readonly IMessageSink _diagnosticMessageSink;
|
||||||
|
|
||||||
|
public AspNetTestCollectionRunner(
|
||||||
|
Dictionary<Type, object> assemblyFixtureMappings,
|
||||||
|
ITestCollection testCollection,
|
||||||
|
IEnumerable<IXunitTestCase> testCases,
|
||||||
|
IMessageSink diagnosticMessageSink,
|
||||||
|
IMessageBus messageBus,
|
||||||
|
ITestCaseOrderer testCaseOrderer,
|
||||||
|
ExceptionAggregator aggregator,
|
||||||
|
CancellationTokenSource cancellationTokenSource)
|
||||||
|
: base(testCollection, testCases, diagnosticMessageSink, messageBus, testCaseOrderer, aggregator, cancellationTokenSource)
|
||||||
|
{
|
||||||
|
_assemblyFixtureMappings = assemblyFixtureMappings;
|
||||||
|
_diagnosticMessageSink = diagnosticMessageSink;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task AfterTestCollectionStartingAsync()
|
||||||
|
{
|
||||||
|
await base.AfterTestCollectionStartingAsync();
|
||||||
|
|
||||||
|
// note: We pass the assembly fixtures into the runner as ICollectionFixture<> - this seems to work OK without any
|
||||||
|
// drawbacks. It's reasonable that we could add IAssemblyFixture<> and related plumbing if it ever became required.
|
||||||
|
//
|
||||||
|
// The reason for assembly fixture is when we want to start/stop something as the project scope - tests can only be
|
||||||
|
// in one test collection at a time.
|
||||||
|
foreach (var mapping in _assemblyFixtureMappings)
|
||||||
|
{
|
||||||
|
CollectionFixtureMappings.Add(mapping.Key, mapping.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Task BeforeTestCollectionFinishedAsync()
|
||||||
|
{
|
||||||
|
// We need to remove the assembly fixtures so they won't get disposed.
|
||||||
|
foreach (var mapping in _assemblyFixtureMappings)
|
||||||
|
{
|
||||||
|
CollectionFixtureMappings.Remove(mapping.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.BeforeTestCollectionFinishedAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Task<RunSummary> RunTestClassAsync(ITestClass testClass, IReflectionTypeInfo @class, IEnumerable<IXunitTestCase> testCases)
|
||||||
|
{
|
||||||
|
var runner = new AspNetTestClassRunner(
|
||||||
|
testClass,
|
||||||
|
@class,
|
||||||
|
testCases,
|
||||||
|
DiagnosticMessageSink,
|
||||||
|
MessageBus,
|
||||||
|
TestCaseOrderer,
|
||||||
|
new ExceptionAggregator(Aggregator),
|
||||||
|
CancellationTokenSource,
|
||||||
|
CollectionFixtureMappings);
|
||||||
|
return runner.RunAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
// 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.Reflection;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
using Xunit.Sdk;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Testing
|
||||||
|
{
|
||||||
|
public class AspNetTestFramework : XunitTestFramework
|
||||||
|
{
|
||||||
|
public AspNetTestFramework(IMessageSink messageSink)
|
||||||
|
: base(messageSink)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override ITestFrameworkExecutor CreateExecutor(AssemblyName assemblyName)
|
||||||
|
=> new AspNetTestFrameworkExecutor(assemblyName, SourceInformationProvider, DiagnosticMessageSink);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
// 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.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
using Xunit.Sdk;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Testing
|
||||||
|
{
|
||||||
|
public class AspNetTestFrameworkExecutor : XunitTestFrameworkExecutor
|
||||||
|
{
|
||||||
|
public AspNetTestFrameworkExecutor(AssemblyName assemblyName, ISourceInformationProvider sourceInformationProvider, IMessageSink diagnosticMessageSink)
|
||||||
|
: base(assemblyName, sourceInformationProvider, diagnosticMessageSink)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async void RunTestCases(IEnumerable<IXunitTestCase> testCases, IMessageSink executionMessageSink, ITestFrameworkExecutionOptions executionOptions)
|
||||||
|
{
|
||||||
|
using (var assemblyRunner = new AspNetTestAssemblyRunner(TestAssembly, testCases, DiagnosticMessageSink, executionMessageSink, executionOptions))
|
||||||
|
{
|
||||||
|
await assemblyRunner.RunAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
// 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 System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
using Xunit.Sdk;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Testing
|
||||||
|
{
|
||||||
|
internal class AspNetTestInvoker : XunitTestInvoker
|
||||||
|
{
|
||||||
|
public AspNetTestInvoker(
|
||||||
|
ITest test,
|
||||||
|
IMessageBus messageBus,
|
||||||
|
Type testClass,
|
||||||
|
object[] constructorArguments,
|
||||||
|
MethodInfo testMethod,
|
||||||
|
object[] testMethodArguments,
|
||||||
|
IReadOnlyList<BeforeAfterTestAttribute> beforeAfterAttributes,
|
||||||
|
ExceptionAggregator aggregator,
|
||||||
|
CancellationTokenSource cancellationTokenSource)
|
||||||
|
: base(test, messageBus, testClass, constructorArguments, testMethod, testMethodArguments, beforeAfterAttributes, aggregator, cancellationTokenSource)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task<decimal> InvokeTestMethodAsync(object testClassInstance)
|
||||||
|
{
|
||||||
|
var output = new TestOutputHelper();
|
||||||
|
output.Initialize(MessageBus, Test);
|
||||||
|
|
||||||
|
var context = new TestContext(TestClass, ConstructorArguments, TestMethod, TestMethodArguments, output);
|
||||||
|
var lifecycleHooks = GetLifecycleHooks(testClassInstance, TestClass, TestMethod);
|
||||||
|
|
||||||
|
await Aggregator.RunAsync(async () =>
|
||||||
|
{
|
||||||
|
foreach (var lifecycleHook in lifecycleHooks)
|
||||||
|
{
|
||||||
|
await lifecycleHook.OnTestStartAsync(context, CancellationTokenSource.Token);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var time = await base.InvokeTestMethodAsync(testClassInstance);
|
||||||
|
|
||||||
|
await Aggregator.RunAsync(async () =>
|
||||||
|
{
|
||||||
|
var exception = Aggregator.HasExceptions ? Aggregator.ToException() : null;
|
||||||
|
foreach (var lifecycleHook in lifecycleHooks)
|
||||||
|
{
|
||||||
|
await lifecycleHook.OnTestEndAsync(context, exception, CancellationTokenSource.Token);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<ITestMethodLifecycle> GetLifecycleHooks(object testClassInstance, Type testClass, MethodInfo testMethod)
|
||||||
|
{
|
||||||
|
foreach (var attribute in testMethod.GetCustomAttributes(inherit: true).OfType<ITestMethodLifecycle>())
|
||||||
|
{
|
||||||
|
yield return attribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (testClassInstance is ITestMethodLifecycle instance)
|
||||||
|
{
|
||||||
|
yield return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var attribute in testClass.GetCustomAttributes(inherit: true).OfType<ITestMethodLifecycle>())
|
||||||
|
{
|
||||||
|
yield return attribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var attribute in testClass.Assembly.GetCustomAttributes(inherit: true).OfType<ITestMethodLifecycle>())
|
||||||
|
{
|
||||||
|
yield return attribute;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
// 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.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Testing.xunit;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
using Xunit.Sdk;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Testing
|
||||||
|
{
|
||||||
|
internal class AspNetTestMethodRunner : XunitTestMethodRunner
|
||||||
|
{
|
||||||
|
private readonly object[] _constructorArguments;
|
||||||
|
private readonly IMessageSink _diagnosticMessageSink;
|
||||||
|
|
||||||
|
public AspNetTestMethodRunner(
|
||||||
|
ITestMethod testMethod,
|
||||||
|
IReflectionTypeInfo @class,
|
||||||
|
IReflectionMethodInfo method,
|
||||||
|
IEnumerable<IXunitTestCase> testCases,
|
||||||
|
IMessageSink diagnosticMessageSink,
|
||||||
|
IMessageBus messageBus,
|
||||||
|
ExceptionAggregator aggregator,
|
||||||
|
CancellationTokenSource cancellationTokenSource,
|
||||||
|
object[] constructorArguments)
|
||||||
|
: base(testMethod, @class, method, testCases, diagnosticMessageSink, messageBus, aggregator, cancellationTokenSource, constructorArguments)
|
||||||
|
{
|
||||||
|
_diagnosticMessageSink = diagnosticMessageSink;
|
||||||
|
_constructorArguments = constructorArguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Task<RunSummary> RunTestCaseAsync(IXunitTestCase testCase)
|
||||||
|
{
|
||||||
|
if (testCase.GetType() == typeof(XunitTestCase))
|
||||||
|
{
|
||||||
|
// If we get here this is a 'regular' test case, not something that represents a skipped test.
|
||||||
|
//
|
||||||
|
// We can take control of it's invocation thusly.
|
||||||
|
var runner = new AspNetTestCaseRunner(
|
||||||
|
testCase,
|
||||||
|
testCase.DisplayName,
|
||||||
|
testCase.SkipReason,
|
||||||
|
_constructorArguments,
|
||||||
|
testCase.TestMethodArguments,
|
||||||
|
MessageBus,
|
||||||
|
new ExceptionAggregator(Aggregator),
|
||||||
|
CancellationTokenSource);
|
||||||
|
return runner.RunAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (testCase.GetType() == typeof(XunitTheoryTestCase))
|
||||||
|
{
|
||||||
|
// If we get here this is a 'regular' theory test case, not something that represents a skipped test.
|
||||||
|
//
|
||||||
|
// We can take control of it's invocation thusly.
|
||||||
|
var runner = new AspNetTheoryTestCaseRunner(
|
||||||
|
testCase,
|
||||||
|
testCase.DisplayName,
|
||||||
|
testCase.SkipReason,
|
||||||
|
_constructorArguments,
|
||||||
|
_diagnosticMessageSink,
|
||||||
|
MessageBus,
|
||||||
|
new ExceptionAggregator(Aggregator),
|
||||||
|
CancellationTokenSource);
|
||||||
|
return runner.RunAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.RunTestCaseAsync(testCase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
// 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 System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
using Xunit.Sdk;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Testing
|
||||||
|
{
|
||||||
|
internal class AspNetTestRunner : XunitTestRunner
|
||||||
|
{
|
||||||
|
public AspNetTestRunner(
|
||||||
|
ITest test,
|
||||||
|
IMessageBus messageBus,
|
||||||
|
Type testClass,
|
||||||
|
object[] constructorArguments,
|
||||||
|
MethodInfo testMethod,
|
||||||
|
object[] testMethodArguments,
|
||||||
|
string skipReason,
|
||||||
|
IReadOnlyList<BeforeAfterTestAttribute> beforeAfterAttributes,
|
||||||
|
ExceptionAggregator aggregator,
|
||||||
|
CancellationTokenSource cancellationTokenSource)
|
||||||
|
: base(test, messageBus, testClass, constructorArguments, testMethod, testMethodArguments, skipReason, beforeAfterAttributes, aggregator, cancellationTokenSource)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task<decimal> InvokeTestMethodAsync(ExceptionAggregator aggregator)
|
||||||
|
{
|
||||||
|
var repeatAttribute = GetRepeatAttribute(TestMethod);
|
||||||
|
if (repeatAttribute == null)
|
||||||
|
{
|
||||||
|
return await InvokeTestMethodCoreAsync(aggregator);
|
||||||
|
}
|
||||||
|
|
||||||
|
var repeatContext = new RepeatContext(repeatAttribute.RunCount);
|
||||||
|
RepeatContext.Current = repeatContext;
|
||||||
|
|
||||||
|
var timeTaken = 0.0M;
|
||||||
|
for (repeatContext.CurrentIteration = 0; repeatContext.CurrentIteration < repeatContext.Limit; repeatContext.CurrentIteration++)
|
||||||
|
{
|
||||||
|
timeTaken = await InvokeTestMethodCoreAsync(aggregator);
|
||||||
|
if (aggregator.HasExceptions)
|
||||||
|
{
|
||||||
|
return timeTaken;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return timeTaken;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task<decimal> InvokeTestMethodCoreAsync(ExceptionAggregator aggregator)
|
||||||
|
{
|
||||||
|
var invoker = new AspNetTestInvoker(Test, MessageBus, TestClass, ConstructorArguments, TestMethod, TestMethodArguments, BeforeAfterAttributes, aggregator, CancellationTokenSource);
|
||||||
|
return invoker.RunAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private RepeatAttribute GetRepeatAttribute(MethodInfo methodInfo)
|
||||||
|
{
|
||||||
|
var attributeCandidate = methodInfo.GetCustomAttribute<RepeatAttribute>();
|
||||||
|
if (attributeCandidate != null)
|
||||||
|
{
|
||||||
|
return attributeCandidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
attributeCandidate = methodInfo.DeclaringType.GetCustomAttribute<RepeatAttribute>();
|
||||||
|
if (attributeCandidate != null)
|
||||||
|
{
|
||||||
|
return attributeCandidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
return methodInfo.DeclaringType.Assembly.GetCustomAttribute<RepeatAttribute>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
// 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 System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
using Xunit.Sdk;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Testing.xunit
|
||||||
|
{
|
||||||
|
internal class AspNetTheoryTestCaseRunner : XunitTheoryTestCaseRunner
|
||||||
|
{
|
||||||
|
public AspNetTheoryTestCaseRunner(
|
||||||
|
IXunitTestCase testCase,
|
||||||
|
string displayName,
|
||||||
|
string skipReason,
|
||||||
|
object[] constructorArguments,
|
||||||
|
IMessageSink diagnosticMessageSink,
|
||||||
|
IMessageBus messageBus,
|
||||||
|
ExceptionAggregator aggregator,
|
||||||
|
CancellationTokenSource cancellationTokenSource)
|
||||||
|
: base(testCase, displayName, skipReason, constructorArguments, diagnosticMessageSink, messageBus, aggregator, cancellationTokenSource)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override XunitTestRunner CreateTestRunner(ITest test, IMessageBus messageBus, Type testClass, object[] constructorArguments, MethodInfo testMethod, object[] testMethodArguments, string skipReason, IReadOnlyList<BeforeAfterTestAttribute> beforeAfterAttributes, ExceptionAggregator aggregator, CancellationTokenSource cancellationTokenSource)
|
||||||
|
{
|
||||||
|
return new AspNetTestRunner(test, messageBus, testClass, constructorArguments, testMethod, testMethodArguments, skipReason, beforeAfterAttributes, aggregator, cancellationTokenSource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Testing
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
|
||||||
|
public class AssemblyFixtureAttribute : Attribute
|
||||||
|
{
|
||||||
|
public AssemblyFixtureAttribute(Type fixtureType)
|
||||||
|
{
|
||||||
|
FixtureType = fixtureType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type FixtureType { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// 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 System.Collections.Generic;
|
||||||
using Xunit.Abstractions;
|
using Xunit.Abstractions;
|
||||||
using Xunit.Sdk;
|
using Xunit.Sdk;
|
||||||
|
|
@ -63,5 +64,24 @@ namespace Microsoft.AspNetCore.Testing
|
||||||
base.CreateTestCasesForSkippedDataRow(discoveryOptions, testMethod, theoryAttribute, dataRow, skipReason)
|
base.CreateTestCasesForSkippedDataRow(discoveryOptions, testMethod, theoryAttribute, dataRow, skipReason)
|
||||||
: base.CreateTestCasesForDataRow(discoveryOptions, testMethod, theoryAttribute, dataRow);
|
: base.CreateTestCasesForDataRow(discoveryOptions, testMethod, theoryAttribute, dataRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override IEnumerable<IXunitTestCase> CreateTestCasesForSkippedDataRow(
|
||||||
|
ITestFrameworkDiscoveryOptions discoveryOptions,
|
||||||
|
ITestMethod testMethod,
|
||||||
|
IAttributeInfo theoryAttribute,
|
||||||
|
object[] dataRow,
|
||||||
|
string skipReason)
|
||||||
|
{
|
||||||
|
return new[]
|
||||||
|
{
|
||||||
|
new WORKAROUND_SkippedDataRowTestCase(DiagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), discoveryOptions.MethodDisplayOptionsOrDefault(), testMethod, skipReason, dataRow),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete]
|
||||||
|
protected override IXunitTestCase CreateTestCaseForSkippedDataRow(ITestFrameworkDiscoveryOptions discoveryOptions, ITestMethod testMethod, IAttributeInfo theoryAttribute, object[] dataRow, string skipReason)
|
||||||
|
{
|
||||||
|
return new WORKAROUND_SkippedDataRowTestCase(DiagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), discoveryOptions.MethodDisplayOptionsOrDefault(), testMethod, skipReason, dataRow);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ namespace Microsoft.AspNetCore.Testing
|
||||||
/// to <c>xunit.console.exe</c>. Similarly, it can run only flaky tests using <c>-trait "Flaky:AzP:OS:all=true" -trait "Flaky:AzP:OS:Darwin=true"</c>
|
/// to <c>xunit.console.exe</c>. Similarly, it can run only flaky tests using <c>-trait "Flaky:AzP:OS:all=true" -trait "Flaky:AzP:OS:Darwin=true"</c>
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </example>
|
/// </example>
|
||||||
[TraitDiscoverer("Microsoft.AspNetCore.Testing." + nameof(FlakyTestDiscoverer), "Microsoft.AspNetCore.Testing")]
|
[TraitDiscoverer("Microsoft.AspNetCore.Testing." + nameof(FlakyTraitDiscoverer), "Microsoft.AspNetCore.Testing")]
|
||||||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly)]
|
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly)]
|
||||||
public sealed class FlakyAttribute : Attribute, ITraitAttribute
|
public sealed class FlakyAttribute : Attribute, ITraitAttribute
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ using Xunit.Sdk;
|
||||||
// Do not change this namespace without changing the usage in FlakyAttribute
|
// Do not change this namespace without changing the usage in FlakyAttribute
|
||||||
namespace Microsoft.AspNetCore.Testing
|
namespace Microsoft.AspNetCore.Testing
|
||||||
{
|
{
|
||||||
public class FlakyTestDiscoverer : ITraitDiscoverer
|
public class FlakyTraitDiscoverer : ITraitDiscoverer
|
||||||
{
|
{
|
||||||
public IEnumerable<KeyValuePair<string, string>> GetTraits(IAttributeInfo traitAttribute)
|
public IEnumerable<KeyValuePair<string, string>> GetTraits(IAttributeInfo traitAttribute)
|
||||||
{
|
{
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Xunit.Abstractions;
|
using Xunit.Abstractions;
|
||||||
using Xunit.Sdk;
|
using Xunit.Sdk;
|
||||||
|
|
||||||
|
|
@ -33,8 +35,11 @@ namespace Microsoft.AspNetCore.Testing
|
||||||
|
|
||||||
public override void Deserialize(IXunitSerializationInfo data)
|
public override void Deserialize(IXunitSerializationInfo data)
|
||||||
{
|
{
|
||||||
base.Deserialize(data);
|
|
||||||
_skipReason = data.GetValue<string>(nameof(_skipReason));
|
_skipReason = data.GetValue<string>(nameof(_skipReason));
|
||||||
|
|
||||||
|
// We need to call base after reading our value, because Deserialize will call
|
||||||
|
// into GetSkipReason.
|
||||||
|
base.Deserialize(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Serialize(IXunitSerializationInfo data)
|
public override void Serialize(IXunitSerializationInfo data)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
using Xunit.Sdk;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Testing
|
||||||
|
{
|
||||||
|
// This is a workaround for https://github.com/xunit/xunit/issues/1782 - as such, this code is a copy-paste
|
||||||
|
// from xUnit with the exception of fixing the bug.
|
||||||
|
//
|
||||||
|
// This will only work with [ConditionalTheory].
|
||||||
|
internal class WORKAROUND_SkippedDataRowTestCase : XunitTestCase
|
||||||
|
{
|
||||||
|
string skipReason;
|
||||||
|
|
||||||
|
/// <summary/>
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
[Obsolete("Called by the de-serializer; should only be called by deriving classes for de-serialization purposes")]
|
||||||
|
public WORKAROUND_SkippedDataRowTestCase() { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="XunitSkippedDataRowTestCase"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="diagnosticMessageSink">The message sink used to send diagnostic messages</param>
|
||||||
|
/// <param name="defaultMethodDisplay">Default method display to use (when not customized).</param>
|
||||||
|
/// <param name="testMethod">The test method this test case belongs to.</param>
|
||||||
|
/// <param name="skipReason">The reason that this test case will be skipped</param>
|
||||||
|
/// <param name="testMethodArguments">The arguments for the test method.</param>
|
||||||
|
[Obsolete("Please call the constructor which takes TestMethodDisplayOptions")]
|
||||||
|
public WORKAROUND_SkippedDataRowTestCase(IMessageSink diagnosticMessageSink,
|
||||||
|
TestMethodDisplay defaultMethodDisplay,
|
||||||
|
ITestMethod testMethod,
|
||||||
|
string skipReason,
|
||||||
|
object[] testMethodArguments = null)
|
||||||
|
: this(diagnosticMessageSink, defaultMethodDisplay, TestMethodDisplayOptions.None, testMethod, skipReason, testMethodArguments) { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="XunitSkippedDataRowTestCase"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="diagnosticMessageSink">The message sink used to send diagnostic messages</param>
|
||||||
|
/// <param name="defaultMethodDisplay">Default method display to use (when not customized).</param>
|
||||||
|
/// <param name="defaultMethodDisplayOptions">Default method display options to use (when not customized).</param>
|
||||||
|
/// <param name="testMethod">The test method this test case belongs to.</param>
|
||||||
|
/// <param name="skipReason">The reason that this test case will be skipped</param>
|
||||||
|
/// <param name="testMethodArguments">The arguments for the test method.</param>
|
||||||
|
public WORKAROUND_SkippedDataRowTestCase(IMessageSink diagnosticMessageSink,
|
||||||
|
TestMethodDisplay defaultMethodDisplay,
|
||||||
|
TestMethodDisplayOptions defaultMethodDisplayOptions,
|
||||||
|
ITestMethod testMethod,
|
||||||
|
string skipReason,
|
||||||
|
object[] testMethodArguments = null)
|
||||||
|
: base(diagnosticMessageSink, defaultMethodDisplay, defaultMethodDisplayOptions, testMethod, testMethodArguments)
|
||||||
|
{
|
||||||
|
this.skipReason = skipReason;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override void Deserialize(IXunitSerializationInfo data)
|
||||||
|
{
|
||||||
|
// SkipReason has to be read before we call base.Deserialize, this is the workaround.
|
||||||
|
this.skipReason = data.GetValue<string>("SkipReason");
|
||||||
|
|
||||||
|
base.Deserialize(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
protected override string GetSkipReason(IAttributeInfo factAttribute)
|
||||||
|
{
|
||||||
|
return skipReason;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override void Serialize(IXunitSerializationInfo data)
|
||||||
|
{
|
||||||
|
base.Serialize(data);
|
||||||
|
|
||||||
|
data.AddValue("SkipReason", skipReason);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
// 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 Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Testing
|
||||||
|
{
|
||||||
|
// We include a collection and assembly fixture to verify that they both still work.
|
||||||
|
[Collection("MyCollection")]
|
||||||
|
[TestCaseOrderer("Microsoft.AspNetCore.Testing.AlphabeticalOrderer", "Microsoft.AspNetCore.Testing.Tests")]
|
||||||
|
public class AssemblyFixtureTest
|
||||||
|
{
|
||||||
|
public AssemblyFixtureTest(TestAssemblyFixture assemblyFixture, TestCollectionFixture collectionFixture)
|
||||||
|
{
|
||||||
|
AssemblyFixture = assemblyFixture;
|
||||||
|
CollectionFixture = collectionFixture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestAssemblyFixture AssemblyFixture { get; }
|
||||||
|
public TestCollectionFixture CollectionFixture { get; }
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void A()
|
||||||
|
{
|
||||||
|
Assert.NotNull(AssemblyFixture);
|
||||||
|
Assert.Equal(0, AssemblyFixture.Count);
|
||||||
|
|
||||||
|
Assert.NotNull(CollectionFixture);
|
||||||
|
Assert.Equal(0, CollectionFixture.Count);
|
||||||
|
|
||||||
|
AssemblyFixture.Count++;
|
||||||
|
CollectionFixture.Count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void B()
|
||||||
|
{
|
||||||
|
Assert.Equal(1, AssemblyFixture.Count);
|
||||||
|
Assert.Equal(1, CollectionFixture.Count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[CollectionDefinition("MyCollection", DisableParallelization = true)]
|
||||||
|
public class MyCollection : ICollectionFixture<TestCollectionFixture>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -29,7 +29,7 @@ namespace Microsoft.AspNetCore.Testing
|
||||||
Assert.True(false, "This test should always be skipped.");
|
Assert.True(false, "This test should always be skipped.");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NETCOREAPP3_0
|
#if NETCOREAPP
|
||||||
[ConditionalFact]
|
[ConditionalFact]
|
||||||
[FrameworkSkipCondition(RuntimeFrameworks.CLR)]
|
[FrameworkSkipCondition(RuntimeFrameworks.CLR)]
|
||||||
public void ThisTestMustRunOnCoreCLR()
|
public void ThisTestMustRunOnCoreCLR()
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ namespace Microsoft.AspNetCore.Testing
|
||||||
Assert.True(true);
|
Assert.True(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NETCOREAPP3_0
|
#if NETCOREAPP
|
||||||
[ConditionalTheory]
|
[ConditionalTheory]
|
||||||
[FrameworkSkipCondition(RuntimeFrameworks.CLR)]
|
[FrameworkSkipCondition(RuntimeFrameworks.CLR)]
|
||||||
[MemberData(nameof(GetInts))]
|
[MemberData(nameof(GetInts))]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks>
|
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net472</TargetFrameworks>
|
||||||
|
|
||||||
<!-- allow skipped tests -->
|
<!-- allow skipped tests -->
|
||||||
<NoWarn>$(NoWarn);xUnit1004</NoWarn>
|
<NoWarn>$(NoWarn);xUnit1004</NoWarn>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
using Microsoft.AspNetCore.Testing;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
[assembly: Repeat(1)]
|
||||||
|
[assembly: AssemblyFixture(typeof(TestAssemblyFixture))]
|
||||||
|
[assembly: TestFramework("Microsoft.AspNetCore.Testing.AspNetTestFramework", "Microsoft.AspNetCore.Testing")]
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
// 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 Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Testing
|
||||||
|
{
|
||||||
|
[Repeat]
|
||||||
|
public class RepeatTest
|
||||||
|
{
|
||||||
|
public static int _runCount = 0;
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Repeat(5)]
|
||||||
|
public void RepeatLimitIsSetCorrectly()
|
||||||
|
{
|
||||||
|
Assert.Equal(5, RepeatContext.Current.Limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Repeat(5)]
|
||||||
|
public void RepeatRunsTestSpecifiedNumberOfTimes()
|
||||||
|
{
|
||||||
|
Assert.Equal(RepeatContext.Current.CurrentIteration, _runCount);
|
||||||
|
_runCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void RepeatCanBeSetOnClass()
|
||||||
|
{
|
||||||
|
Assert.Equal(10, RepeatContext.Current.Limit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LoggedTestXunitRepeatAssemblyTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void RepeatCanBeSetOnAssembly()
|
||||||
|
{
|
||||||
|
Assert.Equal(1, RepeatContext.Current.Limit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Testing
|
||||||
|
{
|
||||||
|
public class TestAssemblyFixture
|
||||||
|
{
|
||||||
|
public int Count { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Testing
|
||||||
|
{
|
||||||
|
public class TestCollectionFixture
|
||||||
|
{
|
||||||
|
public int Count { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
// 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;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Testing
|
||||||
|
{
|
||||||
|
public class TestContextTest : ITestMethodLifecycle
|
||||||
|
{
|
||||||
|
public TestContext Context { get; private set; }
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void FullName_IsUsed_ByDefault()
|
||||||
|
{
|
||||||
|
Assert.Equal(GetType().FullName, Context.FileOutput.TestClassName);
|
||||||
|
}
|
||||||
|
|
||||||
|
Task ITestMethodLifecycle.OnTestStartAsync(TestContext context, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Context = context;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
Task ITestMethodLifecycle.OnTestEndAsync(TestContext context, Exception exception, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Testing.Tests
|
||||||
|
{
|
||||||
|
public class TestContextNameShorteningTest : ITestMethodLifecycle
|
||||||
|
{
|
||||||
|
public TestContext Context { get; private set; }
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void NameIsShortenedWhenAssemblyNameIsAPrefix()
|
||||||
|
{
|
||||||
|
Assert.Equal(GetType().Name, Context.FileOutput.TestClassName);
|
||||||
|
}
|
||||||
|
|
||||||
|
Task ITestMethodLifecycle.OnTestStartAsync(TestContext context, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Context = context;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
Task ITestMethodLifecycle.OnTestEndAsync(TestContext context, Exception exception, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Testing
|
||||||
|
{
|
||||||
|
[ShortClassName]
|
||||||
|
public class TestContextTestClassShortNameAttributeTest : ITestMethodLifecycle
|
||||||
|
{
|
||||||
|
public TestContext Context { get; private set; }
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ShortClassNameUsedWhenShortClassNameAttributeSpecified()
|
||||||
|
{
|
||||||
|
Assert.Equal(GetType().Name, Context.FileOutput.TestClassName);
|
||||||
|
}
|
||||||
|
|
||||||
|
Task ITestMethodLifecycle.OnTestStartAsync(TestContext context, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Context = context;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
Task ITestMethodLifecycle.OnTestEndAsync(TestContext context, Exception exception, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<!-- This file is automatically generated. -->
|
<!-- This file is automatically generated. -->
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netstandard2.0;netcoreapp3.0</TargetFrameworks>
|
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
||||||
<Compile Include="Microsoft.Extensions.WebEncoders.netstandard2.0.cs" />
|
<Compile Include="Microsoft.Extensions.WebEncoders.netstandard2.0.cs" />
|
||||||
|
|
@ -9,8 +9,8 @@
|
||||||
<Reference Include="Microsoft.Extensions.Options" />
|
<Reference Include="Microsoft.Extensions.Options" />
|
||||||
<Reference Include="System.Text.Encodings.Web" />
|
<Reference Include="System.Text.Encodings.Web" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
|
<ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'">
|
||||||
<Compile Include="Microsoft.Extensions.WebEncoders.netcoreapp3.0.cs" />
|
<Compile Include="Microsoft.Extensions.WebEncoders.netcoreapp.cs" />
|
||||||
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||||
<Reference Include="Microsoft.Extensions.Options" />
|
<Reference Include="Microsoft.Extensions.Options" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Description>Contains registration and configuration APIs to add the core framework encoders to a dependency injection container.</Description>
|
<Description>Contains registration and configuration APIs to add the core framework encoders to a dependency injection container.</Description>
|
||||||
<TargetFrameworks>netstandard2.0;netcoreapp3.0</TargetFrameworks>
|
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks>
|
||||||
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">netcoreapp3.0</TargetFrameworks>
|
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">$(DefaultNetCoreTargetFramework)</TargetFrameworks>
|
||||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<PackageTags>aspnetcore</PackageTags>
|
<PackageTags>aspnetcore</PackageTags>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks>
|
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net472</TargetFrameworks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue