Replace RunTests scripts with .NET app (#20337)
This commit is contained in:
parent
b73e221c64
commit
ca5cd91d68
|
|
@ -0,0 +1,2 @@
|
|||
<Project>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<Project>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// 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.
|
||||
|
||||
namespace RunTests
|
||||
{
|
||||
public class ProcessResult
|
||||
{
|
||||
public ProcessResult(string standardOutput, string standardError, int exitCode)
|
||||
{
|
||||
StandardOutput = standardOutput;
|
||||
StandardError = standardError;
|
||||
ExitCode = exitCode;
|
||||
}
|
||||
|
||||
public string StandardOutput { get; }
|
||||
public string StandardError { get; }
|
||||
public int ExitCode { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
// 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.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace RunTests
|
||||
{
|
||||
public static class ProcessUtil
|
||||
{
|
||||
[DllImport("libc", SetLastError = true, EntryPoint = "kill")]
|
||||
private static extern int sys_kill(int pid, int sig);
|
||||
|
||||
public static async Task<ProcessResult> RunAsync(
|
||||
string filename,
|
||||
string arguments,
|
||||
string? workingDirectory = null,
|
||||
bool throwOnError = true,
|
||||
IDictionary<string, string?>? environmentVariables = null,
|
||||
Action<string>? outputDataReceived = null,
|
||||
Action<string>? errorDataReceived = null,
|
||||
Action<int>? onStart = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
Console.WriteLine($"Running '{filename} {arguments}'");
|
||||
using var process = new Process()
|
||||
{
|
||||
StartInfo =
|
||||
{
|
||||
FileName = filename,
|
||||
Arguments = arguments,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
},
|
||||
EnableRaisingEvents = true
|
||||
};
|
||||
|
||||
|
||||
if (workingDirectory != null)
|
||||
{
|
||||
process.StartInfo.WorkingDirectory = workingDirectory;
|
||||
}
|
||||
|
||||
if (environmentVariables != null)
|
||||
{
|
||||
foreach (var kvp in environmentVariables)
|
||||
{
|
||||
process.StartInfo.Environment.Add(kvp);
|
||||
}
|
||||
}
|
||||
|
||||
var outputBuilder = new StringBuilder();
|
||||
process.OutputDataReceived += (_, e) =>
|
||||
{
|
||||
if (e.Data != null)
|
||||
{
|
||||
if (outputDataReceived != null)
|
||||
{
|
||||
outputDataReceived.Invoke(e.Data);
|
||||
}
|
||||
else
|
||||
{
|
||||
outputBuilder.AppendLine(e.Data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var errorBuilder = new StringBuilder();
|
||||
process.ErrorDataReceived += (_, e) =>
|
||||
{
|
||||
if (e.Data != null)
|
||||
{
|
||||
if (errorDataReceived != null)
|
||||
{
|
||||
errorDataReceived.Invoke(e.Data);
|
||||
}
|
||||
else
|
||||
{
|
||||
errorBuilder.AppendLine(e.Data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var processLifetimeTask = new TaskCompletionSource<ProcessResult>();
|
||||
|
||||
process.Exited += (_, e) =>
|
||||
{
|
||||
Console.WriteLine($"'{process.StartInfo.FileName} {process.StartInfo.Arguments}' completed with exit code '{process.ExitCode}'");
|
||||
if (throwOnError && process.ExitCode != 0)
|
||||
{
|
||||
processLifetimeTask.TrySetException(new InvalidOperationException($"Command {filename} {arguments} returned exit code {process.ExitCode}"));
|
||||
}
|
||||
else
|
||||
{
|
||||
processLifetimeTask.TrySetResult(new ProcessResult(outputBuilder.ToString(), errorBuilder.ToString(), process.ExitCode));
|
||||
}
|
||||
};
|
||||
|
||||
process.Start();
|
||||
onStart?.Invoke(process.Id);
|
||||
|
||||
process.BeginOutputReadLine();
|
||||
process.BeginErrorReadLine();
|
||||
|
||||
var cancelledTcs = new TaskCompletionSource<object?>();
|
||||
await using var _ = cancellationToken.Register(() => cancelledTcs.TrySetResult(null));
|
||||
|
||||
var result = await Task.WhenAny(processLifetimeTask.Task, cancelledTcs.Task);
|
||||
|
||||
if (result == cancelledTcs.Task)
|
||||
{
|
||||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
sys_kill(process.Id, sig: 2); // SIGINT
|
||||
|
||||
var cancel = new CancellationTokenSource();
|
||||
|
||||
await Task.WhenAny(processLifetimeTask.Task, Task.Delay(TimeSpan.FromSeconds(5), cancel.Token));
|
||||
|
||||
cancel.Cancel();
|
||||
}
|
||||
|
||||
if (!process.HasExited)
|
||||
{
|
||||
process.CloseMainWindow();
|
||||
|
||||
if (!process.HasExited)
|
||||
{
|
||||
process.Kill();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return await processLifetimeTask.Task;
|
||||
}
|
||||
|
||||
public static void KillProcess(int pid)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var process = Process.GetProcessById(pid);
|
||||
process?.Kill();
|
||||
}
|
||||
catch (ArgumentException) { }
|
||||
catch (InvalidOperationException) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,235 @@
|
|||
// 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.CommandLine;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace RunTests
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static async Task Main(string[] args)
|
||||
{
|
||||
var command = new RootCommand()
|
||||
{
|
||||
new Option(
|
||||
aliases: new string[] { "--target", "-t" },
|
||||
description: "The test dll to run")
|
||||
{ Argument = new Argument<string>(), Required = true },
|
||||
|
||||
new Option(
|
||||
aliases: new string[] { "--sdk" },
|
||||
description: "The version of the sdk being used")
|
||||
{ Argument = new Argument<string>(), Required = true },
|
||||
|
||||
new Option(
|
||||
aliases: new string[] { "--runtime" },
|
||||
description: "The version of the runtime being used")
|
||||
{ Argument = new Argument<string>(), Required = true },
|
||||
|
||||
new Option(
|
||||
aliases: new string[] { "--queue" },
|
||||
description: "The name of the Helix queue being run on")
|
||||
{ Argument = new Argument<string>(), Required = true },
|
||||
|
||||
new Option(
|
||||
aliases: new string[] { "--arch" },
|
||||
description: "The architecture being run on")
|
||||
{ Argument = new Argument<string>(), Required = true },
|
||||
|
||||
new Option(
|
||||
aliases: new string[] { "--quarantined" },
|
||||
description: "Whether quarantined tests should run or not")
|
||||
{ Argument = new Argument<bool>(), Required = true },
|
||||
|
||||
new Option(
|
||||
aliases: new string[] { "--ef" },
|
||||
description: "The version of the EF tool to use")
|
||||
{ Argument = new Argument<string>(), Required = true },
|
||||
};
|
||||
|
||||
var parseResult = command.Parse(args);
|
||||
var target = parseResult.ValueForOption<string>("--target");
|
||||
var sdkVersion = parseResult.ValueForOption<string>("--sdk");
|
||||
var runtimeVersion = parseResult.ValueForOption<string>("--runtime");
|
||||
var helixQueue = parseResult.ValueForOption<string>("--queue");
|
||||
var architecture = parseResult.ValueForOption<string>("--arch");
|
||||
var quarantined = parseResult.ValueForOption<bool>("--quarantined");
|
||||
var efVersion = parseResult.ValueForOption<string>("--ef");
|
||||
|
||||
var HELIX_WORKITEM_ROOT = Environment.GetEnvironmentVariable("HELIX_WORKITEM_ROOT");
|
||||
|
||||
var path = Environment.GetEnvironmentVariable("PATH");
|
||||
var dotnetRoot = Environment.GetEnvironmentVariable("DOTNET_ROOT");
|
||||
|
||||
// Rename default.NuGet.config to NuGet.config if there is not a custom one from the project
|
||||
// We use a local NuGet.config file to avoid polluting global machine state and avoid relying on global machine state
|
||||
if (!File.Exists("NuGet.config"))
|
||||
{
|
||||
File.Copy("default.NuGet.config", "NuGet.config");
|
||||
}
|
||||
|
||||
var environmentVariables = new Dictionary<string, string>();
|
||||
environmentVariables.Add("PATH", path);
|
||||
environmentVariables.Add("DOTNET_ROOT", dotnetRoot);
|
||||
environmentVariables.Add("helix", helixQueue);
|
||||
|
||||
Console.WriteLine($"Current Directory: {HELIX_WORKITEM_ROOT}");
|
||||
var helixDir = HELIX_WORKITEM_ROOT;
|
||||
Console.WriteLine($"Setting HELIX_DIR: {helixDir}");
|
||||
environmentVariables.Add("HELIX_DIR", helixDir);
|
||||
environmentVariables.Add("NUGET_FALLBACK_PACKAGES", helixDir);
|
||||
var nugetRestore = Path.Combine(helixDir, "nugetRestore");
|
||||
Console.WriteLine($"Creating nuget restore directory: {nugetRestore}");
|
||||
environmentVariables.Add("NUGET_RESTORE", nugetRestore);
|
||||
var dotnetEFFullPath = Path.Combine(nugetRestore, $"dotnet-ef/{efVersion}/tools/netcoreapp3.1/any/dotnet-ef.exe");
|
||||
Console.WriteLine($"Set DotNetEfFullPath: {dotnetEFFullPath}");
|
||||
environmentVariables.Add("DotNetEfFullPath", dotnetEFFullPath);
|
||||
|
||||
Console.WriteLine("Checking for Microsoft.AspNetCore.App/");
|
||||
if (Directory.Exists("Microsoft.AspNetCore.App"))
|
||||
{
|
||||
Console.WriteLine($"Found Microsoft.AspNetCore.App/, copying to {dotnetRoot}/shared/Microsoft.AspNetCore.App/{runtimeVersion}");
|
||||
foreach (var file in Directory.EnumerateFiles("Microsoft.AspNetCore.App", "*.*", SearchOption.AllDirectories))
|
||||
{
|
||||
File.Copy(file, $"{dotnetRoot}/shared/Microsoft.AspNetCore.App/{runtimeVersion}", overwrite: true);
|
||||
}
|
||||
|
||||
Console.WriteLine($"Adding current directory to nuget sources: {HELIX_WORKITEM_ROOT}");
|
||||
|
||||
await ProcessUtil.RunAsync($"{dotnetRoot}/dotnet",
|
||||
$"nuget add source {HELIX_WORKITEM_ROOT} --configfile NuGet.config",
|
||||
environmentVariables: environmentVariables);
|
||||
|
||||
await ProcessUtil.RunAsync($"{dotnetRoot}/dotnet",
|
||||
"nuget add source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json --configfile NuGet.config",
|
||||
environmentVariables: environmentVariables);
|
||||
|
||||
// Write nuget sources to console, useful for debugging purposes
|
||||
await ProcessUtil.RunAsync($"{dotnetRoot}/dotnet",
|
||||
"nuget list source",
|
||||
environmentVariables: environmentVariables,
|
||||
outputDataReceived: Console.WriteLine,
|
||||
errorDataReceived: Console.WriteLine);
|
||||
|
||||
await ProcessUtil.RunAsync($"{dotnetRoot}/dotnet",
|
||||
$"tool install dotnet-ef --global --version {efVersion}",
|
||||
environmentVariables: environmentVariables);
|
||||
|
||||
// ';' is the path separator on Windows, and ':' on Unix
|
||||
path += RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ";" : ":";
|
||||
path += $"{Environment.GetEnvironmentVariable("DOTNET_CLI_HOME")}/.dotnet/tools";
|
||||
environmentVariables["PATH"] = path;
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(nugetRestore);
|
||||
|
||||
// Rename default.runner.json to xunit.runner.json if there is not a custom one from the project
|
||||
if (!File.Exists("xunit.runner.json"))
|
||||
{
|
||||
File.Copy("default.runner.json", "xunit.runner.json");
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Displaying directory contents:");
|
||||
foreach (var file in Directory.EnumerateFiles("./"))
|
||||
{
|
||||
Console.WriteLine(Path.GetFileName(file));
|
||||
}
|
||||
foreach (var file in Directory.EnumerateDirectories("./"))
|
||||
{
|
||||
Console.WriteLine(Path.GetFileName(file));
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
// Run test discovery so we know if there are tests to run
|
||||
var discoveryResult = await ProcessUtil.RunAsync($"{dotnetRoot}/dotnet",
|
||||
$"vstest {target} -lt",
|
||||
environmentVariables: environmentVariables);
|
||||
|
||||
if (discoveryResult.StandardOutput.Contains("Exception thrown"))
|
||||
{
|
||||
Console.WriteLine("Exception thrown during test discovery.");
|
||||
Console.WriteLine(discoveryResult.StandardOutput);
|
||||
Environment.Exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
var exitCode = 0;
|
||||
var commonTestArgs = $"vstest {target} --logger:xunit --logger:\"console;verbosity=normal\" --blame";
|
||||
if (quarantined)
|
||||
{
|
||||
Console.WriteLine("Running quarantined tests.");
|
||||
|
||||
// Filter syntax: https://github.com/Microsoft/vstest-docs/blob/master/docs/filter.md
|
||||
var result = await ProcessUtil.RunAsync($"{dotnetRoot}/dotnet",
|
||||
commonTestArgs + " --TestCaseFilter:\"Quarantined=true\"",
|
||||
environmentVariables: environmentVariables,
|
||||
outputDataReceived: Console.WriteLine,
|
||||
errorDataReceived: Console.WriteLine,
|
||||
throwOnError: false);
|
||||
|
||||
if (result.ExitCode != 0)
|
||||
{
|
||||
Console.WriteLine($"Failure in quarantined tests. Exit code: {result.ExitCode}.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Running non-quarantined tests.");
|
||||
|
||||
// Filter syntax: https://github.com/Microsoft/vstest-docs/blob/master/docs/filter.md
|
||||
var result = await ProcessUtil.RunAsync($"{dotnetRoot}/dotnet",
|
||||
commonTestArgs + " --TestCaseFilter:\"Quarantined!=true\"",
|
||||
environmentVariables: environmentVariables,
|
||||
outputDataReceived: Console.WriteLine,
|
||||
errorDataReceived: Console.Error.WriteLine,
|
||||
throwOnError: false);
|
||||
|
||||
if (result.ExitCode != 0)
|
||||
{
|
||||
Console.WriteLine($"Failure in non-quarantined tests. Exit code: {result.ExitCode}.");
|
||||
exitCode = result.ExitCode;
|
||||
}
|
||||
}
|
||||
|
||||
// 'testResults.xml' is the file Helix looks for when processing test results
|
||||
Console.WriteLine();
|
||||
if (File.Exists("TestResults/TestResults.xml"))
|
||||
{
|
||||
Console.WriteLine("Copying TestResults/TestResults.xml to ./testResults.xml");
|
||||
File.Copy("TestResults/TestResults.xml", "testResults.xml");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("No test results found.");
|
||||
}
|
||||
|
||||
var HELIX_WORKITEM_UPLOAD_ROOT = Environment.GetEnvironmentVariable("HELIX_WORKITEM_UPLOAD_ROOT");
|
||||
Console.WriteLine($"Copying artifacts/log/ to {HELIX_WORKITEM_UPLOAD_ROOT}/");
|
||||
if (Directory.Exists("artifacts/log"))
|
||||
{
|
||||
foreach (var file in Directory.EnumerateFiles("artifacts/log", "*.log", SearchOption.AllDirectories))
|
||||
{
|
||||
// Combine the directory name + log name for the copied log file name to avoid overwriting duplicate test names in different test projects
|
||||
var logName = $"{Path.GetFileName(Path.GetDirectoryName(file))}_{Path.GetFileName(file)}";
|
||||
Console.WriteLine($"Copying: {file} to {Path.Combine(HELIX_WORKITEM_UPLOAD_ROOT, logName)}");
|
||||
// Need to copy to HELIX_WORKITEM_UPLOAD_ROOT and HELIX_WORKITEM_UPLOAD_ROOT/../ in order for Azure Devops attachments to link properly and for Helix to store the logs
|
||||
File.Copy(file, Path.Combine(HELIX_WORKITEM_UPLOAD_ROOT, logName));
|
||||
File.Copy(file, Path.Combine(HELIX_WORKITEM_UPLOAD_ROOT, "..", logName));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("No logs found in artifacts/log");
|
||||
}
|
||||
|
||||
Console.WriteLine("Completed Helix job.");
|
||||
Environment.Exit(exitCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp5.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.20158.1" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -2,5 +2,6 @@
|
|||
<configuration>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
|
|
@ -3,13 +3,9 @@ REM Need delayed expansion !PATH! so parens in the path don't mess up the parens
|
|||
setlocal enabledelayedexpansion
|
||||
|
||||
REM Use '$' as a variable name prefix to avoid MSBuild variable collisions with these variables
|
||||
set $target=%1
|
||||
set $sdkVersion=%2
|
||||
set $runtimeVersion=%3
|
||||
set $helixQueue=%4
|
||||
set $arch=%5
|
||||
set $quarantined=%6
|
||||
set $efVersion=%7
|
||||
|
||||
set DOTNET_HOME=%HELIX_CORRELATION_PAYLOAD%\sdk
|
||||
set DOTNET_ROOT=%DOTNET_HOME%\%$arch%
|
||||
|
|
@ -24,89 +20,11 @@ powershell.exe -NoProfile -ExecutionPolicy unrestricted -Command "[Net.ServicePo
|
|||
echo "Installing Runtime"
|
||||
powershell.exe -NoProfile -ExecutionPolicy unrestricted -Command "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -useb 'https://dot.net/v1/dotnet-install.ps1'))) -Architecture %$arch% -Runtime dotnet -Version %$runtimeVersion% -InstallDir %DOTNET_ROOT%"
|
||||
|
||||
REM "Rename default.NuGet.config to NuGet.config if there is not a custom one from the project"
|
||||
if not EXIST ".\NuGet.config" (
|
||||
copy default.NuGet.config NuGet.config
|
||||
)
|
||||
|
||||
echo "Checking for Microsoft.AspNetCore.App"
|
||||
if EXIST ".\Microsoft.AspNetCore.App" (
|
||||
echo "Found Microsoft.AspNetCore.App, copying to %DOTNET_ROOT%\shared\Microsoft.AspNetCore.App\%runtimeVersion%"
|
||||
xcopy /i /y ".\Microsoft.AspNetCore.App" %DOTNET_ROOT%\shared\Microsoft.AspNetCore.App\%runtimeVersion%\
|
||||
|
||||
echo "Adding current directory to nuget sources: %HELIX_WORKITEM_ROOT%"
|
||||
dotnet nuget add source %HELIX_WORKITEM_ROOT% --configfile NuGet.config
|
||||
dotnet nuget add source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json --configfile NuGet.config
|
||||
dotnet nuget list source
|
||||
dotnet tool install dotnet-ef --global --version %$efVersion%
|
||||
|
||||
set PATH=!PATH!;%DOTNET_CLI_HOME%\.dotnet\tools
|
||||
)
|
||||
|
||||
echo "Current Directory: %HELIX_WORKITEM_ROOT%"
|
||||
set HELIX=%$helixQueue%
|
||||
set HELIX_DIR=%HELIX_WORKITEM_ROOT%
|
||||
set NUGET_FALLBACK_PACKAGES=%HELIX_DIR%
|
||||
set NUGET_RESTORE=%HELIX_DIR%\nugetRestore
|
||||
set DotNetEfFullPath=%HELIX_DIR%\nugetRestore\dotnet-ef\%$efVersion%\tools\netcoreapp3.1\any\dotnet-ef.exe
|
||||
echo "Set DotNetEfFullPath: %DotNetEfFullPath%"
|
||||
echo "Setting HELIX_DIR: %HELIX_DIR%"
|
||||
echo Creating nuget restore directory: %NUGET_RESTORE%
|
||||
mkdir %NUGET_RESTORE%
|
||||
mkdir logs
|
||||
|
||||
REM "Rename default.runner.json to xunit.runner.json if there is not a custom one from the project"
|
||||
if not EXIST ".\xunit.runner.json" (
|
||||
copy default.runner.json xunit.runner.json
|
||||
)
|
||||
|
||||
dir
|
||||
|
||||
%DOTNET_ROOT%\dotnet vstest %$target% -lt >discovered.txt
|
||||
find /c "Exception thrown" discovered.txt
|
||||
REM "ERRORLEVEL is not %ERRORLEVEL%" https://blogs.msdn.microsoft.com/oldnewthing/20080926-00/?p=20743/
|
||||
if not errorlevel 1 (
|
||||
echo Exception thrown during test discovery. 1>&2
|
||||
type discovered.txt 1>&2
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
set exit_code=0
|
||||
|
||||
if %$quarantined%==True (
|
||||
set %$quarantined=true
|
||||
)
|
||||
|
||||
REM Disable "!Foo!" expansions because they break the filter syntax
|
||||
setlocal disabledelayedexpansion
|
||||
set NONQUARANTINE_FILTER="Quarantined!=true"
|
||||
set QUARANTINE_FILTER="Quarantined=true"
|
||||
if %$quarantined%==true (
|
||||
echo Running quarantined tests.
|
||||
%DOTNET_ROOT%\dotnet vstest %$target% --logger:xunit --logger:"console;verbosity=normal" --blame --TestCaseFilter:%QUARANTINE_FILTER%
|
||||
if errorlevel 1 (
|
||||
echo Failure in quarantined test 1>&2
|
||||
REM DO NOT EXIT and DO NOT SET EXIT_CODE to 1
|
||||
)
|
||||
) else (
|
||||
REM Filter syntax: https://github.com/Microsoft/vstest-docs/blob/master/docs/filter.md
|
||||
echo Running non-quarantined tests.
|
||||
%DOTNET_ROOT%\dotnet vstest %$target% --logger:xunit --logger:"console;verbosity=normal" --blame --TestCaseFilter:%NONQUARANTINE_FILTER%
|
||||
if errorlevel 1 (
|
||||
echo Failure in non-quarantined test 1>&2
|
||||
set exit_code=1
|
||||
REM DO NOT EXIT
|
||||
)
|
||||
)
|
||||
|
||||
echo "Copying TestResults\TestResults.xml to ."
|
||||
copy TestResults\TestResults.xml testResults.xml
|
||||
echo "Copying artifacts/logs to %HELIX_WORKITEM_UPLOAD_ROOT%\..\"
|
||||
for /R artifacts/log %%f in (*.log) do (
|
||||
echo "Copying: %%f"
|
||||
copy "%%f" %HELIX_WORKITEM_UPLOAD_ROOT%\..\
|
||||
copy "%%f" %HELIX_WORKITEM_UPLOAD_ROOT%\
|
||||
dotnet restore RunTests\RunTests.csproj --source https://api.nuget.org/v3/index.json --ignore-failed-sources
|
||||
dotnet run --project RunTests\RunTests.csproj -- --target %1 --sdk %2 --runtime %3 --queue %4 --arch %5 --quarantined %6 --ef %7
|
||||
if errorlevel 1 (
|
||||
set exit_code=1
|
||||
)
|
||||
|
||||
exit /b %exit_code%
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
test_binary_path="$1"
|
||||
dotnet_sdk_version="$2"
|
||||
dotnet_runtime_version="$3"
|
||||
helix_queue_name="$4"
|
||||
target_arch="$5"
|
||||
quarantined="$6"
|
||||
efVersion="$7"
|
||||
|
||||
RESET="\033[0m"
|
||||
RED="\033[0;31m"
|
||||
|
|
@ -30,19 +25,6 @@ export DOTNET_CLI_HOME="$DIR/.home$RANDOM"
|
|||
|
||||
export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
|
||||
|
||||
# Used by SkipOnHelix attribute
|
||||
export helix="$helix_queue_name"
|
||||
export HELIX_DIR="$DIR"
|
||||
export NUGET_FALLBACK_PACKAGES="$DIR"
|
||||
export DotNetEfFullPath=$DIR\nugetRestore\dotnet-ef\$efVersion\tools\netcoreapp3.1\any\dotnet-ef.dll
|
||||
echo "Set DotNetEfFullPath: $DotNetEfFullPath"
|
||||
export NUGET_RESTORE="$DIR/nugetRestore"
|
||||
echo "Creating nugetRestore directory: $NUGET_RESTORE"
|
||||
mkdir $NUGET_RESTORE
|
||||
mkdir logs
|
||||
|
||||
ls -laR
|
||||
|
||||
RESET="\033[0m"
|
||||
RED="\033[0;31m"
|
||||
YELLOW="\033[0;33m"
|
||||
|
|
@ -93,35 +75,6 @@ if [ $? -ne 0 ]; then
|
|||
done
|
||||
fi
|
||||
|
||||
# Rename default.NuGet.config to NuGet.config if there is not a custom one from the project
|
||||
if [ ! -f "NuGet.config" ]
|
||||
then
|
||||
cp default.NuGet.config NuGet.config
|
||||
fi
|
||||
|
||||
# Copy over any local shared fx if found
|
||||
if [ -d "Microsoft.AspNetCore.App" ]
|
||||
then
|
||||
echo "Found Microsoft.AspNetCore.App directory, copying to $DOTNET_ROOT/shared/Microsoft.AspNetCore.App/$dotnet_runtime_version."
|
||||
cp -r Microsoft.AspNetCore.App $DOTNET_ROOT/shared/Microsoft.AspNetCore.App/$dotnet_runtime_version
|
||||
|
||||
echo "Adding current directory to nuget sources: $DIR"
|
||||
dotnet nuget add source $DIR --configfile NuGet.config
|
||||
dotnet nuget add source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json --configfile NuGet.config
|
||||
dotnet nuget list source
|
||||
|
||||
dotnet tool install dotnet-ef --global --version $efVersion
|
||||
|
||||
# Ensure tools are on on PATH
|
||||
export PATH="$PATH:$DOTNET_CLI_HOME/.dotnet/tools"
|
||||
fi
|
||||
|
||||
# Rename default.runner.json to xunit.runner.json if there is not a custom one from the project
|
||||
if [ ! -f "xunit.runner.json" ]
|
||||
then
|
||||
cp default.runner.json xunit.runner.json
|
||||
fi
|
||||
|
||||
if [ -e /proc/self/coredump_filter ]; then
|
||||
# Include memory in private and shared file-backed mappings in the dump.
|
||||
# This ensures that we can see disassembly from our shared libraries when
|
||||
|
|
@ -129,40 +82,11 @@ if [ -e /proc/self/coredump_filter ]; then
|
|||
echo -n 0x3F > /proc/self/coredump_filter
|
||||
fi
|
||||
|
||||
# dontet-install.sh seems to affect the Linux filesystem and causes test flakiness unless we sync the filesystem before running tests
|
||||
sync
|
||||
|
||||
$DOTNET_ROOT/dotnet vstest $test_binary_path -lt >discovered.txt
|
||||
if grep -q "Exception thrown" discovered.txt; then
|
||||
echo -e "${RED}Exception thrown during test discovery${RESET}".
|
||||
cat discovered.txt
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit_code=0
|
||||
$DOTNET_ROOT/dotnet restore RunTests/RunTests.csproj --source https://api.nuget.org/v3/index.json --ignore-failed-sources
|
||||
$DOTNET_ROOT/dotnet run --project RunTests/RunTests.csproj -- --target $1 --sdk $2 --runtime $3 --queue $4 --arch $5 --quarantined $6 --ef $7
|
||||
|
||||
# Filter syntax: https://github.com/Microsoft/vstest-docs/blob/master/docs/filter.md
|
||||
NONQUARANTINE_FILTER="Quarantined!=true"
|
||||
QUARANTINE_FILTER="Quarantined=true"
|
||||
if [ "$quarantined" == true ]; then
|
||||
echo "Running all tests including quarantined."
|
||||
$DOTNET_ROOT/dotnet vstest $test_binary_path --logger:xunit --logger:"console;verbosity=normal" --blame --TestCaseFilter:"$QUARANTINE_FILTER"
|
||||
if [ $? != 0 ]; then
|
||||
echo "Quarantined tests failed!" 1>&2
|
||||
# DO NOT EXIT
|
||||
fi
|
||||
else
|
||||
echo "Running non-quarantined tests."
|
||||
$DOTNET_ROOT/dotnet vstest $test_binary_path --logger:xunit --logger:"console;verbosity=normal" --blame --TestCaseFilter:"$NONQUARANTINE_FILTER"
|
||||
exit_code=$?
|
||||
if [ $exit_code != 0 ]; then
|
||||
echo "Non-quarantined tests failed!" 1>&2
|
||||
# DO NOT EXIT
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Copying TestResults/TestResults to ."
|
||||
cp TestResults/TestResults.xml testResults.xml
|
||||
echo "Copying artifacts/logs to $HELIX_WORKITEM_UPLOAD_ROOT/"
|
||||
cp `find . -name \*.log` $HELIX_WORKITEM_UPLOAD_ROOT/../
|
||||
cp `find . -name \*.log` $HELIX_WORKITEM_UPLOAD_ROOT/
|
||||
exit $exit_code
|
||||
exit $?
|
||||
|
|
|
|||
|
|
@ -27,11 +27,11 @@ namespace Templates.Test.Helpers
|
|||
public static bool IsCIEnvironment => typeof(Project).Assembly.GetCustomAttributes<AssemblyMetadataAttribute>()
|
||||
.Any(a => a.Key == "ContinuousIntegrationBuild");
|
||||
|
||||
public static string ArtifactsLogDir => (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("HELIX_DIR")))
|
||||
public static string ArtifactsLogDir => (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("HELIX_WORKITEM_UPLOAD_ROOT")))
|
||||
? GetAssemblyMetadata("ArtifactsLogDir")
|
||||
: Path.Combine(Environment.GetEnvironmentVariable("HELIX_DIR"), "logs");
|
||||
|
||||
public static string DotNetEfFullPath => (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DotNetEfFullPath")))
|
||||
: Environment.GetEnvironmentVariable("HELIX_WORKITEM_UPLOAD_ROOT");
|
||||
|
||||
public static string DotNetEfFullPath => (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DotNetEfFullPath")))
|
||||
? typeof(ProjectFactoryFixture).Assembly.GetCustomAttributes<AssemblyMetadataAttribute>()
|
||||
.First(attribute => attribute.Key == "DotNetEfFullPath")
|
||||
.Value
|
||||
|
|
@ -309,7 +309,7 @@ namespace Templates.Test.Helpers
|
|||
internal async Task<ProcessEx> RunDotNetEfCreateMigrationAsync(string migrationName)
|
||||
{
|
||||
var args = $"--verbose --no-build migrations add {migrationName}";
|
||||
|
||||
|
||||
// Only run one instance of 'dotnet new' at once, as a workaround for
|
||||
// https://github.com/aspnet/templating/issues/63
|
||||
await DotNetNewLock.WaitAsync();
|
||||
|
|
@ -324,7 +324,7 @@ namespace Templates.Test.Helpers
|
|||
{
|
||||
command = "dotnet-ef";
|
||||
}
|
||||
|
||||
|
||||
var result = ProcessEx.Run(Output, TemplateOutputDir, command, args);
|
||||
await result.Exited;
|
||||
return result;
|
||||
|
|
@ -353,7 +353,7 @@ namespace Templates.Test.Helpers
|
|||
{
|
||||
command = "dotnet-ef";
|
||||
}
|
||||
|
||||
|
||||
var result = ProcessEx.Run(Output, TemplateOutputDir, command, args);
|
||||
await result.Exited;
|
||||
return result;
|
||||
|
|
|
|||
Loading…
Reference in New Issue