Imported Upstream version 5.20.0.180

Former-commit-id: ff953ca879339fe1e1211f7220f563e1342e66cb
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2019-02-04 20:11:37 +00:00
parent 0e2d47d1c8
commit 0510252385
3360 changed files with 83827 additions and 39243 deletions

View File

@@ -0,0 +1,67 @@
:: Test build and execution wrapper for CoreFX tests
::
:: This wrapper is called for each of CoreFX's tests by runtest.cmd
::
:: %1 contains test folder
:: %2 contains test exe name
::
@echo OFF
setlocal ENABLEDELAYEDEXPANSION
set TestFolder=%1
::
:: We're only interested in referencing the xunit runner - the test dlls will be imported by the test wrapper project
::
set TestExecutable=xunit.console.netcore
set TestFileName=%2
:: Copy the artefacts we need to compile and run the xunit exe
copy /Y "%~dp0\runtest\CoreFXTestHarness\*" "%TestFolder%" >nul
if "%CoreRT_TestLogFileName%"=="" (
set CoreRT_TestLogFileName=testResults.xml
)
:: Create log dir if it doesn't exist
if not exist %XunitLogDir% md %XunitLogDir%
if not exist %XunitLogDir%\%TestFileName% md %XunitLogDir%\%TestFileName%
if not exist %TestFolder%\%TestExecutable%.exe (
:: Not a test we support, exit silently
exit /b 0
)
:: Workaround until we have a better reflection engine
:: Add name of currently executing test to rd.xml
powershell -Command "(Get-Content %TestFolder%\default.rd.xml).replace('*Application*', '%TestFileName%') | Set-Content %TestFolder%\default.rd.xml"
::
:: Force environment to 64-bit if we're doing an x64 test run
::
if "%CoreRT_BuildArch%" == "x64" (
call "%VS150COMNTOOLS%\..\..\VC\Auxiliary\Build\vcvarsall.bat" x64 >nul
)
echo Building %TestFileName%
call "%CoreRT_CliDir%\dotnet.exe" publish %TestFolder%\Test.csproj /ConsoleLoggerParameters:ForceNoAlign "/p:IlcPath=%CoreRT_ToolchainDir%" "/p:DebugSymbols=false" "/p:Configuration=%CoreRT_BuildType%" "/p:FrameworkLibPath=%~dp0..\..\bin\%CoreRT_BuildOS%.%CoreRT_BuildArch%.%CoreRT_BuildType%\lib" "/p:FrameworkObjPath=%~dp0..\..\bin\obj\%CoreRT_BuildOS%.%CoreRT_BuildArch%.%CoreRT_BuildType%\Framework" /p:DisableFrameworkLibGeneration=true /p:TestRootDir=%~dp0 /p:OSGroup=%CoreRT_BuildOS% /p:ExecutableName=%TestExecutable% /nologo
if errorlevel 1 (
echo Building %TestFileName% failed
exit /b 1
)
echo Executing %TestFileName% - writing logs to %XunitLogDir%\%TestFileName%\%CoreRT_TestLogFileName%
echo To repro directly, run call %TestFolder%\native\%TestExecutable% %TestFolder%\%TestFileName%.dll @"%TestFolder%\%TestFileName%.rsp" -xml %XunitLogDir%\%TestFileName%\%CoreRT_TestLogFileName% -notrait category=nonnetcoreapptests -notrait category=nonwindowstests -notrait category=failing
if not exist "%TestFolder%\native\%TestExecutable%".exe (
echo ERROR:Native binary not found Unable to run test.
exit /b 1
)
call %TestFolder%\native\%TestExecutable% %TestFolder%\%TestFileName%.dll @"%TestFolder%\%TestFileName%.rsp" -xml %XunitLogDir%\%TestFileName%\%CoreRT_TestLogFileName% -notrait category=nonnetcoreapptests -notrait category=nonwindowstests -notrait category=failing
set TestExitCode=!ERRORLEVEL!
exit /b %TestExitCode%

78
external/corert/tests/CoreFX/corerun vendored Executable file
View File

@@ -0,0 +1,78 @@
#!/usr/bin/env bash
# This is the Unix equivalent of build-and-run-test.cmd
# It is invoked by each test's bash script. The reason it's called corerun is that
# the unix CoreCLR tests don't have a custom runner override environment variable.
# See issue https://github.com/dotnet/coreclr/issues/9007
# The CoreFX alternative is named corerun to keep parity with the CoreCLR testing convention
export TestFolderName=$1
export TestFileName=$(basename ${TestFolderName})
export TestRootDir=${CoreRT_TestRoot}/CoreFX
export LogDir=$2
#
# We're only interested in referencing the xunit runner - the test dlls will be imported by the test wrapper project
#
TestExecutable=xunit.console.netcore
source "$CoreRT_TestRoot/coredump_handling.sh"
if [[ $CoreRT_EnableCoreDumps == 1 ]]; then
set_up_core_dump_generation
fi
if [ ! -e "${TestFolderName}/${TestExecutable}.exe" ]; then
echo "not found in ${TestFolderName}/${TestExecutable}.exe"
# Not a test we support, exit silently
exit 0
fi
# Copy the artefacts we need to compile and run the xunit exe
cp -a "${CoreRT_TestRoot}/CoreFX/runtest/CoreFXTestHarness/." "${TestFolderName}"
export __exitcode=$?
if [ ${__exitcode} != 0 ];
then
exit ${__exitcode}
fi
# Workaround until we have a better reflection engine
# Add name of currently executing test to rd.xml
sed -i.bak "s/\*Application\*/${TestFileName}/g" "${TestFolderName}/default.rd.xml"
echo Building ${TestFileName}
${CoreRT_CliBinDir}/dotnet publish "/p:IlcPath=${CoreRT_ToolchainDir}" "/p:DebugSymbols=false" /p:OSGroup=${CoreRT_BuildOS} "/p:Configuration=${CoreRT_BuildType}" "/p:FrameworkLibPath=${CoreRT_TestRoot}/../bin/${CoreRT_BuildOS}.${CoreRT_BuildArch}.${CoreRT_BuildType}/lib" "/p:FrameworkObjPath=${CoreRT_TestRoot}/../bin/obj/${CoreRT_BuildOS}.${CoreRT_BuildArch}.${CoreRT_BuildType}/Framework" /p:DisableFrameworkLibGeneration=true /p:TestRootDir=${TestRootDir} /p:ExecutableName=${TestExecutable} "/p:OutputPath=/${TestFolderName}/" ${TestFolderName}/Test.csproj
export __exitcode=$?
if [ ${__exitcode} != 0 ];
then
exit ${__exitcode}
fi
if [ ! -d "${LogDir}/${TestFileName}" ]; then
mkdir -p "${LogDir}/${TestFileName}"
fi
echo Executing ${TestFileName} - writing logs to ${LogDir}/${TestFileName}/testResults.xml
echo To repro directly, run ${TestFolderName}/native/${TestExecutable} ${TestFolderName}/${TestFileName}.dll @${TestFolderName}/${TestFileName}.rsp -xml ${LogDir}/${TestFileName}/testResults.xml -notrait category=nonnetcoreapptests -notrait category=${OSCategory} -notrait category=failing
chmod +x ${TestFolderName}/native/${TestExecutable}
case "$(uname -s)" in
# Check if we're running under Linux
Linux)
export OSCategory="nonlinuxtests"
;;
# Check if we're running under OSX
Darwin)
export OSCategory="nonosxtests"
;;
# Default to Linux if we don't recognize the OS
*)
export OSCategory="nonlinuxtests"
;;
esac
${TestFolderName}/native/${TestExecutable} ${TestFolderName}/${TestFileName}.dll @${TestFolderName}/${TestFileName}.rsp -xml ${LogDir}/${TestFileName}/testResults.xml -notrait category=nonnetcoreapptests -notrait category=${OSCategory} -notrait category=failing
export __exitcode=$?
exit ${__exitcode}

View File

@@ -0,0 +1,18 @@
<Project DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\dependencies.props" />
<!-- Package version dependencies in test helper projects. -->
<PropertyGroup>
<SystemCommandLineVersion>0.1.0-e160909-1</SystemCommandLineVersion>
<NewtonsoftJsonVersion>11.0.2</NewtonsoftJsonVersion>
<NewtonsoftJsonSchemaVersion>3.0.10</NewtonsoftJsonSchemaVersion>
<XunitPackageVersion>2.3.0-beta1-build3642</XunitPackageVersion>
<!-- Due to an API surface mismatch, if the xunit.netcore executable attempts to run the wrong version of the
runner utility, running the tests wil break, so separate both into different version definitions -->
<XunitRunnerUtilityVersion>2.2.0-beta2-build3300</XunitRunnerUtilityVersion>
<XunitAbstractionsVersion>2.0.1</XunitAbstractionsVersion>
<XunitNetcoreExtensionsVersion>2.1.0-preview2-02516-02</XunitNetcoreExtensionsVersion>
<CoreFxTestUtilitiesVersion>4.5.0-preview2-26219-0</CoreFxTestUtilitiesVersion>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,74 @@
<Project DefaultTargets="LinkNative">
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
<Import Project="$(TestRootDir)\dependencies.props" />
<!-- Override Default MSBuild properties-->
<PropertyGroup>
<TargetName>$(ExecutableName)</TargetName>
<TargetExt>.exe</TargetExt>
<OutputType>Exe</OutputType>
</PropertyGroup>
<PropertyGroup>
<ToolsDir>$(FrameworkLibPath)\..\tools\</ToolsDir>
<TargetFramework>netcoreapp2.1</TargetFramework>
<!-- Don't warn if some dependencies were rolled forward -->
<NoWarn>$(NoWarn);NU1603</NoWarn>
</PropertyGroup>
<ItemGroup>
<RdXmlFile Include="default.rd.xml" />
<AppContextSwitchOverrides Include="Switch.System.Enum.RelaxedGetValues" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="xunit.abstractions">
<Version>$(XunitAbstractionsVersion)</Version>
</PackageReference>
<PackageReference Include="xunit.assert">
<Version>$(XunitPackageVersion)</Version>
</PackageReference>
<PackageReference Include="xunit.extensibility.core">
<Version>$(XunitPackageVersion)</Version>
</PackageReference>
<PackageReference Include="xunit.core">
<Version>$(XunitPackageVersion)</Version>
</PackageReference>
<PackageReference Include="xunit.runner.utility">
<Version>$(XunitRunnerUtilityVersion)</Version>
</PackageReference>
<PackageReference Include="xunit.extensibility.execution">
<Version>$(XunitPackageVersion)</Version>
</PackageReference>
<PackageReference Include="microsoft.xunit.netcore.extensions">
<Version>$(XunitNetcoreExtensionsVersion)</Version>
</PackageReference>
<PackageReference Include="CoreFx.Private.TestUtilities">
<Version>$(CoreFxTestUtilitiesVersion)</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>
<!-- Some tests consist of multiple assemblies - make sure ILC sees them -->
<IlcCompileInput Include="$(MSBuildProjectDirectory)\*.dll" />
</ItemGroup>
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
<!-- Set OutputPath after the SDK targets have been imported-->
<PropertyGroup>
<OutputPath>$(MSBuildProjectDirectory)\</OutputPath>
<IntermediateOutputPath>$(MSBuildProjectDirectory)\</IntermediateOutputPath>
</PropertyGroup>
<!-- Switch RuntimeIdentifier according to currently running OSGroup -->
<PropertyGroup>
<RuntimeIdentifier Condition="'$(OSGroup)' == 'Windows_NT'">win-x64</RuntimeIdentifier>
<RuntimeIdentifier Condition="'$(OSGroup)' == 'Linux'">linux-x64</RuntimeIdentifier>
<RuntimeIdentifier Condition="'$(OSGroup)' == 'OSX'">osx-x64</RuntimeIdentifier>
</PropertyGroup>
<!-- Import CoreRT build targets -->
<Import Project="$(IlcPath)\build\Microsoft.NETCore.Native.targets" />
<!-- Since tests are already compiled, override Compile target to prevent CSC running -->
<Target Name="Compile" />
</Project>

View File

@@ -0,0 +1,41 @@
<Directives
xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<Assembly Name="*Application*" Dynamic="Required All" />
<Assembly Name="xunit.abstractions" Dynamic="Required All" />
<Assembly Name="System.Private.CoreLib">
<Type Name="System.Runtime.CompilerServices.CompilationRelaxationsAttribute" Dynamic="Required All" />
<Type Name="System.Runtime.CompilerServices.RuntimeCompatibilityAttribute" Dynamic="Required All" />
<Type Name="System.Runtime.CompilerServices.ExtensionAttribute" Dynamic="Required All" />
<Type Name="System.Runtime.CompilerServices.IntrinsicAttribute" Dynamic="Required All" />
<Type Name="System.Diagnostics.DebuggableAttribute" Dynamic="Required All" />
<Type Name="System.Reflection.AssemblyInformationalVersionAttribute" Dynamic="Required All" />
<Type Name="System.Reflection.AssemblyTitleAttribute" Dynamic="Required All" />
<Type Name="System.Reflection.AssemblyFileVersionAttribute" Dynamic="Required All" />
<Type Name="System.Reflection.AssemblyDescriptionAttribute" Dynamic="Required All" />
<Type Name="System.Reflection.AssemblyCompanyAttribute" Dynamic="Required All" />
<Type Name="System.Reflection.AssemblyCopyrightAttribute" Dynamic="Required All" />
<Type Name="System.Reflection.AssemblyProductAttribute" Dynamic="Required All" />
<Type Name="System.Reflection.AssemblyDefaultAliasAttribute" Dynamic="Required All" />
<Type Name="System.Reflection.AssemblyMetadataAttribute" Dynamic="Required All" />
<Type Name="System.AttributeUsageAttribute" Dynamic="Required All" />
<Type Name="System.AttributeUsageAttribute[]" Dynamic="Required All" />
<Type Name="System.Runtime.InteropServices.ComVisibleAttribute" Dynamic="Required All" />
<Type Name="System.CLSCompliantAttribute" Dynamic="Required All" />
</Assembly>
<Assembly Name="mscorlib">
<Type Name="System.IO.File" Dynamic="Required All"/>
<Type Name="System.Threading.ExecutionContext" Dynamic="Required All"/>
<Type Name="System.Threading.ContextCallback" Dynamic="Required All"/>
</Assembly>
<Assembly Name="xunit.core" Dynamic="Required All" />
<Assembly Name="xunit.runner.utility.dotnet" Dynamic="Required All" />
<Assembly Name="xunit.execution.dotnet" Dynamic="Required All" />
<Assembly Name="xunit.abstractions" Dynamic="Required All" />
<Assembly Name="xunit.core" Dynamic="Required All">
<Type Name="Xunit.Sdk.BeforeAfterTestAttribute[]" Dynamic="Required All" />
</Assembly>
<Assembly Name="Xunit.NetCore.Extensions" Dynamic="Required All" />
<Assembly Name="System.Linq.Expressions" Dynamic="Required All" />
</Application>
</Directives>

View File

@@ -0,0 +1,33 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Don't import the project's parent dir.props - all other projects in the CoreRT repo are set up for the old project format -->
<!--
$(OS) is set to Unix/Windows_NT. This comes from an environment variable on Windows and MSBuild on Unix.
-->
<PropertyGroup>
<OsEnvironment Condition="'$(OsEnvironment)'==''">$(OS)</OsEnvironment>
</PropertyGroup>
<!-- Common repo directories -->
<PropertyGroup>
<CopyNuGetImplementations Condition="'$(CopyNuGetImplementations)'==''">false</CopyNuGetImplementations>
<ProjectDir>$(MSBuildThisFileDirectory)\</ProjectDir>
<SourceDir>$(ProjectDir)src\</SourceDir>
<PackagesDir>$(ProjectDir)..\..\..\packages\</PackagesDir>
<ToolsDir Condition="'$(ToolsDir)'==''">$(ProjectDir)..\Tools\</ToolsDir>
<DotnetCliPath Condition="'$(DotnetCliPath)'==''">$(ToolsDir)dotnetcli/</DotnetCliPath>
<SkipImportILTargets>true</SkipImportILTargets>
</PropertyGroup>
<!-- Provides properties for dependency versions and configures dependency verification/auto-upgrade. -->
<Import Project="$(MSBuildThisFileDirectory)\..\dependencies.props" />
<!-- list of nuget package sources passed to dnu -->
<ItemGroup>
<!-- Need to escape double forward slash (%2F) or MSBuild will normalize to one slash on Unix. -->
<DotnetSourceList Include="https:%2F%2Fdotnet.myget.org/F/dotnet-core/api/v3/index.json" />
<DotnetSourceList Include="https:%2F%2Fapi.nuget.org/v3/index.json" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,107 @@
@if not defined __echo @echo off
setlocal EnableDelayedExpansion
:: Set the default arguments
set __BuildArch=x64
set __BuildType=Debug
set __BuildOS=Windows_NT
:: Default to highest Visual Studio version available
set __VSVersion=vs2017
set __VSProductVersion=150
:: Define a prefix for most output progress messages that come from this script. That makes
:: it easier to see where these are coming from. Note that there is a trailing space here.
set __MsgPrefix=RUNTEST:
set __ProjectDir=%~dp0
:: remove trailing slash
if %__ProjectDir:~-1%==\ set "__ProjectDir=%__ProjectDir:~0,-1%"
set "__ProjectFilesDir=%__ProjectDir%"
set "__RootBinDir=%__ProjectDir%\..\bin"
set "__LogsDir=%__RootBinDir%\Logs"
:Arg_Loop
if "%1" == "" goto ArgsDone
if /i "%1" == "/?" goto Usage
if /i "%1" == "-?" goto Usage
if /i "%1" == "/h" goto Usage
if /i "%1" == "-h" goto Usage
if /i "%1" == "/help" goto Usage
if /i "%1" == "-help" goto Usage
if /i "%1" == "x64" (set __BuildArch=x64&set __MSBuildBuildArch=x64&shift&goto Arg_Loop)
if /i "%1" == "x86" (set __BuildArch=x86&set __MSBuildBuildArch=x86&shift&goto Arg_Loop)
if /i "%1" == "debug" (set __BuildType=Debug&shift&goto Arg_Loop)
if /i "%1" == "release" (set __BuildType=Release&shift&goto Arg_Loop)
if /i "%1" == "LogsDir" (set __LogsDir=%2&shift&shift&goto Arg_Loop)
if /i not "%1" == "msbuildargs" goto SkipMsbuildArgs
set CORE_ROOT=%1
echo %__MsgPrefix%CORE_ROOT is initially set to: "%CORE_ROOT%"
shift
:ArgsDone
set "__TestWorkingDir=%CoreRT_TestRoot\CoreFX%"
if not defined XunitTestBinBase set XunitTestBinBase=%__TestWorkingDir%
if not exist %__LogsDir% md %__LogsDir%
:: Check presence of VS
if not defined VS%__VSProductVersion%COMNTOOLS goto NoVS
set __VSToolsRoot=!VS%__VSProductVersion%COMNTOOLS!
if %__VSToolsRoot:~-1%==\ set "__VSToolsRoot=%__VSToolsRoot:~0,-1%"
:: Set the environment for the build- VS cmd prompt
echo %__MsgPrefix%Using environment: "%__VSToolsRoot%\VsDevCmd.bat"
call "%__VSToolsRoot%\VsDevCmd.bat"
if not defined VSINSTALLDIR (
echo %__MsgPrefix%Error: runtest.cmd should be run from a Visual Studio Command Prompt. Please see https://github.com/dotnet/coreclr/blob/master/Documentation/project-docs/developer-guide.md for build instructions.
exit /b 1
)
if not defined FXCustomTestLauncher (
echo The CoreFX test launcher is not defined
exit /b 1
)
set SAVED_ERROR_LEVEL=0
:: Iterate through unzipped CoreFX tests
for /D %%i in ("%XunitTestBinBase%\*" ) do (
set TestFolderName=%%i
set TestFileName=%%~nxi
echo %FXCustomTestLauncher% !TestFolderName! !TestFileName!
call %FXCustomTestLauncher% !TestFolderName! !TestFileName!
set TestExitCode=!errorlevel!
if !TestExitCode! neq 0 (
echo Test !TestFileName! failed with !TestExitCode!
set SAVED_ERROR_LEVEL=!TestExitCode!
)
)
exit /b !SAVED_ERROR_LEVEL!
:Usage
echo.
echo Usage:
echo %0 BuildArch BuildType
echo where:
echo.
echo./? -? /h -h /help -help: view this message.
echo BuildArch- Optional parameter - x64 or x86 ^(default: x64^).
echo BuildType- Optional parameter - Debug, Release, or Checked ^(default: Debug^).
exit /b 1
:NoVS
echo Visual Studio 2017 ^(Community is free^) is a prerequisite to build this repository.
echo See: https://github.com/dotnet/coreclr/blob/master/Documentation/project-docs/developer-guide.md#prerequisites
exit /b 1

View File

@@ -0,0 +1,80 @@
# Exit code constants
readonly EXIT_CODE_SUCCESS=0 # Script ran normally.
readonly EXIT_CODE_EXCEPTION=1 # Script exited because something exceptional happened (e.g. bad arguments, Ctrl-C interrupt).
readonly EXIT_CODE_TEST_FAILURE=2 # Script completed successfully, but one or more tests failed.
function print_usage {
echo ''
echo 'CoreFX test runner script.'
echo ''
echo 'Typical command line:'
echo ''
echo 'corefx/tests/runtest.sh'
echo ' --testRootDir="tests_downloaded/CoreFX"'
echo ' --testLauncher="tests/CoreFX/corerun"'
echo ''
echo 'Required arguments:'
echo ' --testRootDir=<path> : Root directory of the CoreFX test build '
echo ' --testLauncher=<path> : Path to the test launcher script'
}
function run_tests_in_directory {
local savedErroLevel=$EXIT_CODE_SUCCESS
local testDir=$1
for testSubDir in ${testDir}/* ; do
# Build and run each test
echo Building ${testSubDir}
${FXCustomTestLauncher} ${testSubDir} ${__LogDir}
if [ $? != 0 ];
then
savedErroLevel=$EXIT_CODE_TEST_FAILURE
fi
done
return $savedErroLevel
}
# Argument variables
testRootDir=
__LogDir=
FXCustomTestLauncher=
for i in "$@"
do
case $i in
--testRootDir=*)
testRootDir=${i#*=}
;;
--logdir=*)
__LogDir=${i#*=}
;;
--testLauncher=*)
FXCustomTestLauncher=${i#*=}
;;
*)
echo "Unknown switch: $i"
print_usage
exit $EXIT_CODE_SUCCESS
;;
esac
done
if [ -z "$testRootDir" ]; then
echo "--testRootDir is required."
print_usage
exit $EXIT_CODE_EXCEPTION
fi
if [ ! -d "$testRootDir" ]; then
echo "Directory specified by --testRootDir does not exist: $testRootDir"
exit $EXIT_CODE_EXCEPTION
fi
if [ -z "$__LogDir" ]; then
__LogDir=$testRootDir
fi
run_tests_in_directory ${testRootDir}
exit

View File

@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\dir.props" />
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<OutputType>Exe</OutputType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json">
<Version>$(NewtonsoftJsonVersion)</Version>
</PackageReference>
<PackageReference Include="Newtonsoft.Json.Schema">
<Version>$(NewtonsoftJsonSchemaVersion)</Version>
</PackageReference>
<PackageReference Include="System.CommandLine">
<Version>$(SystemCommandLineVersion)</Version>
</PackageReference>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace CoreFX.TestUtils.TestFileSetup
{
public class RSPGenerator
{
public void GenerateRSPFile(XUnitTestAssembly testDefinition, string outputPath)
{
if (!Directory.Exists(outputPath))
{
Directory.CreateDirectory(outputPath);
}
string rspFilePath = Path.Combine(outputPath, testDefinition.Name + ".rsp");
if (File.Exists(rspFilePath))
File.Delete(rspFilePath);
using (StreamWriter sr = File.CreateText(rspFilePath))
{
if (testDefinition.Exclusions == null)
return;
// Method exclusions
if (testDefinition.Exclusions.Methods != null)
{
foreach (Exclusion exclusion in testDefinition.Exclusions.Methods)
{
if (String.IsNullOrWhiteSpace(exclusion.Name))
continue;
sr.Write("-skipmethod ");
sr.Write(exclusion.Name);
sr.WriteLine();
}
}
// Class exclusions
if (testDefinition.Exclusions.Classes != null)
{
foreach (Exclusion exclusion in testDefinition.Exclusions.Classes)
{
if (String.IsNullOrWhiteSpace(exclusion.Name))
continue;
sr.Write("-skipclass ");
sr.Write(exclusion.Name);
sr.WriteLine();
}
}
// Namespace exclusions
if (testDefinition.Exclusions.Namespaces != null)
{
foreach (Exclusion exclusion in testDefinition.Exclusions.Namespaces)
{
if (String.IsNullOrWhiteSpace(exclusion.Name))
continue;
sr.Write("-skipnamespace ");
sr.Write(exclusion.Name);
sr.WriteLine();
}
}
}
}
}
}

View File

@@ -0,0 +1,329 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Schema;
using Newtonsoft.Json.Schema.Generation;
namespace CoreFX.TestUtils.TestFileSetup
{
/// <summary>
/// Defines the set of flags that represent exit codes
/// </summary>
[Flags]
public enum ExitCode : int
{
Success = 0,
HttpError = 1,
IOError = 2,
JsonSchemaValidationError = 3,
UnknownError = 10
}
/// <summary>
/// This helper class is used to fetch CoreFX tests from a specified URL, unarchive them and create a flat directory structure
/// through which to iterate.
/// </summary>
public static class TestFileSetup
{
private static HttpClient httpClient;
private static bool cleanTestBuild = false;
private static string outputDir;
private static string testUrl;
private static string testListPath;
public static void Main(string[] args)
{
ExitCode exitCode = ExitCode.UnknownError;
ArgumentSyntax argSyntax = ParseCommandLine(args);
try
{
if (!Directory.Exists(outputDir))
Directory.CreateDirectory(outputDir);
if (cleanTestBuild)
{
CleanBuild(outputDir);
}
// Map test names to their definitions
Dictionary<string, XUnitTestAssembly> testAssemblyDefinitions = DeserializeTestJson(testListPath);
SetupTests(testUrl, outputDir, testAssemblyDefinitions).Wait();
exitCode = ExitCode.Success;
}
catch (AggregateException e)
{
e.Handle(innerExc =>
{
if (innerExc is HttpRequestException)
{
exitCode = ExitCode.HttpError;
Console.WriteLine("Error downloading tests from: " + testUrl);
Console.WriteLine(innerExc.Message);
return true;
}
else if (innerExc is IOException)
{
exitCode = ExitCode.IOError;
Console.WriteLine(innerExc.Message);
return true;
}
else if (innerExc is JSchemaValidationException || innerExc is JsonSerializationException)
{
exitCode = ExitCode.JsonSchemaValidationError;
Console.WriteLine("Error validating test list: ");
Console.WriteLine(innerExc.Message);
return true;
}
return false;
});
}
Environment.Exit((int)exitCode);
}
private static ArgumentSyntax ParseCommandLine(string[] args)
{
ArgumentSyntax argSyntax = ArgumentSyntax.Parse(args, syntax =>
{
syntax.DefineOption("out|outDir|outputDirectory", ref outputDir, "Directory where tests are downloaded");
syntax.DefineOption("testUrl", ref testUrl, "URL, pointing to the list of tests");
syntax.DefineOption("testListJsonPath", ref testListPath, "JSON-formatted list of test assembly names to download");
syntax.DefineOption("clean|cleanOutputDir", ref cleanTestBuild, "Clean test assembly output directory");
});
return argSyntax;
}
private static Dictionary<string, XUnitTestAssembly> DeserializeTestJson(string testDefinitionFilePath)
{
JSchemaGenerator jsonGenerator = new JSchemaGenerator();
JSchema testDefinitionSchema = jsonGenerator.Generate(typeof(IList<XUnitTestAssembly>));
IList<XUnitTestAssembly> testAssemblies = new List<XUnitTestAssembly>();
IList<string> validationMessages = new List<string>();
using (var sr = new StreamReader(testDefinitionFilePath))
using (var jsonReader = new JsonTextReader(sr))
using (var jsonValidationReader = new JSchemaValidatingReader(jsonReader))
{
// Create schema validator
jsonValidationReader.Schema = testDefinitionSchema;
jsonValidationReader.ValidationEventHandler += (o, a) => validationMessages.Add(a.Message);
// Deserialize json test assembly definitions
JsonSerializer serializer = new JsonSerializer();
try
{
testAssemblies = serializer.Deserialize<List<XUnitTestAssembly>>(jsonValidationReader);
}
catch (JsonSerializationException ex)
{
throw new AggregateException(ex);
}
}
// TODO - ABORT AND WARN
if (validationMessages.Count != 0)
{
StringBuilder aggregateExceptionMessage = new StringBuilder();
foreach (string validationMessage in validationMessages)
{
aggregateExceptionMessage.Append("JSON Validation Error: ");
aggregateExceptionMessage.Append(validationMessage);
aggregateExceptionMessage.AppendLine();
}
throw new AggregateException(new JSchemaValidationException(aggregateExceptionMessage.ToString()));
}
var nameToTestAssemblyDef = new Dictionary<string, XUnitTestAssembly>();
// Map test names to their definitions
foreach (XUnitTestAssembly assembly in testAssemblies)
{
nameToTestAssemblyDef.Add(assembly.Name, assembly);
}
return nameToTestAssemblyDef;
}
private static async Task SetupTests(string jsonUrl, string destinationDirectory, Dictionary<string, XUnitTestAssembly> testDefinitions = null, bool runAllTests = false)
{
Debug.Assert(Directory.Exists(destinationDirectory));
Debug.Assert(runAllTests || testDefinitions != null);
string tempDirPath = Path.Combine(destinationDirectory, "temp");
if (!Directory.Exists(tempDirPath))
{
Directory.CreateDirectory(tempDirPath);
}
Dictionary<string, XUnitTestAssembly> testPayloads = await GetTestUrls(jsonUrl, testDefinitions, runAllTests);
if (testPayloads == null)
{
return;
}
await GetTestArchives(testPayloads, tempDirPath);
ExpandArchivesInDirectory(tempDirPath, destinationDirectory);
RSPGenerator rspGenerator = new RSPGenerator();
foreach (XUnitTestAssembly assembly in testDefinitions.Values)
{
rspGenerator.GenerateRSPFile(assembly, Path.Combine(destinationDirectory, assembly.Name));
}
Directory.Delete(tempDirPath);
}
private static async Task<Dictionary<string, XUnitTestAssembly>> GetTestUrls(string jsonUrl, Dictionary<string, XUnitTestAssembly> testDefinitions = null, bool runAllTests = false)
{
if (httpClient is null)
{
httpClient = new HttpClient();
}
Debug.Assert(runAllTests || testDefinitions != null);
// Set up the json stream reader
using (var responseStream = await httpClient.GetStreamAsync(jsonUrl))
using (var streamReader = new StreamReader(responseStream))
using (var jsonReader = new JsonTextReader(streamReader))
{
// Manual parsing - we only need to key-value pairs from each object and this avoids deserializing all of the work items into objects
string markedTestName = string.Empty;
string currentPropertyName = string.Empty;
while (jsonReader.Read())
{
if (jsonReader.Value != null)
{
switch (jsonReader.TokenType)
{
case JsonToken.PropertyName:
currentPropertyName = jsonReader.Value.ToString();
break;
case JsonToken.String:
if (currentPropertyName.Equals("WorkItemId"))
{
string currentTestName = jsonReader.Value.ToString();
if (runAllTests || testDefinitions.ContainsKey(currentTestName))
{
markedTestName = currentTestName;
}
}
else if (currentPropertyName.Equals("PayloadUri") && markedTestName != string.Empty)
{
if (!testDefinitions.ContainsKey(markedTestName))
{
testDefinitions[markedTestName] = new XUnitTestAssembly() { Name = markedTestName };
}
testDefinitions[markedTestName].Url = jsonReader.Value.ToString();
markedTestName = string.Empty;
}
break;
}
}
}
}
return testDefinitions;
}
private static async Task GetTestArchives(Dictionary<string, XUnitTestAssembly> testPayloads, string downloadDir)
{
if (httpClient is null)
{
httpClient = new HttpClient();
}
foreach (string testName in testPayloads.Keys)
{
string payloadUri = testPayloads[testName].Url;
if (!Uri.IsWellFormedUriString(payloadUri, UriKind.Absolute))
continue;
using (var response = await httpClient.GetStreamAsync(payloadUri))
{
if (response.CanRead)
{
// Create the test setup directory if it doesn't exist
if (!Directory.Exists(downloadDir))
{
Directory.CreateDirectory(downloadDir);
}
// CoreFX test archives are output as .zip regardless of platform
string archivePath = Path.Combine(downloadDir, testName + ".zip");
// Copy to a temp folder
using (FileStream file = new FileStream(archivePath, FileMode.Create))
{
await response.CopyToAsync(file);
}
}
}
}
}
private static void ExpandArchivesInDirectory(string archiveDirectory, string destinationDirectory, bool cleanup = true)
{
Debug.Assert(Directory.Exists(archiveDirectory));
Debug.Assert(Directory.Exists(destinationDirectory));
string[] archives = Directory.GetFiles(archiveDirectory, "*.zip", SearchOption.TopDirectoryOnly);
foreach (string archivePath in archives)
{
string destinationDirName = Path.Combine(destinationDirectory, Path.GetFileNameWithoutExtension(archivePath));
ZipFile.ExtractToDirectory(archivePath, destinationDirName);
// Delete archives
if (cleanup)
{
File.Delete(archivePath);
}
}
}
private static void CleanBuild(string directoryToClean)
{
Debug.Assert(Directory.Exists(directoryToClean));
DirectoryInfo dirInfo = new DirectoryInfo(directoryToClean);
foreach (FileInfo file in dirInfo.EnumerateFiles())
{
file.Delete();
}
foreach (DirectoryInfo dir in dirInfo.EnumerateDirectories())
{
dir.Delete(true);
}
}
}
}

View File

@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json;
namespace CoreFX.TestUtils.TestFileSetup
{
public class XUnitTestAssembly
{
[JsonRequired]
[JsonProperty("name")]
public string Name;
[JsonRequired]
[JsonProperty("exclusions")]
public Exclusions Exclusions;
// Used to assign a test url or to override it via the json file definition
[JsonIgnore]
[JsonProperty(Required = Required.Default)]
public string Url;
}
public class Exclusions
{
[JsonProperty("namespaces")]
public Exclusion[] Namespaces;
[JsonProperty("classes")]
public Exclusion[] Classes;
[JsonProperty("methods")]
public Exclusion[] Methods;
}
public class Exclusion
{
[JsonRequired]
[JsonProperty("name", Required = Required.DisallowNull)]
public string Name;
[JsonRequired]
[JsonProperty("reason", Required = Required.DisallowNull)]
public string Reason;
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\dir.props" />
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<OutputType>Exe</OutputType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json">
<Version>$(NewtonsoftJsonVersion)</Version>
</PackageReference>
<PackageReference Include="System.CommandLine">
<Version>$(SystemCommandLineVersion)</Version>
</PackageReference>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,132 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
/// <summary>
/// This helper class reads xunit xml log files and prints the tallied test results to the console
/// </summary>
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Net.Http;
using System.Reflection;
using System.Threading.Tasks;
using System.Xml;
using Newtonsoft.Json;
namespace CoreFX.TestUtils.XUnit
{
public static class ResultFormatter
{
private static string logDir;
private static string logPattern;
public static void Main(string[] args)
{
ArgumentSyntax syntax = ParseCommandLine(args);
IEnumerable<string> logFiles = DiscoverLogs(logDir, logPattern);
PrintTotals(logFiles);
}
private static void PrintTotals(IEnumerable<string> logFiles)
{
int total = 0;
int passed = 0;
int failed = 0;
int skipped = 0;
ulong timeElapsed = 0;
bool printTotals = false;
foreach (string logFile in logFiles)
{
try
{
// XMLReader escapes the character sequence \\.. as just a single backslash \ - Is this intended behavior?
using (XmlReader reader = XmlReader.Create(logFile.Replace(@"\\..", @"\..")))
{
reader.MoveToContent();
reader.ReadToDescendant("collection");
do
{
// Get total tests in current element
string totalAttr = reader.GetAttribute("total");
int currentTotal;
Int32.TryParse(totalAttr, out currentTotal);
// Get passed tests
string passedAttr = reader.GetAttribute("passed");
int currentPassed;
Int32.TryParse(passedAttr, out currentPassed);
// Get failed tests
string failedAttr = reader.GetAttribute("failed");
int currentFailed;
Int32.TryParse(failedAttr, out currentFailed);
// Get skipped tests
string skippedAttr = reader.GetAttribute("skipped");
int currentSkipped;
Int32.TryParse(skippedAttr, out currentSkipped);
// Get time elapsed
string timeAttr = reader.GetAttribute("time");
ulong currentTime;
UInt64.TryParse(timeAttr, out currentTime);
// Update running total only once current element has been parsed
total += currentTotal;
passed += currentPassed;
failed += currentFailed;
skipped += currentSkipped;
timeElapsed += currentTime;
} while (reader.ReadToNextSibling("collection"));
// If we've fully parsed a log, print totals
printTotals = true;
}
}
catch (XmlException exc)
{
Console.WriteLine("Malformed Log: {0} ", logFile);
Console.WriteLine("Reason: {0} ", exc.Message);
continue;
}
}
if (printTotals)
{
Console.WriteLine("=== CoreFX TEST EXECUTION SUMMARY ===: ");
Console.WriteLine(String.Format("Total: {0}, Passed: {1}, Failed: {2}, Skipped: {3}", total, passed, failed, timeElapsed));
Console.WriteLine("Detailed logs written to: " + logDir);
}
}
private static ArgumentSyntax ParseCommandLine(string[] args)
{
ArgumentSyntax argSyntax = ArgumentSyntax.Parse(args, syntax =>
{
syntax.DefineOption("log|logDirectory|logDir", ref logDir, "Path to directory of xml test results");
syntax.DefineOption("pattern|p", ref logPattern, "Pattern of XUnit log filenames for which to search");
});
return argSyntax;
}
public static IEnumerable<string> DiscoverLogs(string logDirectory, string logPattern)
{
Debug.Assert(Directory.Exists(logDirectory));
Console.WriteLine(logDirectory);
var logFiles = Directory.EnumerateFiles(logDirectory, logPattern, SearchOption.AllDirectories);
return logFiles;
}
}
}