From ec876591ca3102629400e2ec912c5a958516967e Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Thu, 6 Feb 2020 10:57:51 +0100 Subject: Run illink tests on CI (#937) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Set ILLink.Tasks.Tests to be test project * Unconditionally use arcade * Fix ILLink.Tasks test project - Renamed to ILLink.Tasks.IntegrationTests because it depends on the .nupkg and arcade schedules Test projects before Pack - Fixed path to nupgk in nuget config - Move override of Test target for NUnit project from root Directory.Build.targets. For some reason Condition doesn't work there so the target would always be overriden. - Disabled MusicStore tests They were already disabled in https://github.com/mono/linker/commit/04eb53822f98749bdf6ab47009ba7c269f504eae because of https://github.com/mono/linker/commit/04eb53822f98749bdf6ab47009ba7c269f504eae but looks like that got reverted somehow * Make arcade enabled builds the default and remove special illink_ configs Mono builds can be done with /p:MonoBuild=true * Remove .net framework targets from netcore build * Update ILLink.Tasks to netcore3.0 * Fix netcore condition * More netcore3.0 updates * Try to mimic weird arcade behaviour * Enable test results publishing in arcade * Remove DisableArcadeImport property and use temp folder for ILLink.Tasks test projects instead * Fix net471 build on Unix * Use a temp folder in the repo and write empty Directory.Build.props/targets instead This works better with arcade temp folder overrides. * Revert "Try to mimic weird arcade behaviour" This reverts commit 3923c5410bf2d17073373924dc53020c91fea346. * Force always downloading a local dotnet We need this for the ILLink.Tasks tests. Co-authored-by: Alexander Köplinger --- .../ILLink.Tasks.IntegrationTests/CommandRunner.cs | 191 ++++++++++++++++ .../HelloWorldTest.cs | 76 +++++++ .../ILLink.Tasks.IntegrationTests.csproj | 20 ++ .../IntegrationTestBase.cs | 217 +++++++++++++++++++ test/ILLink.Tasks.IntegrationTests/Loggers.cs | 36 +++ .../MusicStoreReflection.xml | 97 +++++++++ .../MusicStoreTest.cs | 236 ++++++++++++++++++++ test/ILLink.Tasks.IntegrationTests/TestContext.cs | 120 ++++++++++ test/ILLink.Tasks.IntegrationTests/WebApiTest.cs | 98 +++++++++ .../xunit.runner.json | 3 + test/ILLink.Tasks.Tests/CommandRunner.cs | 191 ---------------- test/ILLink.Tasks.Tests/HelloWorldTest.cs | 75 ------- test/ILLink.Tasks.Tests/ILLink.Tasks.Tests.csproj | 33 --- test/ILLink.Tasks.Tests/IntegrationTestBase.cs | 176 --------------- test/ILLink.Tasks.Tests/Loggers.cs | 36 --- test/ILLink.Tasks.Tests/MusicStoreReflection.xml | 97 --------- test/ILLink.Tasks.Tests/MusicStoreTest.cs | 241 --------------------- test/ILLink.Tasks.Tests/TestContext.cs | 119 ---------- test/ILLink.Tasks.Tests/WebApiTest.cs | 96 -------- test/ILLink.Tasks.Tests/nuget/NuGet.config | 11 - test/ILLink.Tasks.Tests/xunit.runner.json | 3 - .../Mono.Linker.Tests.Cases.Expectations.csproj | 6 +- .../Mono.Linker.Tests.Cases.csproj | 10 +- test/Mono.Linker.Tests/Mono.Linker.Tests.csproj | 38 ++-- test/Mono.Linker.Tests/TestCases/TestDatabase.cs | 17 +- .../TestCasesRunner/ILCompiler.cs | 7 +- 26 files changed, 1124 insertions(+), 1126 deletions(-) create mode 100644 test/ILLink.Tasks.IntegrationTests/CommandRunner.cs create mode 100644 test/ILLink.Tasks.IntegrationTests/HelloWorldTest.cs create mode 100644 test/ILLink.Tasks.IntegrationTests/ILLink.Tasks.IntegrationTests.csproj create mode 100644 test/ILLink.Tasks.IntegrationTests/IntegrationTestBase.cs create mode 100644 test/ILLink.Tasks.IntegrationTests/Loggers.cs create mode 100755 test/ILLink.Tasks.IntegrationTests/MusicStoreReflection.xml create mode 100644 test/ILLink.Tasks.IntegrationTests/MusicStoreTest.cs create mode 100644 test/ILLink.Tasks.IntegrationTests/TestContext.cs create mode 100644 test/ILLink.Tasks.IntegrationTests/WebApiTest.cs create mode 100644 test/ILLink.Tasks.IntegrationTests/xunit.runner.json delete mode 100644 test/ILLink.Tasks.Tests/CommandRunner.cs delete mode 100644 test/ILLink.Tasks.Tests/HelloWorldTest.cs delete mode 100644 test/ILLink.Tasks.Tests/ILLink.Tasks.Tests.csproj delete mode 100644 test/ILLink.Tasks.Tests/IntegrationTestBase.cs delete mode 100644 test/ILLink.Tasks.Tests/Loggers.cs delete mode 100755 test/ILLink.Tasks.Tests/MusicStoreReflection.xml delete mode 100644 test/ILLink.Tasks.Tests/MusicStoreTest.cs delete mode 100644 test/ILLink.Tasks.Tests/TestContext.cs delete mode 100644 test/ILLink.Tasks.Tests/WebApiTest.cs delete mode 100644 test/ILLink.Tasks.Tests/nuget/NuGet.config delete mode 100644 test/ILLink.Tasks.Tests/xunit.runner.json (limited to 'test') diff --git a/test/ILLink.Tasks.IntegrationTests/CommandRunner.cs b/test/ILLink.Tasks.IntegrationTests/CommandRunner.cs new file mode 100644 index 000000000..bc790c09a --- /dev/null +++ b/test/ILLink.Tasks.IntegrationTests/CommandRunner.cs @@ -0,0 +1,191 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Text; +using Xunit; +using Xunit.Abstractions; + +namespace ILLink.Tests +{ + + public class CommandHelper + { + private ILogger logger; + + public CommandHelper(ILogger logger) + { + this.logger = logger; + } + + public int Dotnet(string args, string workingDir, string additionalPath = null) + { + return RunCommand(Path.GetFullPath(TestContext.DotnetToolPath), args, + workingDir, additionalPath, out string commandOutput); + } + + public int RunCommand(string command, string args, int timeout = Int32.MaxValue) + { + return RunCommand(command, args, null, null, out string commandOutput, timeout); + } + + public int RunCommand(string command, string args, string workingDir) + { + return RunCommand(command, args, workingDir, null, out string commandOutput); + } + + public int RunCommand(string command, string args, string workingDir, string additionalPath, + out string commandOutput, int timeout = Int32.MaxValue, string terminatingOutput = null) + { + return (new CommandRunner(command, logger)) + .WithArguments(args) + .WithWorkingDir(workingDir) + .WithAdditionalPath(additionalPath) + .WithTimeout(timeout) + .WithTerminatingOutput(terminatingOutput) + .Run(out commandOutput); + } + } + + public class CommandRunner + { + private readonly ILogger logger; + + private string command; + private string args; + private string workingDir; + private string additionalPath; + private int timeout = Int32.MaxValue; + private string terminatingOutput; + + private void LogMessage (string message) + { + logger.LogMessage (message); + } + + public CommandRunner(string command, ILogger logger) { + this.command = command; + this.logger = logger; + } + + public CommandRunner WithArguments(string args) { + this.args = args; + return this; + } + + public CommandRunner WithWorkingDir(string workingDir) { + this.workingDir = workingDir; + return this; + } + + public CommandRunner WithAdditionalPath(string additionalPath) { + this.additionalPath = additionalPath; + return this; + } + + public CommandRunner WithTimeout(int timeout) { + this.timeout = timeout; + return this; + } + + public CommandRunner WithTerminatingOutput(string terminatingOutput) { + this.terminatingOutput = terminatingOutput; + return this; + } + + public int Run() + { + return Run(out string commandOutputUnused); + } + + public int Run(out string commandOutput) + { + if (String.IsNullOrEmpty(command)) { + throw new Exception("No command was specified specified."); + } + if (logger == null) { + throw new Exception("No logger present."); + } + var psi = new ProcessStartInfo + { + FileName = command, + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + }; + LogMessage ($"caller working directory: {Environment.CurrentDirectory}"); + if (!String.IsNullOrEmpty(args)) { + psi.Arguments = args; + LogMessage ($"{command} {args}"); + } else { + LogMessage ($"{command}"); + } + if (!String.IsNullOrEmpty(workingDir)) { + LogMessage ($"working directory: {workingDir}"); + psi.WorkingDirectory = workingDir; + } + if (!String.IsNullOrEmpty(additionalPath)) { + string path = psi.Environment["PATH"]; + psi.Environment["PATH"] = path + ";" + additionalPath; + } + var process = new Process(); + process.StartInfo = psi; + + // dotnet sets some environment variables that + // may cause problems in the child process. + psi.Environment.Remove("MSBuildExtensionsPath"); + psi.Environment.Remove("MSBuildLoadMicrosoftTargetsReadOnly"); + psi.Environment.Remove("MSBuildSDKsPath"); + psi.Environment.Remove("VbcToolExe"); + psi.Environment.Remove("CscToolExe"); + psi.Environment.Remove("MSBUILD_EXE_PATH"); + + LogMessage ("environment:"); + foreach (var item in psi.Environment) { + LogMessage ($"\t{item.Key}={item.Value}"); + } + + StringBuilder processOutput = new StringBuilder(); + DataReceivedEventHandler handler = (sender, e) => { + processOutput.Append(e.Data); + processOutput.AppendLine(); + }; + StringBuilder processError = new StringBuilder(); + DataReceivedEventHandler ehandler = (sender, e) => { + processError.Append(e.Data); + processError.AppendLine(); + }; + process.OutputDataReceived += handler; + process.ErrorDataReceived += ehandler; + + // terminate process if output contains specified string + if (!String.IsNullOrEmpty(terminatingOutput)) { + DataReceivedEventHandler terminatingOutputHandler = (sender, e) => { + if (!String.IsNullOrEmpty(e.Data) && e.Data.Contains(terminatingOutput)) { + process.Kill(); + } + }; + process.OutputDataReceived += terminatingOutputHandler; + } + + // start the process + process.Start(); + process.BeginOutputReadLine(); + process.BeginErrorReadLine(); + if (!process.WaitForExit(timeout)) { + LogMessage ($"killing process after {timeout} ms"); + process.Kill(); + } + // WaitForExit with timeout doesn't guarantee + // that the async output handlers have been + // called, so WaitForExit needs to be called + // afterwards. + process.WaitForExit(); + string processOutputStr = processOutput.ToString(); + string processErrorStr = processError.ToString(); + LogMessage(processOutputStr); + LogMessage(processErrorStr); + commandOutput = processOutputStr; + return process.ExitCode; + } + } +} diff --git a/test/ILLink.Tasks.IntegrationTests/HelloWorldTest.cs b/test/ILLink.Tasks.IntegrationTests/HelloWorldTest.cs new file mode 100644 index 000000000..63b0990c9 --- /dev/null +++ b/test/ILLink.Tasks.IntegrationTests/HelloWorldTest.cs @@ -0,0 +1,76 @@ +using System; +using System.IO; +using Xunit; +using Xunit.Abstractions; +using Xunit.Sdk; + +namespace ILLink.Tests +{ + public class HelloWorldFixture : ProjectFixture + { + public string csproj; + + public HelloWorldFixture (IMessageSink diagnosticMessageSink) : base (diagnosticMessageSink) + { + csproj = SetupProject (); + } + + public string SetupProject() + { + string projectRoot = CreateTestFolder("helloworld"); + string csproj = Path.Combine(projectRoot, $"helloworld.csproj"); + + if (File.Exists(csproj)) { + LogMessage ($"using existing project {csproj}"); + return csproj; + } + + if (Directory.Exists(projectRoot)) { + Directory.Delete(projectRoot, true); + } + + Directory.CreateDirectory(projectRoot); + int ret = CommandHelper.Dotnet("new console", projectRoot); + if (ret != 0) { + LogMessage ("dotnet new failed"); + Assert.True(false); + } + + AddLinkerReference(csproj); + + AddNuGetConfig(projectRoot); + + return csproj; + } + } + + public class HelloWorldTest : IntegrationTestBase, IClassFixture + { + HelloWorldFixture fixture; + + public HelloWorldTest(HelloWorldFixture fixture, ITestOutputHelper helper) : base(helper) { + this.fixture = fixture; + } + + [Fact] + public void RunHelloWorldStandalone() + { + string executablePath = BuildAndLink(fixture.csproj, selfContained: true); + CheckOutput(executablePath, selfContained: true); + } + + [Fact] + public void RunHelloWorldPortable() + { + string target = BuildAndLink(fixture.csproj, selfContained: false); + CheckOutput(target, selfContained: false); + } + + void CheckOutput(string target, bool selfContained = false) + { + int ret = RunApp(target, out string commandOutput, selfContained: selfContained); + Assert.True(ret == 0); + Assert.Contains("Hello World!", commandOutput); + } + } +} diff --git a/test/ILLink.Tasks.IntegrationTests/ILLink.Tasks.IntegrationTests.csproj b/test/ILLink.Tasks.IntegrationTests/ILLink.Tasks.IntegrationTests.csproj new file mode 100644 index 000000000..81a44f503 --- /dev/null +++ b/test/ILLink.Tasks.IntegrationTests/ILLink.Tasks.IntegrationTests.csproj @@ -0,0 +1,20 @@ + + + + netcoreapp3.0 + + + + + + + + + + + + + + + + diff --git a/test/ILLink.Tasks.IntegrationTests/IntegrationTestBase.cs b/test/ILLink.Tasks.IntegrationTests/IntegrationTestBase.cs new file mode 100644 index 000000000..d65990895 --- /dev/null +++ b/test/ILLink.Tasks.IntegrationTests/IntegrationTestBase.cs @@ -0,0 +1,217 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Xml.Linq; +using Xunit; +using Xunit.Abstractions; + +namespace ILLink.Tests +{ + + /// + /// Represents a project. Each fixture contains setup code run + /// once before all tests in the same test class. ProjectFixture + /// is the base type for different specific project fixtures. + /// + public class ProjectFixture + { + private FixtureLogger logger; + protected CommandHelper CommandHelper; + + protected void LogMessage (string message) + { + logger.LogMessage (message); + } + + public ProjectFixture (IMessageSink diagnosticMessageSink) + { + logger = new FixtureLogger (diagnosticMessageSink); + CommandHelper = new CommandHelper (logger); + } + + protected void AddNuGetConfig(string projectRoot) + { + var nugetConfig = Path.Combine(projectRoot, "NuGet.config"); + var xdoc = new XDocument(); + var configuration = new XElement("configuration"); + var packageSources = new XElement("packageSources"); + packageSources.Add(new XElement("add", + new XAttribute("key", "dotnet-core"), + new XAttribute("value", "https://dotnet.myget.org/F/dotnet-core/api/v3/index.json"))); + packageSources.Add(new XElement("add", + new XAttribute("key", "local linker feed"), + new XAttribute("value", TestContext.PackageSource))); + + configuration.Add(packageSources); + xdoc.Add(configuration); + + using (var fs = new FileStream(nugetConfig, FileMode.Create)) { + xdoc.Save(fs); + } + } + + protected void AddLinkerReference(string csproj) + { + var xdoc = XDocument.Load(csproj); + var ns = xdoc.Root.GetDefaultNamespace(); + bool added = false; + foreach (var el in xdoc.Root.Elements(ns + "ItemGroup")) { + if (el.Elements(ns + "PackageReference").Any()) { + el.Add(new XElement(ns+"PackageReference", + new XAttribute("Include", TestContext.TasksPackageName), + new XAttribute("Version", TestContext.TasksPackageVersion))); + added = true; + break; + } + } + if (!added) { + xdoc.Root.Add(new XElement(ns + "ItemGroup", + new XElement(ns + "PackageReference", + new XAttribute("Include", TestContext.TasksPackageName), + new XAttribute("Version", TestContext.TasksPackageVersion)))); + added= true; + } + + using (var fs = new FileStream(csproj, FileMode.Create)) { + xdoc.Save(fs); + } + } + + protected string CreateTestFolder(string projectName) + { + string tempFolder = Path.GetFullPath(Path.Combine("tests-temp", projectName)); + Directory.CreateDirectory(tempFolder); + + // write empty Directory.Build.props and Directory.Build.targets to disable accidental import of arcade from repo root + File.WriteAllText(Path.Combine(tempFolder, "Directory.Build.props"), ""); + File.WriteAllText(Path.Combine(tempFolder, "Directory.Build.targets"), ""); + + return Path.Combine(tempFolder, projectName); + } + + protected void WriteEmbeddedResource(string resourceName, string destination) + { + var assembly = Assembly.GetExecutingAssembly(); + var resourceStream = assembly.GetManifestResourceStream(resourceName); + resourceStream.CopyTo(File.Create(destination)); + } + + static void AddLinkerRoots(string csproj, List rootFiles) + { + var xdoc = XDocument.Load(csproj); + var ns = xdoc.Root.GetDefaultNamespace(); + + var rootsItemGroup = new XElement(ns+"ItemGroup"); + foreach (var rootFile in rootFiles) { + rootsItemGroup.Add(new XElement(ns+"LinkerRootFiles", + new XAttribute("Include", rootFile))); + } + + var propertyGroup = xdoc.Root.Elements(ns + "PropertyGroup").First(); + propertyGroup.AddAfterSelf(rootsItemGroup); + + using (var fs = new FileStream(csproj, FileMode.Create)) { + xdoc.Save(fs); + } + } + + } + + /// + /// Contains logic shared by multiple test classes. + /// + public class IntegrationTestBase + { + private readonly TestLogger logger; + protected readonly CommandHelper CommandHelper; + + public IntegrationTestBase(ITestOutputHelper output) + { + logger = new TestLogger(output); + CommandHelper = new CommandHelper(logger); + } + + private void LogMessage (string message) + { + logger.LogMessage (message); + } + + /// + /// Run the linker on the specified project. This assumes + /// that the project already contains a reference to the + /// linker task package. + /// Optionally takes a list of root descriptor files. + /// Returns the path to the built app, either the renamed + /// host for self-contained publish, or the dll containing + /// the entry point. + /// + public string BuildAndLink(string csproj, List rootFiles = null, Dictionary extraPublishArgs = null, bool selfContained = false) + { + string demoRoot = Path.GetDirectoryName(csproj); + + string publishArgs = $"publish -c {TestContext.Configuration} /v:n /p:ShowLinkerSizeComparison=true"; + if (selfContained) { + publishArgs += $" -r {TestContext.RuntimeIdentifier}"; + } + string rootFilesStr; + if (rootFiles != null && rootFiles.Any()) { + rootFilesStr = String.Join(";", rootFiles); + publishArgs += $" /p:LinkerRootDescriptors={rootFilesStr}"; + } + if (extraPublishArgs != null) { + foreach (var item in extraPublishArgs) { + publishArgs += $" /p:{item.Key}={item.Value}"; + } + } + int ret = CommandHelper.Dotnet(publishArgs, demoRoot); + + if (ret != 0) { + LogMessage("publish failed, returning " + ret); + Assert.True(false); + } + + // detect the target framework for which the app was published + string tfmDir = Path.Combine(demoRoot, "bin", TestContext.Configuration); + string tfm = Directory.GetDirectories(tfmDir).Select(p => Path.GetFileName(p)).Single(); + string builtApp = Path.Combine(tfmDir, tfm); + if (selfContained) { + builtApp = Path.Combine(builtApp, TestContext.RuntimeIdentifier); + } + builtApp = Path.Combine(builtApp, "publish", + Path.GetFileNameWithoutExtension(csproj)); + if (selfContained) { + if (TestContext.RuntimeIdentifier.Contains("win")) { + builtApp += ".exe"; + } + } else { + builtApp += ".dll"; + } + Assert.True(File.Exists(builtApp)); + return builtApp; + } + + public int RunApp(string target, out string processOutput, int timeout = Int32.MaxValue, + string terminatingOutput = null, bool selfContained = false) + { + Assert.True(File.Exists(target)); + int ret; + if (selfContained) { + ret = CommandHelper.RunCommand( + target, null, + Directory.GetParent(target).FullName, + null, out processOutput, timeout, terminatingOutput); + } else { + ret = CommandHelper.RunCommand( + Path.GetFullPath(TestContext.DotnetToolPath), + Path.GetFullPath(target), + Directory.GetParent(target).FullName, + null, out processOutput, timeout, terminatingOutput); + } + return ret; + } + } +} diff --git a/test/ILLink.Tasks.IntegrationTests/Loggers.cs b/test/ILLink.Tasks.IntegrationTests/Loggers.cs new file mode 100644 index 000000000..083cb2769 --- /dev/null +++ b/test/ILLink.Tasks.IntegrationTests/Loggers.cs @@ -0,0 +1,36 @@ +using Xunit.Abstractions; +using Xunit.Sdk; + +namespace ILLink.Tests +{ + public interface ILogger + { + void LogMessage (string message); + } + + public class TestLogger : ILogger + { + private ITestOutputHelper output; + public TestLogger (ITestOutputHelper output) + { + this.output = output; + } + public void LogMessage (string message) + { + output.WriteLine (message); + } + } + + public class FixtureLogger : ILogger + { + private IMessageSink messageSink; + public FixtureLogger (IMessageSink messageSink) + { + this.messageSink = messageSink; + } + public void LogMessage (string message) + { + messageSink.OnMessage (new DiagnosticMessage (message)); + } + } +} \ No newline at end of file diff --git a/test/ILLink.Tasks.IntegrationTests/MusicStoreReflection.xml b/test/ILLink.Tasks.IntegrationTests/MusicStoreReflection.xml new file mode 100755 index 000000000..e35f91155 --- /dev/null +++ b/test/ILLink.Tasks.IntegrationTests/MusicStoreReflection.xml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/ILLink.Tasks.IntegrationTests/MusicStoreTest.cs b/test/ILLink.Tasks.IntegrationTests/MusicStoreTest.cs new file mode 100644 index 000000000..cbb78b62b --- /dev/null +++ b/test/ILLink.Tasks.IntegrationTests/MusicStoreTest.cs @@ -0,0 +1,236 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; +using Xunit; +using Xunit.Abstractions; // ITestOutputHelper + +namespace ILLink.Tests +{ + public class MusicStoreFixture : ProjectFixture + { + public static List rootFiles = new List { "MusicStoreReflection.xml" }; + + private static string gitRepo = "http://github.com/aspnet/JitBench"; + + // Revision can also be a branch name. We generally + // want to ensure that we are able to link the latest + // MusicStore from the dev branch. + private static string gitRevision = "ac314bd68294ae0f91bd16df20cf5ebd4b8ef5b5"; + + // The version of Microsoft.NETCore.App that + // musicstore will run on (and deploy with, for + // self-contained deployments). + private static string runtimeVersion = "3.0.0-preview-27324-5"; + + // The version of the SDK used to build and link + // musicstore, if a specific version is desired. + private static string sdkVersion = "2.2.0-preview1-007525"; + + // The version of Microsoft.AspNetCore.All to publish with. + private static string aspNetVersion = "2.1.0-preview1-27654"; + + public static Dictionary versionPublishArgs; + public static Dictionary VersionPublishArgs + { + get { + if (versionPublishArgs != null) { + return versionPublishArgs; + } + versionPublishArgs = new Dictionary(); + versionPublishArgs.Add("JITBENCH_FRAMEWORK_VERSION", runtimeVersion); + versionPublishArgs.Add("JITBENCH_ASPNET_VERSION", aspNetVersion); + return versionPublishArgs; + } + } + + public static string csproj; + + public MusicStoreFixture(IMessageSink diagnosticMessageSink) : base(diagnosticMessageSink) + { + csproj = SetupProject(); + } + + // returns path to .csproj project file + string SetupProject() + { + int ret; + string repoName = CreateTestFolder("MusicStore"); + string demoRoot = Path.Combine(repoName, Path.Combine("src", "MusicStore")); + string csproj = Path.Combine(demoRoot, "MusicStore.csproj"); + + if (File.Exists(csproj)) { + LogMessage($"using existing project {csproj}"); + return csproj; + } + + if (Directory.Exists(repoName)) { + Directory.Delete(repoName, true); + } + + ret = CommandHelper.RunCommand("git", $"clone {gitRepo} {repoName}"); + if (ret != 0) { + LogMessage("git failed"); + Assert.True(false); + } + + if (!Directory.Exists(demoRoot)) { + LogMessage($"{demoRoot} does not exist"); + Assert.True(false); + } + + ret = CommandHelper.RunCommand("git", $"checkout {gitRevision}", demoRoot); + if (ret != 0) { + LogMessage($"problem checking out revision {gitRevision}"); + Assert.True(false); + } + + // Write root files into the project directory + foreach (var rf in rootFiles) { + WriteEmbeddedResource(rf, Path.Combine(demoRoot, rf)); + } + + // This is necessary because JitBench comes with a + // NuGet.Config that has a line, preventing + // NuGet.Config sources defined in outer directories from + // applying. + string nugetConfig = Path.Combine(repoName, "NuGet.config"); + AddLocalNugetFeedAfterClear(nugetConfig); + + AddLinkerReference(csproj); + + // We no longer need a custom global.json, because we are + // using the same SDK used in the repo. + // AddGlobalJson(repoName); + + return csproj; + } + + void AddGlobalJson(string repoDir) + { + string globalJson = Path.Combine(repoDir, "global.json"); + string globalJsonContents = "{ \"sdk\": { \"version\": \"" + sdkVersion + "\" } }\n"; + File.WriteAllText(globalJson, globalJsonContents); + } + + string GetDotnetToolPath(string dotnetDir) + { + string dotnetToolName = Directory.GetFiles(dotnetDir) + .Select(p => Path.GetFileName(p)) + .Where(p => p.Contains("dotnet")) + .Single(); + string dotnetToolPath = Path.Combine(dotnetDir, dotnetToolName); + + if (!File.Exists(dotnetToolPath)) { + LogMessage("repo-local dotnet tool does not exist."); + Assert.True(false); + } + + return dotnetToolPath; + } + + string ObtainSDK(string rootDir, string repoDir) + { + int ret; + string dotnetDirName = ".dotnet"; + string dotnetDir = Path.Combine(rootDir, dotnetDirName); + if (Directory.Exists(dotnetDir)) { + return GetDotnetToolPath(dotnetDir); + } + + string dotnetInstall = Path.Combine(Path.GetFullPath(repoDir), "dotnet-install"); + if (TestContext.RuntimeIdentifier.Contains("win")) { + dotnetInstall += ".ps1"; + } else { + dotnetInstall += ".sh"; + } + if (!File.Exists(dotnetInstall)) { + LogMessage($"missing dotnet-install script at {dotnetInstall}"); + Assert.True(false); + } + + if (TestContext.RuntimeIdentifier.Contains("win")) { + ret = CommandHelper.RunCommand("powershell", $"{dotnetInstall} -SharedRuntime -InstallDir {dotnetDirName} -Channel master -Architecture x64 -Version {runtimeVersion}", rootDir); + if (ret != 0) { + LogMessage("failed to retrieve shared runtime"); + Assert.True(false); + } + ret = CommandHelper.RunCommand("powershell", $"{dotnetInstall} -InstallDir {dotnetDirName} -Channel master -Architecture x64 -Version {sdkVersion}", rootDir); + if (ret != 0) { + LogMessage("failed to retrieve sdk"); + Assert.True(false); + } + } else { + ret = CommandHelper.RunCommand(dotnetInstall, $"-sharedruntime -runtimeid {TestContext.RuntimeIdentifier} -installdir {dotnetDirName} -channel master -architecture x64 -version {runtimeVersion}", rootDir); + if (ret != 0) { + LogMessage("failed to retrieve shared runtime"); + Assert.True(false); + } + ret = CommandHelper.RunCommand(dotnetInstall, $"-installdir {dotnetDirName} -channel master -architecture x64 -version {sdkVersion}", rootDir); + if (ret != 0) { + LogMessage("failed to retrieve sdk"); + Assert.True(false); + } + } + + return GetDotnetToolPath(dotnetDir); + } + + private void AddLocalNugetFeedAfterClear(string nugetConfig) + { + string localPackagePath = Path.GetFullPath(TestContext.PackageSource); + var xdoc = XDocument.Load(nugetConfig); + var ns = xdoc.Root.GetDefaultNamespace(); + var clear = xdoc.Root.Element(ns+"packageSources").Element(ns+"clear"); + clear.Parent.Add(new XElement(ns+"add", + new XAttribute("key", "local linker feed"), + new XAttribute("value", localPackagePath))); + + using (var fs = new FileStream(nugetConfig, FileMode.Create)) { + xdoc.Save(fs); + } + } + } + + public class MusicStoreTest : IntegrationTestBase, IClassFixture + { + + MusicStoreFixture fixture; + + public MusicStoreTest(MusicStoreFixture fixture, ITestOutputHelper output) : base(output) { + this.fixture = fixture; + // MusicStore has been updated to target netcoreapp3.0, so + // we should be able to run on the SDK used to build this + // repo. + // context.DotnetToolPath = ObtainSDK(context.TestBin, repoName); + } + + //[Fact] // https://github.com/aspnet/JitBench/issues/96 + public void RunMusicStoreStandalone() + { + string executablePath = BuildAndLink(MusicStoreFixture.csproj, MusicStoreFixture.rootFiles, MusicStoreFixture.VersionPublishArgs, selfContained: true); + CheckOutput(executablePath, selfContained: true); + } + + //[Fact] // https://github.com/aspnet/JitBench/issues/96 + public void RunMusicStorePortable() + { + Dictionary extraPublishArgs = new Dictionary(MusicStoreFixture.VersionPublishArgs); + extraPublishArgs.Add("PublishWithAspNetCoreTargetManifest", "false"); + string target = BuildAndLink(MusicStoreFixture.csproj, null, extraPublishArgs, selfContained: false); + CheckOutput(target, selfContained: false); + } + + void CheckOutput(string target, bool selfContained = false) + { + int ret = RunApp(target, out string commandOutput, selfContained: selfContained); + + Assert.Contains("starting request to http://localhost:5000", commandOutput); + Assert.Contains("Response: OK", commandOutput); + Assert.Contains("Running 100 requests", commandOutput); + Assert.True(ret == 0); + } + + } +} diff --git a/test/ILLink.Tasks.IntegrationTests/TestContext.cs b/test/ILLink.Tasks.IntegrationTests/TestContext.cs new file mode 100644 index 000000000..d8f7f0b6d --- /dev/null +++ b/test/ILLink.Tasks.IntegrationTests/TestContext.cs @@ -0,0 +1,120 @@ +using System; +using System.IO; +using System.Linq; +using Microsoft.DotNet.PlatformAbstractions; + +namespace ILLink.Tests +{ + public static class TestContext + { + /// + /// The name of the tasks package to add to the integration + /// projects. + /// + public static string TasksPackageName { get; private set; } + + /// + /// The version of the tasks package to add to the + /// integration projects. + /// + public static string TasksPackageVersion { get; private set; } + + /// + /// The path of the directory from which to get the linker + /// package. + /// + public static string PackageSource { get; private set; } + + /// + /// The path to the dotnet tool to use to run the + /// integration tests. + /// + public static string DotnetToolPath { get; set; } + + /// + /// The RID to use when restoring, building, and linking the + /// integration test projects. + /// + public static string RuntimeIdentifier { get; private set; } + + /// + /// The configuration to use to build the integration test + /// projects. + /// + public static string Configuration { get; private set; } + + /// + /// The root testbin directory. Used to install test + /// assets that don't depend on the configuration or + /// target framework. + /// + public static string TestBin { get; private set; } + + static TestContext() + { + SetupDefaultContext(); + } + + /// + /// This is the context from which tests will be run in the + /// linker repo. The local directory that contains the + /// linker integration packages (hard-coded here) is + /// searched for the tasks package. This assumes that only + /// one version of the package is present, and uses it to + /// unambiguously determine which package to use in the tests. + /// + public static void SetupDefaultContext() + { + // test working directory is test project's // + var testBin = Path.Combine(Environment.CurrentDirectory, "..", ".."); + var repoRoot = Path.GetFullPath(Path.Combine(testBin, "..", "..", "..")); + + // We want to build and link integration projects in the + // release configuration. + Configuration = "Release"; + TestBin = testBin; + + // Locate task package + var packageName = "ILLink.Tasks"; + var packageSource = Path.Combine(repoRoot, "artifacts", "packages", Configuration, "Shipping"); + var tasksPackages = Directory.GetFiles(packageSource) + .Where(p => Path.GetExtension(p) == ".nupkg") + .Select(p => Path.GetFileNameWithoutExtension(p)) + .Where(p => p.StartsWith(packageName)); + var nPackages = tasksPackages.Count(); + if (nPackages > 1) { + throw new Exception($"duplicate {packageName} packages in {packageSource}"); + } else if (nPackages == 0) { + throw new Exception($"{packageName} package not found in {packageSource}"); + } + var tasksPackage = tasksPackages.Single(); + var version = tasksPackage.Remove(0, packageName.Length + 1); + + // Locate dotnet host + var dotnetDir = Path.Combine(repoRoot, ".dotnet"); + var dotnetToolName = Directory.GetFiles(dotnetDir) + .Select(p => Path.GetFileName(p)) + .Where(p => p.StartsWith("dotnet")) + .Where(p => { + var ext = Path.GetExtension(p); + return ext == "" || ext == ".exe"; + }) + .Single(); + var dotnetToolPath = Path.Combine(dotnetDir, dotnetToolName); + + // Initialize static members + PackageSource = packageSource; + TasksPackageName = packageName; + TasksPackageVersion = version; + DotnetToolPath = dotnetToolPath; + // This sets the RID to the RID of the currently-executing system. + RuntimeIdentifier = RuntimeEnvironment.GetRuntimeIdentifier(); + // workaround: the osx.10.13-x64 RID doesn't exist yet. + // see https://github.com/NuGet/Home/issues/5862 + if (RuntimeIdentifier == "osx.10.14-x64") + { + RuntimeIdentifier = "osx.10.13-x64"; + } + } + } +} diff --git a/test/ILLink.Tasks.IntegrationTests/WebApiTest.cs b/test/ILLink.Tasks.IntegrationTests/WebApiTest.cs new file mode 100644 index 000000000..334468167 --- /dev/null +++ b/test/ILLink.Tasks.IntegrationTests/WebApiTest.cs @@ -0,0 +1,98 @@ +using System; +using System.IO; +using System.Xml.Linq; +using Xunit; +using Xunit.Abstractions; + +namespace ILLink.Tests +{ + public class WebApiFixture : ProjectFixture + { + public string csproj; + + public WebApiFixture(IMessageSink diagnosticMessageSink) : base(diagnosticMessageSink) { + csproj = SetupProject(); + } + + public string SetupProject() + { + string projectRoot = CreateTestFolder("webapi"); + string csproj = Path.Combine(projectRoot, $"webapi.csproj"); + + if (File.Exists(csproj)) { + LogMessage($"using existing project {csproj}"); + return csproj; + } + + if (Directory.Exists(projectRoot)) { + Directory.Delete(projectRoot, true); + } + + Directory.CreateDirectory(projectRoot); + int ret = CommandHelper.Dotnet("new webapi", projectRoot); + if (ret != 0) { + LogMessage("dotnet new failed"); + Assert.True(false); + } + + PreventPublishFiltering(csproj); + + AddLinkerReference(csproj); + + AddNuGetConfig(projectRoot); + + return csproj; + } + + // TODO: Remove this once we figure out what to do about apps + // that have the publish output filtered by a manifest + // file. It looks like aspnet has made this the default. See + // the bug at https://github.com/dotnet/sdk/issues/1160. + private void PreventPublishFiltering(string csproj) { + var xdoc = XDocument.Load(csproj); + var ns = xdoc.Root.GetDefaultNamespace(); + + var propertygroup = xdoc.Root.Element(ns + "PropertyGroup"); + + LogMessage("setting PublishWithAspNetCoreTargetManifest=false"); + propertygroup.Add(new XElement(ns + "PublishWithAspNetCoreTargetManifest", + "false")); + + using (var fs = new FileStream(csproj, FileMode.Create)) { + xdoc.Save(fs); + } + } + } + + public class WebApiTest : IntegrationTestBase, IClassFixture + { + private WebApiFixture fixture; + + public WebApiTest(WebApiFixture fixture, ITestOutputHelper output) : base(output) + { + this.fixture = fixture; + } + + [Fact] + public void RunWebApiStandalone() + { + string executablePath = BuildAndLink(fixture.csproj, selfContained: true); + CheckOutput(executablePath, selfContained: true); + } + + [Fact] + public void RunWebApiPortable() + { + string target = BuildAndLink(fixture.csproj, selfContained: false); + CheckOutput(target, selfContained: false); + } + + void CheckOutput(string target, bool selfContained = false) + { + string terminatingOutput = "Application started. Press Ctrl+C to shut down."; + int ret = RunApp(target, out string commandOutput, 60000, terminatingOutput, selfContained: selfContained); + Assert.Contains("Now listening on: http://localhost:5000", commandOutput); + Assert.Contains(terminatingOutput, commandOutput); + } + } +} diff --git a/test/ILLink.Tasks.IntegrationTests/xunit.runner.json b/test/ILLink.Tasks.IntegrationTests/xunit.runner.json new file mode 100644 index 000000000..40be06652 --- /dev/null +++ b/test/ILLink.Tasks.IntegrationTests/xunit.runner.json @@ -0,0 +1,3 @@ +{ + "diagnosticMessages": true +} \ No newline at end of file diff --git a/test/ILLink.Tasks.Tests/CommandRunner.cs b/test/ILLink.Tasks.Tests/CommandRunner.cs deleted file mode 100644 index bc790c09a..000000000 --- a/test/ILLink.Tasks.Tests/CommandRunner.cs +++ /dev/null @@ -1,191 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Text; -using Xunit; -using Xunit.Abstractions; - -namespace ILLink.Tests -{ - - public class CommandHelper - { - private ILogger logger; - - public CommandHelper(ILogger logger) - { - this.logger = logger; - } - - public int Dotnet(string args, string workingDir, string additionalPath = null) - { - return RunCommand(Path.GetFullPath(TestContext.DotnetToolPath), args, - workingDir, additionalPath, out string commandOutput); - } - - public int RunCommand(string command, string args, int timeout = Int32.MaxValue) - { - return RunCommand(command, args, null, null, out string commandOutput, timeout); - } - - public int RunCommand(string command, string args, string workingDir) - { - return RunCommand(command, args, workingDir, null, out string commandOutput); - } - - public int RunCommand(string command, string args, string workingDir, string additionalPath, - out string commandOutput, int timeout = Int32.MaxValue, string terminatingOutput = null) - { - return (new CommandRunner(command, logger)) - .WithArguments(args) - .WithWorkingDir(workingDir) - .WithAdditionalPath(additionalPath) - .WithTimeout(timeout) - .WithTerminatingOutput(terminatingOutput) - .Run(out commandOutput); - } - } - - public class CommandRunner - { - private readonly ILogger logger; - - private string command; - private string args; - private string workingDir; - private string additionalPath; - private int timeout = Int32.MaxValue; - private string terminatingOutput; - - private void LogMessage (string message) - { - logger.LogMessage (message); - } - - public CommandRunner(string command, ILogger logger) { - this.command = command; - this.logger = logger; - } - - public CommandRunner WithArguments(string args) { - this.args = args; - return this; - } - - public CommandRunner WithWorkingDir(string workingDir) { - this.workingDir = workingDir; - return this; - } - - public CommandRunner WithAdditionalPath(string additionalPath) { - this.additionalPath = additionalPath; - return this; - } - - public CommandRunner WithTimeout(int timeout) { - this.timeout = timeout; - return this; - } - - public CommandRunner WithTerminatingOutput(string terminatingOutput) { - this.terminatingOutput = terminatingOutput; - return this; - } - - public int Run() - { - return Run(out string commandOutputUnused); - } - - public int Run(out string commandOutput) - { - if (String.IsNullOrEmpty(command)) { - throw new Exception("No command was specified specified."); - } - if (logger == null) { - throw new Exception("No logger present."); - } - var psi = new ProcessStartInfo - { - FileName = command, - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - }; - LogMessage ($"caller working directory: {Environment.CurrentDirectory}"); - if (!String.IsNullOrEmpty(args)) { - psi.Arguments = args; - LogMessage ($"{command} {args}"); - } else { - LogMessage ($"{command}"); - } - if (!String.IsNullOrEmpty(workingDir)) { - LogMessage ($"working directory: {workingDir}"); - psi.WorkingDirectory = workingDir; - } - if (!String.IsNullOrEmpty(additionalPath)) { - string path = psi.Environment["PATH"]; - psi.Environment["PATH"] = path + ";" + additionalPath; - } - var process = new Process(); - process.StartInfo = psi; - - // dotnet sets some environment variables that - // may cause problems in the child process. - psi.Environment.Remove("MSBuildExtensionsPath"); - psi.Environment.Remove("MSBuildLoadMicrosoftTargetsReadOnly"); - psi.Environment.Remove("MSBuildSDKsPath"); - psi.Environment.Remove("VbcToolExe"); - psi.Environment.Remove("CscToolExe"); - psi.Environment.Remove("MSBUILD_EXE_PATH"); - - LogMessage ("environment:"); - foreach (var item in psi.Environment) { - LogMessage ($"\t{item.Key}={item.Value}"); - } - - StringBuilder processOutput = new StringBuilder(); - DataReceivedEventHandler handler = (sender, e) => { - processOutput.Append(e.Data); - processOutput.AppendLine(); - }; - StringBuilder processError = new StringBuilder(); - DataReceivedEventHandler ehandler = (sender, e) => { - processError.Append(e.Data); - processError.AppendLine(); - }; - process.OutputDataReceived += handler; - process.ErrorDataReceived += ehandler; - - // terminate process if output contains specified string - if (!String.IsNullOrEmpty(terminatingOutput)) { - DataReceivedEventHandler terminatingOutputHandler = (sender, e) => { - if (!String.IsNullOrEmpty(e.Data) && e.Data.Contains(terminatingOutput)) { - process.Kill(); - } - }; - process.OutputDataReceived += terminatingOutputHandler; - } - - // start the process - process.Start(); - process.BeginOutputReadLine(); - process.BeginErrorReadLine(); - if (!process.WaitForExit(timeout)) { - LogMessage ($"killing process after {timeout} ms"); - process.Kill(); - } - // WaitForExit with timeout doesn't guarantee - // that the async output handlers have been - // called, so WaitForExit needs to be called - // afterwards. - process.WaitForExit(); - string processOutputStr = processOutput.ToString(); - string processErrorStr = processError.ToString(); - LogMessage(processOutputStr); - LogMessage(processErrorStr); - commandOutput = processOutputStr; - return process.ExitCode; - } - } -} diff --git a/test/ILLink.Tasks.Tests/HelloWorldTest.cs b/test/ILLink.Tasks.Tests/HelloWorldTest.cs deleted file mode 100644 index b9d1528c5..000000000 --- a/test/ILLink.Tasks.Tests/HelloWorldTest.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using System.IO; -using Xunit; -using Xunit.Abstractions; -using Xunit.Sdk; - -namespace ILLink.Tests -{ - public class HelloWorldFixture : ProjectFixture - { - public string csproj; - - public HelloWorldFixture (IMessageSink diagnosticMessageSink) : base (diagnosticMessageSink) - { - csproj = SetupProject (); - } - - public string SetupProject() - { - string projectRoot = "helloworld"; - string csproj = Path.Combine(projectRoot, $"{projectRoot}.csproj"); - - if (File.Exists(csproj)) { - LogMessage ($"using existing project {csproj}"); - return csproj; - } - - if (Directory.Exists(projectRoot)) { - Directory.Delete(projectRoot, true); - } - - Directory.CreateDirectory(projectRoot); - int ret = CommandHelper.Dotnet("new console", projectRoot); - if (ret != 0) { - LogMessage ("dotnet new failed"); - Assert.True(false); - } - - AddLinkerReference(csproj); - - return csproj; - } - - } - - public class HelloWorldTest : IntegrationTestBase, IClassFixture - { - HelloWorldFixture fixture; - - public HelloWorldTest(HelloWorldFixture fixture, ITestOutputHelper helper) : base(helper) { - this.fixture = fixture; - } - - [Fact] - public void RunHelloWorldStandalone() - { - string executablePath = BuildAndLink(fixture.csproj, selfContained: true); - CheckOutput(executablePath, selfContained: true); - } - - [Fact] - public void RunHelloWorldPortable() - { - string target = BuildAndLink(fixture.csproj, selfContained: false); - CheckOutput(target, selfContained: false); - } - - void CheckOutput(string target, bool selfContained = false) - { - int ret = RunApp(target, out string commandOutput, selfContained: selfContained); - Assert.True(ret == 0); - Assert.Contains("Hello World!", commandOutput); - } - } -} diff --git a/test/ILLink.Tasks.Tests/ILLink.Tasks.Tests.csproj b/test/ILLink.Tasks.Tests/ILLink.Tasks.Tests.csproj deleted file mode 100644 index 5ce4708cc..000000000 --- a/test/ILLink.Tasks.Tests/ILLink.Tasks.Tests.csproj +++ /dev/null @@ -1,33 +0,0 @@ - - - - netcoreapp3.0 - - false - false - - - - - - PreserveNewest - - - - - - - - - - - - - - - - - - - diff --git a/test/ILLink.Tasks.Tests/IntegrationTestBase.cs b/test/ILLink.Tasks.Tests/IntegrationTestBase.cs deleted file mode 100644 index 3027f4fca..000000000 --- a/test/ILLink.Tasks.Tests/IntegrationTestBase.cs +++ /dev/null @@ -1,176 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Xml.Linq; -using Xunit; -using Xunit.Abstractions; - -namespace ILLink.Tests -{ - - /// - /// Represents a project. Each fixture contains setup code run - /// once before all tests in the same test class. ProjectFixture - /// is the base type for different specific project fixtures. - /// - public class ProjectFixture - { - private FixtureLogger logger; - protected CommandHelper CommandHelper; - - protected void LogMessage (string message) - { - logger.LogMessage (message); - } - - public ProjectFixture (IMessageSink diagnosticMessageSink) - { - logger = new FixtureLogger (diagnosticMessageSink); - CommandHelper = new CommandHelper (logger); - } - - protected void AddLinkerReference(string csproj) - { - var xdoc = XDocument.Load(csproj); - var ns = xdoc.Root.GetDefaultNamespace(); - bool added = false; - foreach (var el in xdoc.Root.Elements(ns + "ItemGroup")) { - if (el.Elements(ns + "PackageReference").Any()) { - el.Add(new XElement(ns+"PackageReference", - new XAttribute("Include", TestContext.TasksPackageName), - new XAttribute("Version", TestContext.TasksPackageVersion))); - added = true; - break; - } - } - if (!added) { - xdoc.Root.Add(new XElement(ns + "ItemGroup", - new XElement(ns + "PackageReference", - new XAttribute("Include", TestContext.TasksPackageName), - new XAttribute("Version", TestContext.TasksPackageVersion)))); - added= true; - } - - using (var fs = new FileStream(csproj, FileMode.Create)) { - xdoc.Save(fs); - } - } - - static void AddLinkerRoots(string csproj, List rootFiles) - { - var xdoc = XDocument.Load(csproj); - var ns = xdoc.Root.GetDefaultNamespace(); - - var rootsItemGroup = new XElement(ns+"ItemGroup"); - foreach (var rootFile in rootFiles) { - rootsItemGroup.Add(new XElement(ns+"LinkerRootFiles", - new XAttribute("Include", rootFile))); - } - - var propertyGroup = xdoc.Root.Elements(ns + "PropertyGroup").First(); - propertyGroup.AddAfterSelf(rootsItemGroup); - - using (var fs = new FileStream(csproj, FileMode.Create)) { - xdoc.Save(fs); - } - } - - } - - /// - /// Contains logic shared by multiple test classes. - /// - public class IntegrationTestBase - { - private readonly TestLogger logger; - protected readonly CommandHelper CommandHelper; - - public IntegrationTestBase(ITestOutputHelper output) - { - logger = new TestLogger(output); - CommandHelper = new CommandHelper(logger); - } - - private void LogMessage (string message) - { - logger.LogMessage (message); - } - - /// - /// Run the linker on the specified project. This assumes - /// that the project already contains a reference to the - /// linker task package. - /// Optionally takes a list of root descriptor files. - /// Returns the path to the built app, either the renamed - /// host for self-contained publish, or the dll containing - /// the entry point. - /// - public string BuildAndLink(string csproj, List rootFiles = null, Dictionary extraPublishArgs = null, bool selfContained = false) - { - string demoRoot = Path.GetDirectoryName(csproj); - - string publishArgs = $"publish -c {TestContext.Configuration} /v:n /p:ShowLinkerSizeComparison=true"; - if (selfContained) { - publishArgs += $" -r {TestContext.RuntimeIdentifier}"; - } - string rootFilesStr; - if (rootFiles != null && rootFiles.Any()) { - rootFilesStr = String.Join(";", rootFiles); - publishArgs += $" /p:LinkerRootDescriptors={rootFilesStr}"; - } - if (extraPublishArgs != null) { - foreach (var item in extraPublishArgs) { - publishArgs += $" /p:{item.Key}={item.Value}"; - } - } - int ret = CommandHelper.Dotnet(publishArgs, demoRoot); - - if (ret != 0) { - LogMessage("publish failed, returning " + ret); - Assert.True(false); - } - - // detect the target framework for which the app was published - string tfmDir = Path.Combine(demoRoot, "bin", TestContext.Configuration); - string tfm = Directory.GetDirectories(tfmDir).Select(p => Path.GetFileName(p)).Single(); - string builtApp = Path.Combine(tfmDir, tfm); - if (selfContained) { - builtApp = Path.Combine(builtApp, TestContext.RuntimeIdentifier); - } - builtApp = Path.Combine(builtApp, "publish", - Path.GetFileNameWithoutExtension(csproj)); - if (selfContained) { - if (TestContext.RuntimeIdentifier.Contains("win")) { - builtApp += ".exe"; - } - } else { - builtApp += ".dll"; - } - Assert.True(File.Exists(builtApp)); - return builtApp; - } - - public int RunApp(string target, out string processOutput, int timeout = Int32.MaxValue, - string terminatingOutput = null, bool selfContained = false) - { - Assert.True(File.Exists(target)); - int ret; - if (selfContained) { - ret = CommandHelper.RunCommand( - target, null, - Directory.GetParent(target).FullName, - null, out processOutput, timeout, terminatingOutput); - } else { - ret = CommandHelper.RunCommand( - Path.GetFullPath(TestContext.DotnetToolPath), - Path.GetFullPath(target), - Directory.GetParent(target).FullName, - null, out processOutput, timeout, terminatingOutput); - } - return ret; - } - } -} diff --git a/test/ILLink.Tasks.Tests/Loggers.cs b/test/ILLink.Tasks.Tests/Loggers.cs deleted file mode 100644 index 083cb2769..000000000 --- a/test/ILLink.Tasks.Tests/Loggers.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Xunit.Abstractions; -using Xunit.Sdk; - -namespace ILLink.Tests -{ - public interface ILogger - { - void LogMessage (string message); - } - - public class TestLogger : ILogger - { - private ITestOutputHelper output; - public TestLogger (ITestOutputHelper output) - { - this.output = output; - } - public void LogMessage (string message) - { - output.WriteLine (message); - } - } - - public class FixtureLogger : ILogger - { - private IMessageSink messageSink; - public FixtureLogger (IMessageSink messageSink) - { - this.messageSink = messageSink; - } - public void LogMessage (string message) - { - messageSink.OnMessage (new DiagnosticMessage (message)); - } - } -} \ No newline at end of file diff --git a/test/ILLink.Tasks.Tests/MusicStoreReflection.xml b/test/ILLink.Tasks.Tests/MusicStoreReflection.xml deleted file mode 100755 index e35f91155..000000000 --- a/test/ILLink.Tasks.Tests/MusicStoreReflection.xml +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/ILLink.Tasks.Tests/MusicStoreTest.cs b/test/ILLink.Tasks.Tests/MusicStoreTest.cs deleted file mode 100644 index 0ae386cf2..000000000 --- a/test/ILLink.Tasks.Tests/MusicStoreTest.cs +++ /dev/null @@ -1,241 +0,0 @@ -using System; -using System.IO; -using System.Collections.Generic; -using System.Linq; -using System.Xml.Linq; -using Xunit; -using Xunit.Abstractions; // ITestOutputHelper - -namespace ILLink.Tests -{ - public class MusicStoreFixture : ProjectFixture - { - public static List rootFiles = new List { "MusicStoreReflection.xml" }; - - private static string gitRepo = "http://github.com/aspnet/JitBench"; - private static string repoName = "JitBench"; - - // Revision can also be a branch name. We generally - // want to ensure that we are able to link the latest - // MusicStore from the dev branch. - private static string gitRevision = "ac314bd68294ae0f91bd16df20cf5ebd4b8ef5b5"; - - // The version of Microsoft.NETCore.App that - // musicstore will run on (and deploy with, for - // self-contained deployments). - private static string runtimeVersion = "3.0.0-preview-27324-5"; - - // The version of the SDK used to build and link - // musicstore, if a specific version is desired. - private static string sdkVersion = "2.2.0-preview1-007525"; - - // The version of Microsoft.AspNetCore.All to publish with. - private static string aspNetVersion = "2.1.0-preview1-27654"; - - public static Dictionary versionPublishArgs; - public static Dictionary VersionPublishArgs - { - get { - if (versionPublishArgs != null) { - return versionPublishArgs; - } - versionPublishArgs = new Dictionary(); - versionPublishArgs.Add("JITBENCH_FRAMEWORK_VERSION", runtimeVersion); - versionPublishArgs.Add("JITBENCH_ASPNET_VERSION", aspNetVersion); - return versionPublishArgs; - } - } - - public static string csproj; - - public MusicStoreFixture(IMessageSink diagnosticMessageSink) : base(diagnosticMessageSink) - { - csproj = SetupProject(); - } - - // returns path to .csproj project file - string SetupProject() - { - int ret; - string demoRoot = Path.Combine(repoName, Path.Combine("src", "MusicStore")); - string csproj = Path.Combine(demoRoot, "MusicStore.csproj"); - - if (File.Exists(csproj)) { - LogMessage($"using existing project {csproj}"); - return csproj; - } - - if (Directory.Exists(repoName)) { - Directory.Delete(repoName, true); - } - - ret = CommandHelper.RunCommand("git", $"clone {gitRepo} {repoName}"); - if (ret != 0) { - LogMessage("git failed"); - Assert.True(false); - } - - if (!Directory.Exists(demoRoot)) { - LogMessage($"{demoRoot} does not exist"); - Assert.True(false); - } - - ret = CommandHelper.RunCommand("git", $"checkout {gitRevision}", demoRoot); - if (ret != 0) { - LogMessage($"problem checking out revision {gitRevision}"); - Assert.True(false); - } - - // Copy root files into the project directory - CopyRootFiles(demoRoot); - - // This is necessary because JitBench comes with a - // NuGet.Config that has a line, preventing - // NuGet.Config sources defined in outer directories from - // applying. - string nugetConfig = Path.Combine(repoName, "NuGet.config"); - AddLocalNugetFeedAfterClear(nugetConfig); - - AddLinkerReference(csproj); - - // We no longer need a custom global.json, because we are - // using the same SDK used in the repo. - // AddGlobalJson(repoName); - - return csproj; - } - - void AddGlobalJson(string repoDir) - { - string globalJson = Path.Combine(repoDir, "global.json"); - string globalJsonContents = "{ \"sdk\": { \"version\": \"" + sdkVersion + "\" } }\n"; - File.WriteAllText(globalJson, globalJsonContents); - } - - string GetDotnetToolPath(string dotnetDir) - { - string dotnetToolName = Directory.GetFiles(dotnetDir) - .Select(p => Path.GetFileName(p)) - .Where(p => p.Contains("dotnet")) - .Single(); - string dotnetToolPath = Path.Combine(dotnetDir, dotnetToolName); - - if (!File.Exists(dotnetToolPath)) { - LogMessage("repo-local dotnet tool does not exist."); - Assert.True(false); - } - - return dotnetToolPath; - } - - string ObtainSDK(string rootDir, string repoDir) - { - int ret; - string dotnetDirName = ".dotnet"; - string dotnetDir = Path.Combine(rootDir, dotnetDirName); - if (Directory.Exists(dotnetDir)) { - return GetDotnetToolPath(dotnetDir); - } - - string dotnetInstall = Path.Combine(Path.GetFullPath(repoDir), "dotnet-install"); - if (TestContext.RuntimeIdentifier.Contains("win")) { - dotnetInstall += ".ps1"; - } else { - dotnetInstall += ".sh"; - } - if (!File.Exists(dotnetInstall)) { - LogMessage($"missing dotnet-install script at {dotnetInstall}"); - Assert.True(false); - } - - if (TestContext.RuntimeIdentifier.Contains("win")) { - ret = CommandHelper.RunCommand("powershell", $"{dotnetInstall} -SharedRuntime -InstallDir {dotnetDirName} -Channel master -Architecture x64 -Version {runtimeVersion}", rootDir); - if (ret != 0) { - LogMessage("failed to retrieve shared runtime"); - Assert.True(false); - } - ret = CommandHelper.RunCommand("powershell", $"{dotnetInstall} -InstallDir {dotnetDirName} -Channel master -Architecture x64 -Version {sdkVersion}", rootDir); - if (ret != 0) { - LogMessage("failed to retrieve sdk"); - Assert.True(false); - } - } else { - ret = CommandHelper.RunCommand(dotnetInstall, $"-sharedruntime -runtimeid {TestContext.RuntimeIdentifier} -installdir {dotnetDirName} -channel master -architecture x64 -version {runtimeVersion}", rootDir); - if (ret != 0) { - LogMessage("failed to retrieve shared runtime"); - Assert.True(false); - } - ret = CommandHelper.RunCommand(dotnetInstall, $"-installdir {dotnetDirName} -channel master -architecture x64 -version {sdkVersion}", rootDir); - if (ret != 0) { - LogMessage("failed to retrieve sdk"); - Assert.True(false); - } - } - - return GetDotnetToolPath(dotnetDir); - } - - static void CopyRootFiles(string demoRoot) - { - foreach (var rf in rootFiles) { - File.Copy(rf, Path.Combine(demoRoot, rf)); - } - } - - private void AddLocalNugetFeedAfterClear(string nugetConfig) - { - string localPackagePath = Path.GetFullPath(TestContext.PackageSource); - var xdoc = XDocument.Load(nugetConfig); - var ns = xdoc.Root.GetDefaultNamespace(); - var clear = xdoc.Root.Element(ns+"packageSources").Element(ns+"clear"); - clear.Parent.Add(new XElement(ns+"add", - new XAttribute("key", "local linker feed"), - new XAttribute("value", localPackagePath))); - - using (var fs = new FileStream(nugetConfig, FileMode.Create)) { - xdoc.Save(fs); - } - } - } - - public class MusicStoreTest : IntegrationTestBase, IClassFixture - { - - MusicStoreFixture fixture; - - public MusicStoreTest(MusicStoreFixture fixture, ITestOutputHelper output) : base(output) { - this.fixture = fixture; - // MusicStore has been updated to target netcoreapp3.0, so - // we should be able to run on the SDK used to build this - // repo. - // context.DotnetToolPath = ObtainSDK(context.TestBin, repoName); - } - - [Fact] - public void RunMusicStoreStandalone() - { - string executablePath = BuildAndLink(MusicStoreFixture.csproj, MusicStoreFixture.rootFiles, MusicStoreFixture.VersionPublishArgs, selfContained: true); - CheckOutput(executablePath, selfContained: true); - } - - [Fact] - public void RunMusicStorePortable() - { - Dictionary extraPublishArgs = new Dictionary(MusicStoreFixture.VersionPublishArgs); - extraPublishArgs.Add("PublishWithAspNetCoreTargetManifest", "false"); - string target = BuildAndLink(MusicStoreFixture.csproj, null, extraPublishArgs, selfContained: false); - CheckOutput(target, selfContained: false); - } - - void CheckOutput(string target, bool selfContained = false) - { - int ret = RunApp(target, out string commandOutput, selfContained: selfContained); - - Assert.Contains("starting request to http://localhost:5000", commandOutput); - Assert.Contains("Response: OK", commandOutput); - Assert.Contains("Running 100 requests", commandOutput); - Assert.True(ret == 0); - } - - } -} diff --git a/test/ILLink.Tasks.Tests/TestContext.cs b/test/ILLink.Tasks.Tests/TestContext.cs deleted file mode 100644 index 593e5ec95..000000000 --- a/test/ILLink.Tasks.Tests/TestContext.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using Microsoft.DotNet.PlatformAbstractions; - -namespace ILLink.Tests -{ - public static class TestContext - { - /// - /// The name of the tasks package to add to the integration - /// projects. - /// - public static string TasksPackageName { get; private set; } - - /// - /// The version of the tasks package to add to the - /// integration projects. - /// - public static string TasksPackageVersion { get; private set; } - - /// - /// The path of the directory from which to get the linker - /// package. - /// - public static string PackageSource { get; private set; } - - /// - /// The path to the dotnet tool to use to run the - /// integration tests. - /// - public static string DotnetToolPath { get; set; } - - /// - /// The RID to use when restoring, building, and linking the - /// integration test projects. - /// - public static string RuntimeIdentifier { get; private set; } - - /// - /// The configuration to use to build the integration test - /// projects. - /// - public static string Configuration { get; private set; } - - /// - /// The root testbin directory. Used to install test - /// assets that don't depend on the configuration or - /// target framework. - /// - public static string TestBin { get; private set; } - - static TestContext() - { - SetupDefaultContext(); - } - - /// - /// This is the context from which tests will be run in the - /// linker repo. The local directory that contains the - /// linker integration packages (hard-coded here) is - /// searched for the tasks package. This assumes that only - /// one version of the package is present, and uses it to - /// unambiguously determine which package to use in the tests. - /// - public static void SetupDefaultContext() - { - // test working directory is test project's // - var testBin = Path.Combine(Environment.CurrentDirectory, "..", ".."); - var repoRoot = Path.GetFullPath(Path.Combine(testBin, "..", "..", "..")); - - // Locate task package - var packageName = "ILLink.Tasks"; - var packageSource = Path.Combine(repoRoot, "src", "ILLink.Tasks", "bin", "nupkgs"); - var tasksPackages = Directory.GetFiles(packageSource) - .Where(p => Path.GetExtension(p) == ".nupkg") - .Select(p => Path.GetFileNameWithoutExtension(p)) - .Where(p => p.StartsWith(packageName)); - var nPackages = tasksPackages.Count(); - if (nPackages > 1) { - throw new Exception($"duplicate {packageName} packages in {packageSource}"); - } else if (nPackages == 0) { - throw new Exception($"{packageName} package not found in {packageSource}"); - } - var tasksPackage = tasksPackages.Single(); - var version = tasksPackage.Remove(0, packageName.Length + 1); - - // Locate dotnet host - var dotnetDir = Path.Combine(repoRoot, ".dotnet"); - var dotnetToolName = Directory.GetFiles(dotnetDir) - .Select(p => Path.GetFileName(p)) - .Where(p => p.StartsWith("dotnet")) - .Where(p => { - var ext = Path.GetExtension(p); - return ext == "" || ext == ".exe"; - }) - .Single(); - var dotnetToolPath = Path.Combine(dotnetDir, dotnetToolName); - - // Initialize static members - PackageSource = packageSource; - TasksPackageName = packageName; - TasksPackageVersion = version; - DotnetToolPath = dotnetToolPath; - // This sets the RID to the RID of the currently-executing system. - RuntimeIdentifier = RuntimeEnvironment.GetRuntimeIdentifier(); - // workaround: the osx.10.13-x64 RID doesn't exist yet. - // see https://github.com/NuGet/Home/issues/5862 - if (RuntimeIdentifier == "osx.10.14-x64") - { - RuntimeIdentifier = "osx.10.13-x64"; - } - // We want to build and link integration projects in the - // release configuration. - Configuration = "Release"; - TestBin = testBin; - } - } -} diff --git a/test/ILLink.Tasks.Tests/WebApiTest.cs b/test/ILLink.Tasks.Tests/WebApiTest.cs deleted file mode 100644 index 2cdd3495a..000000000 --- a/test/ILLink.Tasks.Tests/WebApiTest.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System; -using System.IO; -using System.Xml.Linq; -using Xunit; -using Xunit.Abstractions; - -namespace ILLink.Tests -{ - public class WebApiFixture : ProjectFixture - { - public string csproj; - - public WebApiFixture(IMessageSink diagnosticMessageSink) : base(diagnosticMessageSink) { - csproj = SetupProject(); - } - - public string SetupProject() - { - string projectRoot = "webapi"; - string csproj = Path.Combine(projectRoot, $"{projectRoot}.csproj"); - - if (File.Exists(csproj)) { - LogMessage($"using existing project {csproj}"); - return csproj; - } - - if (Directory.Exists(projectRoot)) { - Directory.Delete(projectRoot, true); - } - - Directory.CreateDirectory(projectRoot); - int ret = CommandHelper.Dotnet("new webapi", projectRoot); - if (ret != 0) { - LogMessage("dotnet new failed"); - Assert.True(false); - } - - PreventPublishFiltering(csproj); - - AddLinkerReference(csproj); - - return csproj; - } - - // TODO: Remove this once we figure out what to do about apps - // that have the publish output filtered by a manifest - // file. It looks like aspnet has made this the default. See - // the bug at https://github.com/dotnet/sdk/issues/1160. - private void PreventPublishFiltering(string csproj) { - var xdoc = XDocument.Load(csproj); - var ns = xdoc.Root.GetDefaultNamespace(); - - var propertygroup = xdoc.Root.Element(ns + "PropertyGroup"); - - LogMessage("setting PublishWithAspNetCoreTargetManifest=false"); - propertygroup.Add(new XElement(ns + "PublishWithAspNetCoreTargetManifest", - "false")); - - using (var fs = new FileStream(csproj, FileMode.Create)) { - xdoc.Save(fs); - } - } - } - - public class WebApiTest : IntegrationTestBase, IClassFixture - { - private WebApiFixture fixture; - - public WebApiTest(WebApiFixture fixture, ITestOutputHelper output) : base(output) - { - this.fixture = fixture; - } - - [Fact] - public void RunWebApiStandalone() - { - string executablePath = BuildAndLink(fixture.csproj, selfContained: true); - CheckOutput(executablePath, selfContained: true); - } - - [Fact] - public void RunWebApiPortable() - { - string target = BuildAndLink(fixture.csproj, selfContained: false); - CheckOutput(target, selfContained: false); - } - - void CheckOutput(string target, bool selfContained = false) - { - string terminatingOutput = "Application started. Press Ctrl+C to shut down."; - int ret = RunApp(target, out string commandOutput, 60000, terminatingOutput, selfContained: selfContained); - Assert.Contains("Now listening on: http://localhost:5000", commandOutput); - Assert.Contains(terminatingOutput, commandOutput); - } - } -} diff --git a/test/ILLink.Tasks.Tests/nuget/NuGet.config b/test/ILLink.Tasks.Tests/nuget/NuGet.config deleted file mode 100644 index 1954d0af0..000000000 --- a/test/ILLink.Tasks.Tests/nuget/NuGet.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - diff --git a/test/ILLink.Tasks.Tests/xunit.runner.json b/test/ILLink.Tasks.Tests/xunit.runner.json deleted file mode 100644 index 40be06652..000000000 --- a/test/ILLink.Tasks.Tests/xunit.runner.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "diagnosticMessages": true -} \ No newline at end of file diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Mono.Linker.Tests.Cases.Expectations.csproj b/test/Mono.Linker.Tests.Cases.Expectations/Mono.Linker.Tests.Cases.Expectations.csproj index db2718da3..a7faebae5 100644 --- a/test/Mono.Linker.Tests.Cases.Expectations/Mono.Linker.Tests.Cases.Expectations.csproj +++ b/test/Mono.Linker.Tests.Cases.Expectations/Mono.Linker.Tests.Cases.Expectations.csproj @@ -1,13 +1,13 @@ - Debug;Release;illink_Debug;illink_Release + Debug;Release - + netcoreapp3.0 - + net471 diff --git a/test/Mono.Linker.Tests.Cases/Mono.Linker.Tests.Cases.csproj b/test/Mono.Linker.Tests.Cases/Mono.Linker.Tests.Cases.csproj index f1b5db37a..852a4a5bb 100644 --- a/test/Mono.Linker.Tests.Cases/Mono.Linker.Tests.Cases.csproj +++ b/test/Mono.Linker.Tests.Cases/Mono.Linker.Tests.Cases.csproj @@ -6,18 +6,16 @@ true false 8.0 - Debug;Release;illink_Debug;illink_Release + Debug;Release - + netcoreapp3.0 - true $(DefineConstants);ILLINK - + net471 - false @@ -131,7 +129,7 @@ - + diff --git a/test/Mono.Linker.Tests/Mono.Linker.Tests.csproj b/test/Mono.Linker.Tests/Mono.Linker.Tests.csproj index 3653c8e6b..236ff33ab 100644 --- a/test/Mono.Linker.Tests/Mono.Linker.Tests.csproj +++ b/test/Mono.Linker.Tests/Mono.Linker.Tests.csproj @@ -1,26 +1,20 @@ - + + - true - Debug;Release;illink_Debug;illink_Release + Debug;Release - + netcoreapp3.0 - true $(DefineConstants);ILLINK - $(DefineConstants);DEBUG + $(DefineConstants);DEBUG $(DefineConstants);NETCOREAPP - - $(DefineConstants);ARCADE - - true - + net471 - false @@ -36,7 +30,7 @@ - + @@ -48,29 +42,37 @@ - + $(MSBuildThisFileDirectory)../../eng/ilasm.ilproj - $(ArtifactsDir)tools - $(MSBuildThisFileDirectory)$(BaseIntermediateOutputPath)tools + $(ArtifactsDir)tools - + - + + + + + + + + + diff --git a/test/Mono.Linker.Tests/TestCases/TestDatabase.cs b/test/Mono.Linker.Tests/TestCases/TestDatabase.cs index b29dd2d43..fbb516153 100644 --- a/test/Mono.Linker.Tests/TestCases/TestDatabase.cs +++ b/test/Mono.Linker.Tests/TestCases/TestDatabase.cs @@ -193,19 +193,11 @@ namespace Mono.Linker.Tests.TestCases static void GetDirectoryPaths(out string rootSourceDirectory, out string testCaseAssemblyPath, [CallerFilePath] string thisFile = null) { -#if ILLINK -#if DEBUG - var configDirectoryName = "illink_Debug"; -#else - var configDirectoryName = "illink_Release"; -#endif -#else #if DEBUG var configDirectoryName = "Debug"; #else var configDirectoryName = "Release"; #endif -#endif #if NETCOREAPP3_0 var tfm = "netcoreapp3.0"; @@ -218,18 +210,11 @@ namespace Mono.Linker.Tests.TestCases #if ILLINK // Deterministic builds sanitize source paths, so CallerFilePathAttribute gives an incorrect path. // Instead, get the testcase dll based on the working directory of the test runner. -#if ARCADE + // working directory is artifacts/bin/Mono.Linker.Tests// var artifactsBinDir = Path.Combine (Directory.GetCurrentDirectory (), "..", "..", ".."); rootSourceDirectory = Path.GetFullPath (Path.Combine (artifactsBinDir, "..", "..", "test", "Mono.Linker.Tests.Cases")); testCaseAssemblyPath = Path.GetFullPath (Path.Combine (artifactsBinDir, "Mono.Linker.Tests.Cases", configDirectoryName, tfm, "Mono.Linker.Tests.Cases.dll")); -#else - // working directory is test/Mono.Linker.Tests/bin// - var testDir = Path.Combine (Directory.GetCurrentDirectory (), "..", "..", "..", ".."); - rootSourceDirectory = Path.GetFullPath (Path.Combine (testDir, "Mono.Linker.Tests.Cases")); - testCaseAssemblyPath = Path.GetFullPath (Path.Combine (rootSourceDirectory, "bin", configDirectoryName, tfm, "Mono.Linker.Tests.Cases.dll")); -#endif // ARCADE - #else var thisDirectory = Path.GetDirectoryName (thisFile); rootSourceDirectory = Path.GetFullPath (Path.Combine (thisDirectory, "..", "..", "Mono.Linker.Tests.Cases")); diff --git a/test/Mono.Linker.Tests/TestCasesRunner/ILCompiler.cs b/test/Mono.Linker.Tests/TestCasesRunner/ILCompiler.cs index 14ec56d9e..a35c10787 100644 --- a/test/Mono.Linker.Tests/TestCasesRunner/ILCompiler.cs +++ b/test/Mono.Linker.Tests/TestCasesRunner/ILCompiler.cs @@ -68,13 +68,10 @@ namespace Mono.Linker.Tests.TestCasesRunner { { #if ILLINK var extension = RuntimeInformation.IsOSPlatform (OSPlatform.Windows) ? ".exe" : ""; -#if ARCADE + // working directory is artifacts/bin/Mono.Linker.Tests// var toolsDir = Path.Combine (Directory.GetCurrentDirectory (), "..", "..", "..", "..", "tools"); -#else - // working directory is test/Mono.Linker.Tests/bin// - var toolsDir = Path.Combine (Directory.GetCurrentDirectory (), "..", "..", "..", "obj", "tools"); -#endif // ARCADE + var ilasmPath = Path.GetFullPath (Path.Combine (toolsDir, "ilasm", $"ilasm{extension}")).ToNPath (); if (ilasmPath.FileExists ()) return ilasmPath; -- cgit v1.2.3