diff --git a/NUnitConsole.sln b/NUnitConsole.sln index 95a3d2ac5..468bc2cdf 100644 --- a/NUnitConsole.sln +++ b/NUnitConsole.sln @@ -145,12 +145,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "nunit.common", "src\NUnitCo EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "nunit.common.tests", "src\NUnitCommon\nunit.common.tests\nunit.common.tests.csproj", "{6605DA54-EBF4-4ED1-B5BC-B607AD0CE308}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "nunit.agent.core", "src\NUnitCommon\nunit.agent.core\nunit.agent.core.csproj", "{4FCFAF1C-1579-4A1C-BAF9-9627E39D7CDA}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "nunit.agent.core.tests", "src\NUnitCommon\nunit.agent.core.tests\nunit.agent.core.tests.csproj", "{89258A3E-5B62-487A-9AE7-D7672CBF61F1}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DirectTestAgent", "src\NUnitCommon\DirectTestAgent\DirectTestAgent.csproj", "{0E415863-1621-41DB-9DB0-36B5664DFF35}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FakeExtensions", "src\TestData\FakeExtensions\2.0\FakeExtensions.csproj", "{E3A8037B-83EF-CB79-3EED-492C89F47BF9}" EndProject Global @@ -251,18 +245,6 @@ Global {6605DA54-EBF4-4ED1-B5BC-B607AD0CE308}.Debug|Any CPU.Build.0 = Debug|Any CPU {6605DA54-EBF4-4ED1-B5BC-B607AD0CE308}.Release|Any CPU.ActiveCfg = Release|Any CPU {6605DA54-EBF4-4ED1-B5BC-B607AD0CE308}.Release|Any CPU.Build.0 = Release|Any CPU - {4FCFAF1C-1579-4A1C-BAF9-9627E39D7CDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4FCFAF1C-1579-4A1C-BAF9-9627E39D7CDA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4FCFAF1C-1579-4A1C-BAF9-9627E39D7CDA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4FCFAF1C-1579-4A1C-BAF9-9627E39D7CDA}.Release|Any CPU.Build.0 = Release|Any CPU - {89258A3E-5B62-487A-9AE7-D7672CBF61F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {89258A3E-5B62-487A-9AE7-D7672CBF61F1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {89258A3E-5B62-487A-9AE7-D7672CBF61F1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {89258A3E-5B62-487A-9AE7-D7672CBF61F1}.Release|Any CPU.Build.0 = Release|Any CPU - {0E415863-1621-41DB-9DB0-36B5664DFF35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0E415863-1621-41DB-9DB0-36B5664DFF35}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0E415863-1621-41DB-9DB0-36B5664DFF35}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0E415863-1621-41DB-9DB0-36B5664DFF35}.Release|Any CPU.Build.0 = Release|Any CPU {E3A8037B-83EF-CB79-3EED-492C89F47BF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E3A8037B-83EF-CB79-3EED-492C89F47BF9}.Debug|Any CPU.Build.0 = Debug|Any CPU {E3A8037B-83EF-CB79-3EED-492C89F47BF9}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -304,9 +286,6 @@ Global {B22FEE5B-83D4-4021-B066-1B958332D391} = {3B30D2E5-1587-4D68-B848-1BDDB3C24BFC} {9D9CAD66-8EDF-4ED0-A222-503BE9B21EC7} = {3B30D2E5-1587-4D68-B848-1BDDB3C24BFC} {6605DA54-EBF4-4ED1-B5BC-B607AD0CE308} = {3B30D2E5-1587-4D68-B848-1BDDB3C24BFC} - {4FCFAF1C-1579-4A1C-BAF9-9627E39D7CDA} = {3B30D2E5-1587-4D68-B848-1BDDB3C24BFC} - {89258A3E-5B62-487A-9AE7-D7672CBF61F1} = {3B30D2E5-1587-4D68-B848-1BDDB3C24BFC} - {0E415863-1621-41DB-9DB0-36B5664DFF35} = {3B30D2E5-1587-4D68-B848-1BDDB3C24BFC} {E3A8037B-83EF-CB79-3EED-492C89F47BF9} = {37D508B2-91E0-4B32-869B-DFF9E68EA213} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution diff --git a/build.cake b/build.cake index fc4440e18..17caa4159 100644 --- a/build.cake +++ b/build.cake @@ -1,5 +1,5 @@ // Load the recipe -#load nuget:?package=NUnit.Cake.Recipe&version=2.0.0-beta.4.2 +#load nuget:?package=NUnit.Cake.Recipe&version=2.0.0-beta.4.3 // Comment out above line and uncomment below for local tests of recipe changes //#load ../NUnit.Cake.Recipe/src/NUnit.Cake.Recipe/content/*.cake @@ -73,26 +73,6 @@ PackageDefinition NUnitExtensibilityPackage = new NuGetPackage( HasDirectory("lib/netstandard2.0").WithFile("nunit.extensibility.pdb") }); -PackageDefinition NUnitAgentCorePackage = new NuGetPackage( - id: "NUnit.Agent.Core", - source: BuildSettings.SourceDirectory + "NUnitCommon/nunit.agent.core/nunit.agent.core.csproj", - checks: new PackageCheck[] - { - HasFiles("LICENSE.txt"), - HasDirectory("lib/net462").WithFile("nunit.agent.core.dll" ), - HasDirectory("lib/net8.0").WithFiles("nunit.agent.core.dll"), - HasDependency("NUnit.Engine.Api"), - HasDependency("NUnit.Common", THIS_VERSION), - HasDependency("TestCentric.Metadata", "3.0.4") - }, - symbols: new PackageCheck[] - { - HasDirectory("lib/net462").WithFile("nunit.agent.core.pdb"), - HasDirectory("lib/net8.0").WithFile("nunit.agent.core.pdb") - }, - testRunner: new DirectTestAgentRunner(), - tests: AgentCoreTests); - PackageDefinition NUnitEnginePackage = new NuGetPackage( id: "NUnit.Engine", source: BuildSettings.SourceDirectory + "NUnitEngine/nunit.engine/nunit.engine.csproj", @@ -167,7 +147,6 @@ BuildSettings.Packages.AddRange(new PackageDefinition[] { NUnitExtensibilityApiPackage, NUnitCommonPackage, NUnitExtensibilityPackage, - NUnitAgentCorePackage, NUnitEnginePackage, NUnitConsoleRunnerDotNetToolPackage, NUnitConsoleRunnerNuGetPackage, diff --git a/package-tests.cake b/package-tests.cake index e0938b3f7..6f9ba0cff 100644 --- a/package-tests.cake +++ b/package-tests.cake @@ -68,13 +68,6 @@ AddToBothLists(new PackageTest(1, "Net60Test") ExpectedResult = new MockAssemblyExpectedResult("netcore-6.0") }); -AddToBothLists(new PackageTest(1, "NetCore31Test") -{ - Description = "Run mock-assembly.dll under .NET Core 3.1", - Arguments = "testdata/netcoreapp3.1/mock-assembly.dll", - ExpectedResult = new MockAssemblyExpectedResult("netcore-3.1") -}); - ////////////////////////////////////////////////////////////////////// // RUN MOCK-ASSEMBLY-X86 UNDER EACH RUNTIME ////////////////////////////////////////////////////////////////////// @@ -132,13 +125,6 @@ if (dotnetX86Available) Arguments = "testdata/net7.0/mock-assembly-x86.dll", ExpectedResult = new MockAssemblyX86ExpectedResult("netcore-7.0") }); - - StandardRunnerTests.Add(new PackageTest(1, "NetCore31X86Test") - { - Description = "Run mock-assembly-x86.dll under .NET Core 3.1", - Arguments = "testdata/netcoreapp3.1/mock-assembly-x86.dll", - ExpectedResult = new MockAssemblyX86ExpectedResult("netcore-3.1") - }); } } diff --git a/src/Directory.Build.props b/src/Directory.Build.props index e4175408e..b9f5b9048 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -20,9 +20,6 @@ portable true - - 8.0.0 - 4.0.0-beta.4 NUnit Software NUnit 4 Runner and Engine @@ -40,11 +37,17 @@ 2.0.3 - + - 4.6.1 - 5.3.0 + 8.0.0 + 4.0.0-beta.4 4.14.0 + 4.0.0-beta.2.3 + 4.0.0-beta.4 + 4.0.0-beta.2.3 + 4.6.1 + 5.3.0 + 3.0.4 diff --git a/src/NUnitCommon/DirectTestAgent/DirectTestAgent.cs b/src/NUnitCommon/DirectTestAgent/DirectTestAgent.cs deleted file mode 100644 index 736a8d492..000000000 --- a/src/NUnitCommon/DirectTestAgent/DirectTestAgent.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using System.Diagnostics; - -namespace NUnit.Agents -{ - public class DirectTestAgent : NUnitAgent - { - public static void Main(string[] args) - { - Execute(args); - } - } -} diff --git a/src/NUnitCommon/DirectTestAgent/DirectTestAgent.csproj b/src/NUnitCommon/DirectTestAgent/DirectTestAgent.csproj deleted file mode 100644 index ea99841eb..000000000 --- a/src/NUnitCommon/DirectTestAgent/DirectTestAgent.csproj +++ /dev/null @@ -1,24 +0,0 @@ - - - - NUnit.Agents.Agents - Exe - net462;net8.0 - ..\..\bin\$(Configuration)\direct-test-agent\ - false - - - - - - - - - - - - - - - - diff --git a/src/NUnitCommon/nunit.agent.core.tests/AgentDirectRunnerTests.cs b/src/NUnitCommon/nunit.agent.core.tests/AgentDirectRunnerTests.cs deleted file mode 100644 index b810b864d..000000000 --- a/src/NUnitCommon/nunit.agent.core.tests/AgentDirectRunnerTests.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -namespace NUnit.Agents -{ - public class AgentDirectRunnerTests - { - //[Test] -// public void RunAgentDirectly() -// { -// RunTestUnderTestBed(typeof(MockAssembly).Assembly.Location); -// } - -// private static void RunTestUnderTestBed(string testAssembly) -// { -// string agentAssembly = typeof(DirectTestAgent).Assembly.Location; - -//#if NETFRAMEWORK -// string agentExe = agentAssembly; -//#else -// string agentExe = Path.ChangeExtension(agentAssembly, ".exe"); -//#endif -// var startInfo = new ProcessStartInfo(agentExe); -// startInfo.Arguments = testAssembly; -// startInfo.RedirectStandardOutput = true; -// startInfo.UseShellExecute = false; - -// Process? process = Process.Start(startInfo); - -// if (process is not null) -// { -// process.WaitForExit(); -// Console.WriteLine($"Agent process exited with rc={process.ExitCode}"); - -// string output = process.StandardOutput.ReadToEnd(); -// if (!output.Contains("Test Run Summary")) -// Assert.Fail("No Summary Report found"); -// } -// } - } -} diff --git a/src/NUnitCommon/nunit.agent.core.tests/AgentOptionTests.cs b/src/NUnitCommon/nunit.agent.core.tests/AgentOptionTests.cs deleted file mode 100644 index 6990f4b01..000000000 --- a/src/NUnitCommon/nunit.agent.core.tests/AgentOptionTests.cs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using System; -using NUnit.Engine; -using NUnit.Framework; - -namespace NUnit.Agents -{ - public class AgentOptionTests - { - private static TestCaseData[] DefaultSettings = new[] - { - new TestCaseData("AgentId", Guid.Empty), - new TestCaseData("AgencyUrl", string.Empty), - new TestCaseData("AgencyPid", string.Empty), - new TestCaseData("DebugAgent", false), - new TestCaseData("DebugTests", false), - new TestCaseData("TraceLevel", InternalTraceLevel.Off), - new TestCaseData("WorkDirectory", string.Empty) - }; - - [TestCaseSource(nameof(DefaultSettings))] - public void DefaultOptionSettings(string propertyName, T defaultValue) - { - var options = new AgentOptions(); - var prop = typeof(AgentOptions).GetProperty(propertyName); - Assert.That(prop, Is.Not.Null, $"Property {propertyName} does not exist"); - Assert.That(prop.GetValue(options, Array.Empty()), Is.EqualTo(defaultValue)); - } - - private static readonly Guid AGENT_GUID = Guid.NewGuid(); - private static readonly TestCaseData[] ValidSettings = new[] - { - // Boolean options - no values provided - new TestCaseData("--debug-agent", "DebugAgent", true), - new TestCaseData("--debug-tests", "DebugTests", true), - // Options with values - using '=' as delimiter - new TestCaseData($"--agentId={AGENT_GUID}", "AgentId", AGENT_GUID), - new TestCaseData("--agencyUrl=THEURL", "AgencyUrl", "THEURL"), - new TestCaseData("--pid=1234", "AgencyPid", "1234"), - new TestCaseData("--trace=Info", "TraceLevel", InternalTraceLevel.Info), - new TestCaseData("--work=WORKDIR", "WorkDirectory", "WORKDIR"), - // Options with values - using ':' as delimiter - new TestCaseData("--trace:Error", "TraceLevel", InternalTraceLevel.Error), - new TestCaseData("--work:WORKDIR", "WorkDirectory", "WORKDIR"), - // Value with spaces (provided OS passes them through) - new TestCaseData("--work:MY WORK DIR", "WorkDirectory", "MY WORK DIR"), - }; - - [TestCaseSource(nameof(ValidSettings))] - public void ValidOptionSettings(string option, string propertyName, T expectedValue) - { - var options = new AgentOptions(option); - var prop = typeof(AgentOptions).GetProperty(propertyName); - Assert.That(prop, Is.Not.Null, $"Property {propertyName} does not exist"); - Assert.That(prop.GetValue(options, Array.Empty()), Is.EqualTo(expectedValue)); - } - - [Test] - public void MultipleOptions() - { - var options = new AgentOptions("--debug-tests", "--trace=Info", "--work", "MYWORKDIR"); - Assert.That(options.DebugAgent, Is.False); - Assert.That(options.DebugTests); - Assert.That(options.TraceLevel, Is.EqualTo(InternalTraceLevel.Info)); - Assert.That(options.WorkDirectory, Is.EqualTo("MYWORKDIR")); - } - - [Test] - public void FileNameSupplied() - { - var filename = GetType().Assembly.Location; - var options = new AgentOptions(filename); - Assert.That(options.Files.Count, Is.EqualTo(1)); - Assert.That(options.Files[0], Is.EqualTo(filename)); - } - } -} diff --git a/src/NUnitCommon/nunit.agent.core.tests/App.config b/src/NUnitCommon/nunit.agent.core.tests/App.config deleted file mode 100644 index 0529ebd07..000000000 --- a/src/NUnitCommon/nunit.agent.core.tests/App.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/src/NUnitCommon/nunit.agent.core.tests/Drivers/DriverServiceTests.cs b/src/NUnitCommon/nunit.agent.core.tests/Drivers/DriverServiceTests.cs deleted file mode 100644 index ed1f803b1..000000000 --- a/src/NUnitCommon/nunit.agent.core.tests/Drivers/DriverServiceTests.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using System; -using System.IO; -using NUnit.Framework; -using NUnit.Engine.Drivers; - -namespace NUnit.Engine.Services -{ - [TestFixture] - public class DriverServiceTests - { - private DriverService _driverService; - - [SetUp] - public void CreateDriverFactory() - { - _driverService = new DriverService(); - } - - [TestCaseSource(nameof(DriverSelectionTestCases))] - public void CorrectDriverIsUsed(string fileName, bool skipNonTestAssemblies, Type expectedType) - { - var assemblyPath = Path.Combine(TestContext.CurrentContext.TestDirectory, fileName); - var driver = _driverService.GetDriver(AppDomain.CurrentDomain, new TestPackage(assemblyPath), assemblyPath, null, skipNonTestAssemblies); - Assert.That(driver, Is.InstanceOf(expectedType)); - } - - private static TestCaseData[] DriverSelectionTestCases = new[] - { - new TestCaseData("mock-assembly.dll", false, typeof(NUnitFrameworkDriver)), - new TestCaseData("mock-assembly.dll", true, typeof(NUnitFrameworkDriver)), - new TestCaseData("notest-assembly.dll", false, typeof(NUnitFrameworkDriver)).Ignore("Assembly not present"), - }; - } -} diff --git a/src/NUnitCommon/nunit.agent.core.tests/Drivers/NUnit3DriverFactoryTests.cs b/src/NUnitCommon/nunit.agent.core.tests/Drivers/NUnit3DriverFactoryTests.cs deleted file mode 100644 index 3f892ea04..000000000 --- a/src/NUnitCommon/nunit.agent.core.tests/Drivers/NUnit3DriverFactoryTests.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using NUnit.Framework; -using System; -using System.Reflection; - -namespace NUnit.Engine.Drivers -{ - public class NUnit3DriverFactoryTests - { - private NUnit3DriverFactory _factory; - - [SetUp] - public void SetUp() - { - _factory = new NUnit3DriverFactory(); - } - - [TestCase(2, ExpectedResult = false)] - [TestCase(3, ExpectedResult = true)] - [TestCase(4, ExpectedResult = true)] - public bool SupportsNetFramework(int majorVersion) - { - AssemblyName name = new AssemblyName("nunit.framework") - { - Version = new Version(majorVersion, 0) - }; - - return _factory.IsSupportedTestFramework(name); - } - - [Test] - public void DoesNotSupportOtherFrameworks() - { - AssemblyName name = new AssemblyName("VSTest.dll") - { - Version = new Version(3, 0) - }; - - Assert.That(_factory.IsSupportedTestFramework(name), Is.False); - } - } -} diff --git a/src/NUnitCommon/nunit.agent.core.tests/Drivers/NUnitFrameworkDriverTests.cs b/src/NUnitCommon/nunit.agent.core.tests/Drivers/NUnitFrameworkDriverTests.cs deleted file mode 100644 index ef158a64f..000000000 --- a/src/NUnitCommon/nunit.agent.core.tests/Drivers/NUnitFrameworkDriverTests.cs +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using System; -using System.Collections.Generic; -using System.Reflection; -using NUnit.TestData.Assemblies; -using NUnit.Framework; -using NUnit.Framework.Internal; - -namespace NUnit.Engine.Drivers -{ - // Functional tests of the NUnitFrameworkDriver calling into the framework. -#if NETFRAMEWORK - [TestFixture("2009")] -#endif - [TestFixture("2018")] - public class NUnitFrameworkDriverTests - { - private const string MOCK_ASSEMBLY = "mock-assembly.dll"; - private const string LOAD_MESSAGE = "Method called without calling Load first. Possible error in runner."; - - private IDictionary _settings = new Dictionary(); - - private NUnitFrameworkDriver _driver; - private string _mockAssemblyPath; - - private string _whichApi; - public NUnitFrameworkDriverTests(string whichApi) - { - _whichApi = whichApi; - } - - [SetUp] - public void CreateDriver() - { - var nunitRef = typeof(TestAttribute).Assembly.GetName(); - _mockAssemblyPath = System.IO.Path.Combine(TestContext.CurrentContext.TestDirectory, MOCK_ASSEMBLY); - -#if NETFRAMEWORK - _driver = new NUnitFrameworkDriver(AppDomain.CurrentDomain, _whichApi, "99", nunitRef); -#else - _driver = new NUnitFrameworkDriver("99", nunitRef); -#endif - } - - [Test] - public void Load_GoodFile_ReturnsRunnableSuite() - { - var result = XmlHelper.CreateXmlNode(_driver.Load(_mockAssemblyPath, _settings)); - - Assert.That(result.Name, Is.EqualTo("test-suite")); - Assert.That(result.GetAttribute("type"), Is.EqualTo("Assembly")); - Assert.That(result.GetAttribute("runstate"), Is.EqualTo("Runnable")); - Assert.That(result.GetAttribute("testcasecount"), Is.EqualTo(MockAssembly.Tests.ToString())); - Assert.That(result.SelectNodes("test-suite")?.Count, Is.EqualTo(0), "Load result should not have child tests"); - } - - [Test] - public void Explore_AfterLoad_ReturnsRunnableSuite() - { - _driver.Load(_mockAssemblyPath, _settings); - var result = XmlHelper.CreateXmlNode(_driver.Explore(TestFilter.Empty.Text)); - - Assert.That(result.Name, Is.EqualTo("test-suite")); - Assert.That(result.GetAttribute("type"), Is.EqualTo("Assembly")); - Assert.That(result.GetAttribute("runstate"), Is.EqualTo("Runnable")); - Assert.That(result.GetAttribute("testcasecount"), Is.EqualTo(MockAssembly.Tests.ToString())); - Assert.That(result.SelectNodes("test-suite")?.Count, Is.GreaterThan(0), "Explore result should have child tests"); - } - - [Test] - public void ExploreTestsAction_WithoutLoad_ThrowsInvalidOperationException() - { - var ex = Assert.Catch(() => _driver.Explore(TestFilter.Empty.Text)); - if (ex is System.Reflection.TargetInvocationException) - ex = ex.InnerException; - Assert.That(ex, Is.TypeOf()); - Assert.That(ex.Message, Is.EqualTo(LOAD_MESSAGE)); - } - - [Test] - public void CountTestsAction_AfterLoad_ReturnsCorrectCount() - { - _driver.Load(_mockAssemblyPath, _settings); - Assert.That(_driver.CountTestCases(TestFilter.Empty.Text), Is.EqualTo(MockAssembly.Tests)); - } - - [Test] - public void CountTestsAction_WithoutLoad_ThrowsInvalidOperationException() - { - var ex = Assert.Catch(() => _driver.CountTestCases(TestFilter.Empty.Text)); - if (ex is System.Reflection.TargetInvocationException) - ex = ex.InnerException; - Assert.That(ex, Is.TypeOf()); - Assert.That(ex.Message, Is.EqualTo(LOAD_MESSAGE)); - } - - [Test] - public void RunTestsAction_AfterLoad_ReturnsRunnableSuite() - { - _driver.Load(_mockAssemblyPath, _settings); - var result = XmlHelper.CreateXmlNode(_driver.Run(null, TestFilter.Empty.Text)); - - Assert.That(result.Name, Is.EqualTo("test-suite")); - Assert.That(result.GetAttribute("type"), Is.EqualTo("Assembly")); - Assert.That(result.GetAttribute("runstate"), Is.EqualTo("Runnable")); - Assert.That(result.GetAttribute("testcasecount", 0), Is.EqualTo(MockAssembly.Tests)); - Assert.That(result.GetAttribute("result"), Is.EqualTo("Failed")); - Assert.That(result.GetAttribute("passed", 0), Is.EqualTo(MockAssembly.Passed_Raw)); - Assert.That(result.GetAttribute("failed", 0), Is.EqualTo(MockAssembly.Failed_Raw)); - Assert.That(result.GetAttribute("skipped", 0), Is.EqualTo(MockAssembly.Skipped)); - Assert.That(result.GetAttribute("inconclusive", 0), Is.EqualTo(MockAssembly.Inconclusive)); - Assert.That(result.SelectNodes("test-suite")?.Count, Is.GreaterThan(0), "Explore result should have child tests"); - } - - [Test] - public void RunTestsAction_WithoutLoad_ThrowsInvalidOperationException() - { - var ex = Assert.Catch(() => _driver.Run(null, TestFilter.Empty.Text)); - Assert.That(ex, Is.TypeOf()); - Assert.That(ex.Message, Is.EqualTo(LOAD_MESSAGE)); - } - - [Test] - public void RunTestsAction_WithInvalidFilterElement_ThrowsException() - { - _driver.Load(_mockAssemblyPath, _settings); - - var invalidFilter = "foo"; - var ex = Assert.Catch(() => _driver.Run(null, invalidFilter)); - - if (_whichApi == "2018") - { - Assert.That(ex, Is.TypeOf()); - Assert.That(ex.InnerException, Is.TypeOf()); - } - else - Assert.That(ex, Is.TypeOf()); - } - -#if NETFRAMEWORK - // Nested Class tests Api Selection in the driver - public class ApiSelectionTests() - { - [TestCase("4.2.2", "2018")] - [TestCase("3.14.0", "2018")] - [TestCase("3.2.0", "2018")] - [TestCase("3.0.1", "2009")] - [TestCase("3.0.0", "2009")] - public void CorrectApiIsSelected(string nunitVersion, string apiVersion) - { - var driver = new NUnitFrameworkDriver(AppDomain.CurrentDomain, "99", new AssemblyName() - { - Name = "nunit.framework", - Version = new Version(nunitVersion) - }); - - Assert.That(driver.API, Is.EqualTo(apiVersion)); - } - } - - private class CallbackEventHandler : System.Web.UI.ICallbackEventHandler - { - private string? _result; - - public string? GetCallbackResult() - { - return _result; - } - - public void RaiseCallbackEvent(string eventArgument) - { - _result = eventArgument; - } - } -#endif - } -} diff --git a/src/NUnitCommon/nunit.agent.core.tests/Program.cs b/src/NUnitCommon/nunit.agent.core.tests/Program.cs deleted file mode 100644 index 559c7607d..000000000 --- a/src/NUnitCommon/nunit.agent.core.tests/Program.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using NUnitLite; - -namespace NUnit.Engine.Tests -{ - public class Program - { - public static int Main(string[] args) - { - return new TextRunner(typeof(Program).Assembly).Execute(args); - } - } -} diff --git a/src/NUnitCommon/nunit.agent.core.tests/Runners/DomainManagerStaticTests.cs b/src/NUnitCommon/nunit.agent.core.tests/Runners/DomainManagerStaticTests.cs deleted file mode 100644 index 4bba7de15..000000000 --- a/src/NUnitCommon/nunit.agent.core.tests/Runners/DomainManagerStaticTests.cs +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -#if NETFRAMEWORK -using System; -using System.Collections.Generic; -using System.Configuration; -using System.Diagnostics.CodeAnalysis; -using System.IO; -using NUnit.Common; -using NUnit.Framework; - -namespace NUnit.Engine.Runners -{ - public static class DomainManagerStaticTests - { - private static string path1 = TestPath("/test/bin/debug/test1.dll"); - private static string path2 = TestPath("/test/bin/debug/test2.dll"); - private static string path3 = TestPath("/test/utils/test3.dll"); - - private const string STANDARD_CONFIG_FILE = "nunit.agent.core.tests.exe.config"; - private const string ALTERNATE_CONFIG_FILE = "alt.config"; - - [Test] - public static void GetPrivateBinPath() - { - string[] assemblies = new string[] { path1, path2, path3 }; - - Assert.That(DomainManager.GetPrivateBinPath(TestPath("/test"), assemblies), Is.EqualTo(TestPath("bin/debug") + Path.PathSeparator + TestPath("utils"))); - } - - [Test] - public static void GetCommonAppBase_OneElement() - { - string[] assemblies = new string[] { path1 }; - - Assert.That(DomainManager.GetCommonAppBase(assemblies), Is.EqualTo(TestPath("/test/bin/debug"))); - } - - [Test] - public static void GetCommonAppBase_TwoElements_SameDirectory() - { - string[] assemblies = new string[] { path1, path2 }; - - Assert.That(DomainManager.GetCommonAppBase(assemblies), Is.EqualTo(TestPath("/test/bin/debug"))); - } - - [Test] - public static void GetCommonAppBase_TwoElements_DifferentDirectories() - { - string[] assemblies = new string[] { path1, path3 }; - - Assert.That(DomainManager.GetCommonAppBase(assemblies), Is.EqualTo(TestPath("/test"))); - } - - [Test] - public static void GetCommonAppBase_ThreeElements_DifferentDirectories() - { - string[] assemblies = new string[] { path1, path2, path3 }; - - Assert.That(DomainManager.GetCommonAppBase(assemblies), Is.EqualTo(TestPath("/test"))); - } - - [Test] - public static void ProperConfigFileIsUsed() - { - // NOTE: The alternate config file, alt.config, is copied to the bin directory and - // may be specified from the command-line, using --configfile=alt.config. This allows - // manual testing of the option while permitting this test to still pass. - var expectedPath = Path.Combine(TestContext.CurrentContext.TestDirectory, STANDARD_CONFIG_FILE); - var alternatePath = Path.Combine(TestContext.CurrentContext.TestDirectory, ALTERNATE_CONFIG_FILE); - Assert.That(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile, Is.SamePath(expectedPath).Or.SamePath(alternatePath)); - } - - [Test] - public static void CanReadConfigFile() - { - // NOTE: The alternate config file has a different value so we can see it being used - var expectedSetting = Path.GetFileName(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile) == ALTERNATE_CONFIG_FILE - ? "Alternate config used" - : "54321"; - Assert.That(ConfigurationManager.AppSettings.Get("test.setting"), Is.EqualTo(expectedSetting)); - } - - [TestCase("/path/to/mytest.dll", null, "/path/to/")] - [TestCase("/path/to/mytest.dll", "/path", "/path/")] - public static void ApplicationBaseTests(string filePath, string? appBase, string expected) - { - filePath = TestPath(filePath); - appBase = TestPath(appBase); - expected = TestPath(expected); - - var package = new TestPackage(filePath); - if (appBase is not null) - package.Settings.Add(SettingDefinitions.BasePath.WithValue(appBase)); - - Assert.That(DomainManager.GetApplicationBase(package), Is.SamePath(expected)); - } - - [TestCase("/path/to/mytest.dll", "/path/to", null)] - [TestCase("/path/to/mytest.dll", "/path", "to")] - public static void PrivateBinPathTests(string filePath, string appBase, string? expected) - { - filePath = TestPath(filePath); - appBase = TestPath(appBase); - expected = TestPath(expected); - - var package = new TestPackage(filePath); - - Assert.That(DomainManager.GetPrivateBinPath(appBase, package), Is.EqualTo(expected)); - } - - [TestCase("/path/to/mytest.dll", "/path/to", null, "/path/to/mytest.dll.config")] - [TestCase("/path/to/mytest.dll", "/path", null, "/path/to/mytest.dll.config")] - [TestCase("/path/to/mytest.nunit", "/path/to", null, null)] - [TestCase("/path/to/mytest.nunit", "/path/to", "/path/to/mytest.config", "/path/to/mytest.config")] - public static void ConfigFileTests(string filePath, string appBase, string? configSetting, string? expected) - { - filePath = TestPath(filePath); - appBase = TestPath(appBase); - configSetting = TestPath(configSetting); - expected = TestPath(expected); - - var package = new TestPackage(filePath); - if (configSetting is not null) - package.Settings.Add(SettingDefinitions.ConfigurationFile.WithValue(configSetting)); - - Assert.That(DomainManager.GetConfigFile(appBase, package), Is.EqualTo(expected)); - } - - /// - /// Take a valid Linux filePath and make a valid windows filePath out of it - /// if we are on Windows. Change slashes to backslashes and, if the - /// filePath starts with a slash, add C: in front of it. - /// - [return: NotNullIfNotNull(nameof(path))] - private static string? TestPath(string? path) - { - if (path is not null && Path.DirectorySeparatorChar != '/') - { - path = path.Replace('/', Path.DirectorySeparatorChar); - if (path[0] == Path.DirectorySeparatorChar) - path = "C:" + path; - } - - return path; - } - - private static IEnumerable AppDomainData() - { - yield return new TestCaseData(new TestPackage(@"C:\path\to\mytest.dll"), @"C:\path\to"); - } - } -} -#endif \ No newline at end of file diff --git a/src/NUnitCommon/nunit.agent.core.tests/Runners/DomainManagerTests.cs b/src/NUnitCommon/nunit.agent.core.tests/Runners/DomainManagerTests.cs deleted file mode 100644 index 705a5d15c..000000000 --- a/src/NUnitCommon/nunit.agent.core.tests/Runners/DomainManagerTests.cs +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -#if NETFRAMEWORK -using System; -using System.IO; -using NUnit.Framework; -using NUnit.Common; - -namespace NUnit.Engine.Runners -{ - public class DomainManagerTests - { - private const string DUMMY_ASSEMBLY = "test.dll"; - private static readonly string DUMMY_ASSEMBLY_PATH = Environment.OSVersion.Platform == PlatformID.Win32NT - ? @"C:\A\B\C\" - : "/A/B/C/"; - - private DomainManager _domainManager; - // We use a sub-package, because that's what DomainManager normally gets - private TestPackage _package = new TestPackage(DUMMY_ASSEMBLY_PATH + DUMMY_ASSEMBLY).SubPackages[0]; - - [SetUp] - public void CreateDomainManager() - { - _domainManager = new DomainManager(); - } - - [Test, Platform("Linux,Net", Reason = "get_SetupInformation() fails on Windows+Mono")] - public void CanCreateDomain() - { - var domain = _domainManager.CreateDomain(_package); - - Assert.That(domain, Is.Not.Null); - var setup = domain.SetupInformation; - - Assert.That(setup.ApplicationName, Does.StartWith("Tests_")); - Assert.That(setup.ApplicationBase, Is.SamePath(DUMMY_ASSEMBLY_PATH), "ApplicationBase"); - Assert.That( - Path.GetFileName(setup.ConfigurationFile), - Is.EqualTo(DUMMY_ASSEMBLY + ".config").IgnoreCase, - "ConfigurationFile"); - Assert.That(setup.PrivateBinPath, Is.EqualTo(null), "PrivateBinPath"); - Assert.That(setup.ShadowCopyFiles, Is.Null.Or.EqualTo("false")); - //Assert.That(setup.ShadowCopyDirectories, Is.SamePath(DUMMY_ASSEMBLY_PATH), "ShadowCopyDirectories" ); - } - - [Test, Platform("Linux,Net", Reason = "get_SetupInformation() fails on Windows+Mono")] - public void CanCreateDomainWithApplicationBaseSpecified() - { - string assemblyDir = Path.GetDirectoryName(_package.FullName)!; - string basePath = Path.GetDirectoryName(Path.GetDirectoryName(assemblyDir))!; - string relPath = assemblyDir.Substring(basePath.Length + 1); - - _package.Settings.Add(SettingDefinitions.BasePath.WithValue(basePath)); - var domain = _domainManager.CreateDomain(_package); - - Assert.That(domain, Is.Not.Null); - var setup = domain.SetupInformation; - - Assert.That(setup.ApplicationName, Does.StartWith("Tests_")); - Assert.That(setup.ApplicationBase, Is.SamePath(basePath), "ApplicationBase"); - Assert.That( - Path.GetFileName(setup.ConfigurationFile), - Is.EqualTo(DUMMY_ASSEMBLY + ".config").IgnoreCase, - "ConfigurationFile"); - Assert.That(setup.PrivateBinPath, Is.SamePath(relPath), "PrivateBinPath"); - Assert.That(setup.ShadowCopyFiles, Is.Null.Or.EqualTo("false")); - } - - [Test] - public void CanUnloadDomain() - { - var domain = _domainManager.CreateDomain(_package); - DomainManager.Unload(domain); - - CheckDomainIsUnloaded(domain); - } - - [Test] - public void UnloadingTwiceThrowsNUnitEngineUnloadException() - { - var domain = _domainManager.CreateDomain(_package); - DomainManager.Unload(domain); - - Assert.That(() => DomainManager.Unload(domain), Throws.TypeOf()); - - CheckDomainIsUnloaded(domain); - } - - private static void CheckDomainIsUnloaded(AppDomain domain) - { - // HACK: Either the Assert will succeed or the - // exception should be thrown. - bool unloaded = false; - - try - { - unloaded = domain.IsFinalizingForUnload(); - } - catch (AppDomainUnloadedException) - { - unloaded = true; - } - - Assert.That(unloaded, Is.True, "Domain was not unloaded"); - } - } -} -#endif \ No newline at end of file diff --git a/src/NUnitCommon/nunit.agent.core.tests/Runners/FakeTestAgentRunner.cs b/src/NUnitCommon/nunit.agent.core.tests/Runners/FakeTestAgentRunner.cs deleted file mode 100644 index c7fe16621..000000000 --- a/src/NUnitCommon/nunit.agent.core.tests/Runners/FakeTestAgentRunner.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using NUnit.Engine.Drivers; -using System; - -namespace NUnit.Engine.Runners -{ - internal class FakeTestAgentRunner : TestAgentRunner - { - public FakeTestAgentRunner(TestPackage package, IDriverService? driverService = null) : base(package) - { - TestDomain = AppDomain.CurrentDomain; - DriverService = driverService; - } - - public new void Load() - { - base.Load(); - } - } -} diff --git a/src/NUnitCommon/nunit.agent.core.tests/Runners/TestAgentRunnerExceptionTests.cs b/src/NUnitCommon/nunit.agent.core.tests/Runners/TestAgentRunnerExceptionTests.cs deleted file mode 100644 index b932d0196..000000000 --- a/src/NUnitCommon/nunit.agent.core.tests/Runners/TestAgentRunnerExceptionTests.cs +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using System; -using System.Collections.Generic; -using NSubstitute; -using NSubstitute.ExceptionExtensions; -using NUnit.Engine.Extensibility; -using NUnit.Framework; - -namespace NUnit.Engine.Runners -{ - public class TestAgentRunnerExceptionTests - { - private IFrameworkDriver _driver; - private FakeTestAgentRunner _runner; - private readonly TestFilter _testFilter = new TestFilter(string.Empty); - - [SetUp] - public void Initialize() - { - _driver = Substitute.For(); - var driverService = Substitute.For(); - driverService.GetDriver( - AppDomain.CurrentDomain, - new TestPackage(), - string.Empty, - string.Empty, - false).ReturnsForAnyArgs(_driver); - - _runner = new FakeTestAgentRunner(new TestPackage("mock-assembly.dll").SubPackages[0], driverService); - } - - [TearDown] - public void Cleanup() - { - _runner.Dispose(); - } - - [Test] - public void Explore_Passes_Along_NUnitEngineException() - { - _driver.Explore(Arg.Any()).Throws(new NUnitEngineException("Message")); - var ex = Assert.Throws(() => _runner.Explore(new TestFilter(string.Empty))); - Assert.That(ex.Message, Is.EqualTo("Message")); - } - - [Test] - public void Explore_Throws_NUnitEngineException() - { - _driver.Explore(Arg.Any()).Throws(new ArgumentException("Message")); - var ex = Assert.Throws(() => _runner.Explore(new TestFilter(string.Empty))); - Assert.That(ex.InnerException, Is.Not.Null); - Assert.That(ex.InnerException, Is.InstanceOf()); - Assert.That(ex.InnerException.Message, Is.EqualTo("Message")); - } - - [Test] - public void Load_Passes_Along_NUnitEngineException() - { - _driver.Load(Arg.Any(), Arg.Any>()).Throws(new NUnitEngineException("Message")); - var ex = Assert.Throws(() => _runner.Load()); - Assert.That(ex.Message, Is.EqualTo("Message")); - } - - [Test] - public void Load_Throws_NUnitEngineException() - { - _driver.Load(Arg.Any(), Arg.Any>()).Throws(new ArgumentException("Message")); - var ex = Assert.Throws(() => _runner.Load()); - Assert.That(ex.InnerException, Is.Not.Null); - Assert.That(ex.InnerException, Is.InstanceOf()); - Assert.That(ex.InnerException.Message, Is.EqualTo("Message")); - } - - [Test] - public void CountTestCases_Passes_Along_NUnitEngineException() - { - _driver.CountTestCases(Arg.Any()).Throws(new NUnitEngineException("Message")); - var ex = Assert.Throws(() => _runner.CountTestCases(_testFilter)); - Assert.That(ex.Message, Is.EqualTo("Message")); - } - - [Test] - public void CountTestCases_Throws_NUnitEngineException() - { - _driver.CountTestCases(Arg.Any()).Throws(new ArgumentException("Message")); - var ex = Assert.Throws(() => _runner.CountTestCases(_testFilter)); - Assert.That(ex.InnerException, Is.Not.Null); - Assert.That(ex.InnerException, Is.InstanceOf()); - Assert.That(ex.InnerException.Message, Is.EqualTo("Message")); - } - - [Test] - public void Run_Passes_Along_NUnitEngineException() - { - _driver.Run(Arg.Any(), Arg.Any()).Throws(new NUnitEngineException("Message")); - var ex = Assert.Throws(() => _runner.Run(Substitute.For(), _testFilter)); - Assert.That(ex.Message, Is.EqualTo("Message")); - } - - [Test] - public void Run_Throws_NUnitEngineException() - { - _driver.Run(Arg.Any(), Arg.Any()).Throws(new ArgumentException("Message")); - var ex = Assert.Throws(() => _runner.Run(Substitute.For(), _testFilter)); - Assert.That(ex.InnerException, Is.Not.Null); - Assert.That(ex.InnerException, Is.InstanceOf()); - Assert.That(ex.InnerException.Message, Is.EqualTo("Message")); - } - - [Test] - public void StopRun_Passes_Along_NUnitEngineException() - { - _driver.When(x => x.ForcedStop()) - .Do(x => { throw new NUnitEngineException("Message"); }); - - var ex = Assert.Throws(() => _runner.ForcedStop()); - Assert.That(ex?.Message, Is.EqualTo("Message")); - } - } -} diff --git a/src/NUnitCommon/nunit.agent.core.tests/Runners/TestAgentRunnerTests.cs b/src/NUnitCommon/nunit.agent.core.tests/Runners/TestAgentRunnerTests.cs deleted file mode 100644 index 4b5285018..000000000 --- a/src/NUnitCommon/nunit.agent.core.tests/Runners/TestAgentRunnerTests.cs +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using System; -using System.IO; -using NUnit.Common; -using NUnit.Framework; -using NUnit.Framework.Internal; -using NUnit.TestData.Assemblies; - -namespace NUnit.Engine.Runners -{ - [TestFixture(typeof(LocalTestRunner))] -#if NETFRAMEWORK - [TestFixture(typeof(TestDomainRunner))] -#endif - public class TestAgentRunnerTests : ITestEventListener - where TRunner : TestAgentRunner - { - protected TestPackage _package; - protected TRunner _runner; - - [SetUp] - public void Initialize() - { - var mockAssemblyPath = Path.Combine(TestContext.CurrentContext.TestDirectory, "mock-assembly.dll"); - - _package = new TestPackage(mockAssemblyPath).SubPackages[0]; - - _runner = (TRunner)Activator.CreateInstance(typeof(TRunner), _package)!; - } - - [TearDown] - public void Cleanup() - { - if (_runner is not null) - _runner.Dispose(); - } - - [Test] - public void Load() - { - var result = _runner.Load(); - CheckLoadResult(result); - } - -#if NETCOREAPP3_1_OR_GREATER - [Test] - public void ListResolutionStats() - { - _package.AddSetting(SettingDefinitions.ListResolutionStats.WithValue(true)); - var result = _runner.Load(); - CheckLoadResult(result); - } -#endif - - [Test] - public void CountTestCases() - { - int count = _runner.CountTestCases(TestFilter.Empty); - Assert.That(_runner.IsPackageLoaded, "Package was not loaded automatically"); - Assert.That(count, Is.EqualTo(MockAssembly.Tests)); - } - - [Test] - public void Explore() - { - var result = _runner.Explore(TestFilter.Empty); - CheckLoadResult(result); - } - - [Test] - public void Run() - { - var result = _runner.Run(null, TestFilter.Empty); - CheckRunResult(result); - } - - //[Test] - public void RunAsync() - { - var asyncResult = _runner.RunAsync(null, TestFilter.Empty); - asyncResult.Wait(-1); - Assert.That(asyncResult.IsComplete, "Async result is not complete"); - - CheckRunResult(asyncResult.EngineResult); - } - - private void CheckLoadResult(TestEngineResult result) - { - Assert.That(_runner.IsPackageLoaded, "Package was not loaded automatically"); - Assert.That(result.IsSingle); - var node = result.XmlNodes[0]; - Assert.That(node.Name, Is.EqualTo("test-suite")); - Assert.That(node.GetAttribute("type"), Is.EqualTo("Assembly")); - Assert.That(node.GetAttribute("testcasecount", 0), Is.EqualTo(MockAssembly.Tests)); - Assert.That(node.GetAttribute("runstate"), Is.EqualTo("Runnable")); - } - - private void CheckRunResult(TestEngineResult result) - { - CheckLoadResult(result); - var node = result.XmlNodes[0]; - Assert.That(node.GetAttribute("passed", 0), Is.EqualTo(MockAssembly.Passed_Raw)); - Assert.That(node.GetAttribute("failed", 0), Is.EqualTo(MockAssembly.Failed_Raw)); - Assert.That(node.GetAttribute("skipped", 0), Is.EqualTo(MockAssembly.Skipped)); - Assert.That(node.GetAttribute("inconclusive", 0), Is.EqualTo(MockAssembly.Inconclusive)); - } - - public void OnTestEvent(string report) - { - // Do nothing - } - } -} diff --git a/src/NUnitCommon/nunit.agent.core.tests/alt.config b/src/NUnitCommon/nunit.agent.core.tests/alt.config deleted file mode 100644 index 542674047..000000000 --- a/src/NUnitCommon/nunit.agent.core.tests/alt.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/src/NUnitCommon/nunit.agent.core.tests/nunit.agent.core.tests.csproj b/src/NUnitCommon/nunit.agent.core.tests/nunit.agent.core.tests.csproj deleted file mode 100644 index 2d0807edc..000000000 --- a/src/NUnitCommon/nunit.agent.core.tests/nunit.agent.core.tests.csproj +++ /dev/null @@ -1,28 +0,0 @@ - - - - net462;net8.0 - Exe - true - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/NUnitCommon/nunit.agent.core/AgentDirectRunner.cs b/src/NUnitCommon/nunit.agent.core/AgentDirectRunner.cs deleted file mode 100644 index b434fa04f..000000000 --- a/src/NUnitCommon/nunit.agent.core/AgentDirectRunner.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using System; -using System.IO; -using System.Xml; -using NUnit.TextDisplay; -using NUnit.Common; -using NUnit.Engine; -using NUnit.Engine.Runners; - -namespace NUnit.Agents -{ - public class AgentDirectRunner - { - private static Logger log = InternalTrace.GetLogger(typeof(AgentDirectRunner)); - private AgentOptions _options; - - private ColorConsoleWriter OutWriter { get; } = new ColorConsoleWriter(); - - public AgentDirectRunner(AgentOptions options) - { - _options = options; - } - - public void ExecuteTestsDirectly() - { - try - { - var testFile = _options.Files[0]; - - ResultReporter.WriteHeader(OutWriter); - - TestPackage package = new TestPackage(testFile).SubPackages[0]; - -#if NETFRAMEWORK - var runner = new TestDomainRunner(package); -#else - var runner = new LocalTestRunner(package); -#endif - var xmlResult = runner.Run(null, TestFilter.Empty).Xml; - var summary = new ResultSummary(xmlResult); - - new ResultReporter().ReportResults(summary, OutWriter); - - var pathToResultFile = Path.Combine(_options.WorkDirectory, "TestResult.xml"); - WriteResultFile(xmlResult, pathToResultFile); - OutWriter.WriteLine($"Saved result file as {pathToResultFile}"); - } - catch (Exception ex) - { - log.Error(ex.ToString()); - Environment.Exit(AgentExitCodes.UNEXPECTED_EXCEPTION); - } - - Environment.Exit(AgentExitCodes.OK); - } - - public static void WriteResultFile(XmlNode resultNode, string outputPath) - { - using (var stream = new FileStream(outputPath, FileMode.Create, FileAccess.Write)) - using (var writer = new StreamWriter(stream)) - { - WriteResultFile(resultNode, writer); - } - } - - public static void WriteResultFile(XmlNode resultNode, TextWriter writer) - { - var settings = new XmlWriterSettings(); - settings.Indent = true; - - using (XmlWriter xmlWriter = XmlWriter.Create(writer, settings)) - { - xmlWriter.WriteStartDocument(false); - resultNode.WriteTo(xmlWriter); - } - } - } -} diff --git a/src/NUnitCommon/nunit.agent.core/AgentOptions.cs b/src/NUnitCommon/nunit.agent.core/AgentOptions.cs deleted file mode 100644 index 8a879edcd..000000000 --- a/src/NUnitCommon/nunit.agent.core/AgentOptions.cs +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using NUnit.Engine; -using System; -using System.Collections.Generic; -using System.IO; - -namespace NUnit.Agents -{ - /// - /// All agents, either built-in or pluggable, must be able to - /// handle the options defined in this class. In some cases, - /// it may be permissible to ignore them but they should never - /// give rise to an error. - /// - public class AgentOptions - { - private static readonly char[] DELIMS = new[] { '=', ':' }; - // Dictionary containing valid options with bool value true if a value is required. - private static readonly Dictionary VALID_OPTIONS = new Dictionary(); - - static AgentOptions() - { - VALID_OPTIONS["agentId"] = true; - VALID_OPTIONS["agencyUrl"] = true; - VALID_OPTIONS["debug-agent"] = false; - VALID_OPTIONS["debug-tests"] = false; - VALID_OPTIONS["trace"] = true; - VALID_OPTIONS["pid"] = true; - VALID_OPTIONS["work"] = true; - } - - public AgentOptions(params string[] args) - { - int index; - for (index = 0; index < args.Length; index++) - { - string arg = args[index]; - - if (IsOption(arg)) - { - var option = arg.Substring(2); - var delim = option.IndexOfAny(DELIMS); - var opt = option; - string? val = null; - if (delim > 0) - { - opt = option.Substring(0, delim); - val = option.Substring(delim + 1); - } - - // Simultaneously check that the option is valid and determine if it takes an argument - if (!VALID_OPTIONS.TryGetValue(opt, out bool optionTakesValue)) - throw new Exception($"Invalid argument: {arg}"); - - if (optionTakesValue) - { - if (val is null && index + 1 < args.Length) - val = args[++index]; - - if (val is null) - throw new Exception($"Option requires a value: {arg}"); - } - else if (delim > 0) - { - throw new Exception($"Option does not take a value: {arg}"); - } - - if (opt == "agentId") - AgentId = new Guid(GetArgumentValue(arg)); - else if (opt == "agencyUrl") - AgencyUrl = GetArgumentValue(arg); - else if (opt == "debug-agent") - DebugAgent = true; - else if (opt == "debug-tests") - DebugTests = true; - else if (opt == "trace") - TraceLevel = (InternalTraceLevel)Enum.Parse(typeof(InternalTraceLevel), val.ShouldNotBeNull()); - else if (opt == "pid") - AgencyPid = val.ShouldNotBeNull(); - else if (opt == "work") - WorkDirectory = val.ShouldNotBeNull(); - else - throw new Exception($"Invalid argument: {arg}"); - } - else if (File.Exists(arg)) - Files.Add(arg); - else - throw new FileNotFoundException($"FileNotFound: {arg}"); - } - - if (Files.Count > 1) - throw new ArgumentException($"Only one file argument is allowed but {Files.Count} were supplied"); - - string GetArgumentValue(string argument) - { - var delim = argument.IndexOfAny(DELIMS); - - if (delim > 0) - return argument.Substring(delim + 1); - - if (index + 1 < args.Length) - return args[++index]; - - throw new Exception($"Option requires a value: {argument}"); - } - } - - public Guid AgentId { get; } = Guid.Empty; - public string AgencyUrl { get; } = string.Empty; - public string AgencyPid { get; } = string.Empty; - public bool DebugTests { get; } = false; - public bool DebugAgent { get; } = false; - public InternalTraceLevel TraceLevel { get; } = InternalTraceLevel.Off; - public string WorkDirectory { get; } = string.Empty; - - public List Files { get; } = new List(); - - private static bool IsOption(string arg) - { - return arg.StartsWith("--", StringComparison.Ordinal); - } - } -} diff --git a/src/NUnitCommon/nunit.agent.core/Agents/LocalProcessAgentLauncher.cs b/src/NUnitCommon/nunit.agent.core/Agents/LocalProcessAgentLauncher.cs deleted file mode 100644 index a00c0769b..000000000 --- a/src/NUnitCommon/nunit.agent.core/Agents/LocalProcessAgentLauncher.cs +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -#if NETFRAMEWORK -using NUnit.Engine.Extensibility; -using System; -using System.Diagnostics; -using System.Runtime.Versioning; -using System.Text; -using NUnit.Common; -using System.IO; - -namespace NUnit.Engine.Agents -{ - public abstract class LocalProcessAgentLauncher : IAgentLauncher - { - protected abstract string AgentName { get; } - protected abstract TestAgentType AgentType { get; } - protected abstract FrameworkName AgentRuntime { get; } - - protected abstract string AgentPath { get; } - - // Override if the agent path for X86 is different - protected virtual string X86AgentPath => AgentPath; - - public TestAgentInfo AgentInfo => new TestAgentInfo(AgentName, TestAgentType.LocalProcess, AgentRuntime); - - public bool CanCreateAgent(TestPackage package) - { - // Get target runtime from package - string runtimeSetting = package.Settings.GetValueOrDefault(SettingDefinitions.TargetFrameworkName); - var targetRuntime = new FrameworkName(runtimeSetting); - bool runAsX86 = package.Settings.GetValueOrDefault(SettingDefinitions.RunAsX86); - - // Running under X86 under .NET Core is currently only supported on Windows - if (runAsX86 && targetRuntime.Identifier == FrameworkIdentifiers.NetCoreApp && Path.DirectorySeparatorChar != '\\') - return false; - - return targetRuntime.Identifier == AgentRuntime.Identifier && targetRuntime.Version.Major <= AgentRuntime.Version.Major; - } - - public Process CreateAgent(Guid agentId, string agencyUrl, TestPackage package) - { - // Should not be called unless we have previously checked CanCreateAgent - Guard.ArgumentValid(CanCreateAgent(package), "Unable to create agent. Check result of CanCreateAgent before calling CreateAgent.", nameof(package)); - - var process = new Process() - { - EnableRaisingEvents = true - }; - - // Access package settings - var settings = package.Settings; - bool runAsX86 = settings.GetValueOrDefault(SettingDefinitions.RunAsX86); - bool debugTests = settings.GetValueOrDefault(SettingDefinitions.DebugTests); - bool debugAgent = settings.GetValueOrDefault(SettingDefinitions.DebugAgent); - string traceLevel = settings.GetValueOrDefault(SettingDefinitions.InternalTraceLevel); - bool loadUserProfile = settings.GetValueOrDefault(SettingDefinitions.LoadUserProfile); - string workDirectory = settings.GetValueOrDefault(SettingDefinitions.WorkDirectory); - - var sb = new StringBuilder($"--agentId={agentId} --agencyUrl={agencyUrl} --pid={Process.GetCurrentProcess().Id}"); - - // Set options that need to be in effect before the package - // is loaded by using the command line. - if (traceLevel != "Off") - sb.Append(" --trace=").EscapeProcessArgument(traceLevel); - if (debugAgent) - sb.Append(" --debug-agent"); - if (debugTests) - sb.Append(" --debug-tests"); - if (workDirectory != string.Empty) - sb.Append(" --work=").EscapeProcessArgument(workDirectory); - - string arguments = sb.ToString(); - - var startInfo = process.StartInfo; - startInfo.UseShellExecute = false; - startInfo.CreateNoWindow = true; - startInfo.WorkingDirectory = Environment.CurrentDirectory; - startInfo.LoadUserProfile = loadUserProfile; - - startInfo.FileName = runAsX86 ? X86AgentPath : AgentPath; - startInfo.Arguments = arguments; - - if (AgentRuntime.Identifier == FrameworkIdentifiers.NetCoreApp) - { - startInfo.FileName = DotNet.GetDotnetExecutable(runAsX86); - startInfo.Arguments = $"\"{AgentPath}\" {arguments}"; - } - - return process; - } - } -} -#endif diff --git a/src/NUnitCommon/nunit.agent.core/Agents/RemoteTestAgent.cs b/src/NUnitCommon/nunit.agent.core/Agents/RemoteTestAgent.cs deleted file mode 100644 index 321b03deb..000000000 --- a/src/NUnitCommon/nunit.agent.core/Agents/RemoteTestAgent.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using System; -using NUnit.Engine.Communication.Transports; -using NUnit.Engine.Runners; - -namespace NUnit.Engine.Agents -{ - /// - /// RemoteTestAgent represents a remote agent executing in another process - /// and communicating with NUnit by TCP. Although it is similar to a - /// TestServer, it does not publish a Uri at which clients may connect - /// to it. Rather, it reports back to the sponsoring TestAgency upon - /// startup so that the agency may in turn provide it to clients for use. - /// - public class RemoteTestAgent : TestAgent - { - /// - /// Construct a RemoteTestAgent - /// - /// - /// The first argument is a temporary measure and will be removed - /// once services are all moved from nunit.engine.core to nunit.engine. - /// - public RemoteTestAgent(Guid agentId) : base(agentId) - { - } - - public ITestAgentTransport? Transport; - - public override bool Start() - { - Guard.OperationValid(Transport is not null, "Transport must be set before calling Start()."); - return Transport.Start(); - } - - public override void Stop() - { - Guard.OperationValid(Transport is not null, "Transport must be set before calling Stop()."); - Transport.Stop(); - } - - public override ITestEngineRunner CreateRunner(TestPackage package) - { -#if NETFRAMEWORK - return new TestDomainRunner(package); -#else - return new LocalTestRunner(package); -#endif - } - } -} diff --git a/src/NUnitCommon/nunit.agent.core/Agents/TestAgent.cs b/src/NUnitCommon/nunit.agent.core/Agents/TestAgent.cs deleted file mode 100644 index f8c0a9f98..000000000 --- a/src/NUnitCommon/nunit.agent.core/Agents/TestAgent.cs +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using System; -using System.Threading; - -namespace NUnit.Engine.Agents -{ - /// - /// Abstract base for all types of TestAgents. - /// A TestAgent provides services of locating, - /// loading and running tests in a particular - /// context such as an application domain or process. - /// - public abstract class TestAgent : ITestAgent, IDisposable - { - internal readonly ManualResetEvent StopSignal = new ManualResetEvent(false); - - /// - /// Initializes a new instance of the class. - /// - /// The identifier of the agent. - public TestAgent(Guid agentId) - { - Id = agentId; - } - - /// - /// Gets a Guid that uniquely identifies this agent. - /// - public Guid Id { get; } - - /// - /// Starts the agent, performing any required initialization - /// - /// true if the agent was started successfully. - public abstract bool Start(); - - /// - /// Stops the agent, releasing any resources - /// - public abstract void Stop(); - - /// - /// Creates a test runner - /// - public abstract ITestEngineRunner CreateRunner(TestPackage package); - - public bool WaitForStop(int timeout) - { - return StopSignal.WaitOne(timeout); - } - - public void Dispose() - { - GC.SuppressFinalize(this); - Dispose(true); - } - - private bool _disposed = false; - - /// - /// Dispose is overridden to stop the agent - /// - protected virtual void Dispose(bool disposing) - { - if (!_disposed) - { - if (disposing) - Stop(); - - _disposed = true; - } - } - } -} diff --git a/src/NUnitCommon/nunit.agent.core/CallbackHandler.cs b/src/NUnitCommon/nunit.agent.core/CallbackHandler.cs deleted file mode 100644 index cec574316..000000000 --- a/src/NUnitCommon/nunit.agent.core/CallbackHandler.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -#if NETFRAMEWORK -using System; -using System.Web.UI; - -namespace NUnit.Engine -{ - public class CallbackHandler : MarshalByRefObject, ICallbackEventHandler - { - public string? Result { get; private set; } - - public override object InitializeLifetimeService() - { - return null!; - } - - public string GetCallbackResult() - { - throw new NotImplementedException(); - } - - public void RaiseCallbackEvent(string eventArgument) - { - Result = eventArgument; - } - } -} -#endif \ No newline at end of file diff --git a/src/NUnitCommon/nunit.agent.core/Communication/Transports/ITestAgentTransport.cs b/src/NUnitCommon/nunit.agent.core/Communication/Transports/ITestAgentTransport.cs deleted file mode 100644 index 9859a6fba..000000000 --- a/src/NUnitCommon/nunit.agent.core/Communication/Transports/ITestAgentTransport.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using NUnit.Engine.Agents; - -namespace NUnit.Engine.Communication.Transports -{ - /// - /// The ITestAgentTransport interface is implemented by a - /// class providing communication for a TestAgent. - /// - public interface ITestAgentTransport - { - TestAgent Agent { get; } - ITestEngineRunner CreateRunner(TestPackage package); - bool Start(); - void Stop(); - } -} diff --git a/src/NUnitCommon/nunit.agent.core/Communication/Transports/Tcp/TestAgentTcpTransport.cs b/src/NUnitCommon/nunit.agent.core/Communication/Transports/Tcp/TestAgentTcpTransport.cs deleted file mode 100644 index 7a6224c46..000000000 --- a/src/NUnitCommon/nunit.agent.core/Communication/Transports/Tcp/TestAgentTcpTransport.cs +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using System.Net; -using System.Net.Sockets; -using System.Threading; -using System.Xml.Serialization; -using NUnit.Engine.Agents; -using NUnit.Engine.Communication.Messages; -using NUnit.Engine.Communication.Protocols; - -namespace NUnit.Engine.Communication.Transports.Tcp -{ - /// - /// TestAgentTcpTransport uses TCP to support - /// a TestAgent in communicating with a TestAgency and - /// with the runners that make use of it. - /// - public class TestAgentTcpTransport : ITestAgentTransport, ITestEventListener - { - private static readonly Logger log = InternalTrace.GetLogger(typeof(TestAgentTcpTransport)); - private static readonly char[] PortSeparator = [':']; - - private readonly string _agencyUrl; - private Socket? _clientSocket; - private ITestEngineRunner? _runner; - private XmlSerializer _testPackageSerializer = new XmlSerializer(typeof(TestPackage)); - - public TestAgentTcpTransport(RemoteTestAgent agent, string serverUrl) - { - Guard.ArgumentNotNull(agent); - Agent = agent; - - Guard.ArgumentNotNullOrEmpty(serverUrl); - _agencyUrl = serverUrl; - - var parts = serverUrl.Split(PortSeparator); - Guard.ArgumentValid(parts.Length == 2, "Invalid server address specified. Must be a valid endpoint including the port number", nameof(serverUrl)); - ServerEndPoint = new IPEndPoint(IPAddress.Parse(parts[0]), int.Parse(parts[1])); - } - - public TestAgent Agent { get; } - - public IPEndPoint ServerEndPoint { get; } - - public bool Start() - { - log.Info("Connecting to TestAgency at {0}", _agencyUrl); - - // Connect to the server - _clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - _clientSocket.Connect(ServerEndPoint); - - // Immediately upon connection send the agent Id as a raw byte array - _clientSocket.Send(Agent.Id.ToByteArray()); - - // Start the loop that reads and executes commands - Thread commandLoop = new Thread(CommandLoop); - commandLoop.Start(); - - return true; - } - - public void Stop() - { - Agent.StopSignal.Set(); - } - - public ITestEngineRunner CreateRunner(TestPackage package) - { - return Agent.CreateRunner(package); - } - - private void CommandLoop() - { - bool keepRunning = true; - var socketReader = new SocketReader(_clientSocket.ShouldNotBeNull(), new BinarySerializationProtocol()); - - while (keepRunning) - { - var command = socketReader.GetNextMessage(); - - switch (command.Code) - { - case MessageCode.CreateRunner: - var package = PackageHelper.FromXml(command.Data!); - _runner = CreateRunner(package); - break; - case MessageCode.LoadCommand: - SendResult(_runner.ShouldNotBeNull().Load().Xml.OuterXml); - break; - case MessageCode.ReloadCommand: - SendResult(_runner.ShouldNotBeNull().Reload().Xml.OuterXml); - break; - case MessageCode.UnloadCommand: - _runner.ShouldNotBeNull().Unload(); - break; - case MessageCode.ExploreCommand: - var filter = new TestFilter(command.Data!); - SendResult(_runner.ShouldNotBeNull().Explore(filter).Xml.OuterXml); - break; - case MessageCode.CountCasesCommand: - filter = new TestFilter(command.Data!); - SendResult(_runner.ShouldNotBeNull().CountTestCases(filter).ToString()); - break; - case MessageCode.RunCommand: - filter = new TestFilter(command.Data!); - SendResult(_runner.ShouldNotBeNull().Run(this, filter).Xml.OuterXml); - break; - - case MessageCode.RunAsyncCommand: - filter = new TestFilter(command.Data!); - _runner.ShouldNotBeNull().RunAsync(this, filter); - break; - - case MessageCode.StopAgent: - keepRunning = false; - break; - } - } - - Stop(); - } - - private void SendResult(string result) - { - var resultMessage = new TestEngineMessage(MessageCode.CommandResult, result); - var bytes = new BinarySerializationProtocol().Encode(resultMessage); - _clientSocket.ShouldNotBeNull().Send(bytes); - } - - public void OnTestEvent(string report) - { - var progressMessage = new TestEngineMessage(MessageCode.ProgressReport, report); - var bytes = new BinarySerializationProtocol().Encode(progressMessage); - _clientSocket.ShouldNotBeNull().Send(bytes); - } - } -} diff --git a/src/NUnitCommon/nunit.agent.core/Drivers/DriverService.cs b/src/NUnitCommon/nunit.agent.core/Drivers/DriverService.cs deleted file mode 100644 index cea15c18f..000000000 --- a/src/NUnitCommon/nunit.agent.core/Drivers/DriverService.cs +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using NUnit.Common; -using NUnit.Engine.Extensibility; -using NUnit.Extensibility; -using TestCentric.Metadata; - -namespace NUnit.Engine.Drivers -{ - /// - /// The DriverService provides drivers able to load and run tests - /// using various frameworks. - /// - public class DriverService : IDriverService - { -#if NETFRAMEWORK - private const string TYPE_EXTENSION_PATH = "/NUnit/Engine/TypeExtensions/"; - - private static readonly Assembly THIS_ASSEMBLY = typeof(DriverService).Assembly; - private static readonly bool RUNNING_UNDER_CHOCOLATEY = - System.IO.File.Exists(Path.Combine(Path.GetDirectoryName(THIS_ASSEMBLY.Location)!, "VERIFICATION.txt")); - private static readonly string PACKAGE_PREFIX = RUNNING_UNDER_CHOCOLATEY ? "nunit-extension-" : "NUnit.Extension."; -#endif - - private static readonly Logger log = InternalTrace.GetLogger("DriverService"); - - private static readonly char[] CommaSeparator = [',']; - - private readonly List _factories = new List(); - - public DriverService() - { - _factories.Add(new NUnit3DriverFactory()); - - // TODO: Restore extensibility to Driver Service - //var extensionManager = new ExtensionManager() - //{ - // TypeExtensionPath = TYPE_EXTENSION_PATH, - // PackagePrefixes = [PACKAGE_PREFIX] - //}; - - //extensionManager.FindExtensionPoints(THIS_ASSEMBLY); - //extensionManager.FindExtensionAssemblies(THIS_ASSEMBLY); - - //foreach (IDriverFactory factory in extensionManager.GetExtensions()) - // _factories.Add(factory); - - //var node = extensionManager.GetExtensionNode("/NUnit/Engine/NUnitV2Driver"); - //if (node is not null) - // _factories.Add(new NUnit2DriverFactory(node)); - } - - /// - /// Get a driver suitable for use with a particular test assembly. - /// - /// The application domain to use for the tests - /// The full path to the test assembly - /// The value of any TargetFrameworkAttribute on the assembly, or null - /// True if non-test assemblies should simply be skipped rather than reporting an error - public IFrameworkDriver GetDriver(AppDomain domain, TestPackage package, string assemblyPath, string? targetFramework, bool skipNonTestAssemblies) - { - string InternalErrorMessage(string message) => - $"Internal Error: {message} {assemblyPath}"; - - Guard.ArgumentValid(File.Exists(assemblyPath), InternalErrorMessage("File not found"), nameof(assemblyPath)); - Guard.ArgumentValid(PathUtils.IsAssemblyFileType(assemblyPath), InternalErrorMessage("Not an assembly type"), nameof(assemblyPath)); - - log.Debug("Looking for a driver"); - using (var assemblyDef = AssemblyDefinition.ReadAssembly(assemblyPath)) - { - if (skipNonTestAssemblies) - { - // TODO: We should not get here since the engine should have eliminated any - // such assemblies. Double-check for now but remove before the next release. - foreach (var attr in assemblyDef.CustomAttributes) - if (attr.AttributeType.FullName == "NUnit.Framework.NonTestAssemblyAttribute") - throw new InvalidOperationException(InternalErrorMessage("Assembly should have been skipped")); - } - - foreach (var factory in _factories) - { - log.Debug($"Trying {factory.GetType().Name}"); - - foreach (var cecilRef in assemblyDef.MainModule.AssemblyReferences) - { - var assemblyName = new AssemblyName(cecilRef.FullName); - if (factory.IsSupportedTestFramework(assemblyName)) - { -#if NETFRAMEWORK - return factory.GetDriver(domain, package.ID, assemblyName); -#else - return factory.GetDriver(package.ID, assemblyName); -#endif - } - } - } - } - - return new InvalidAssemblyFrameworkDriver(assemblyPath, package.ID, - $"No suitable test driver has not been found for {assemblyPath}"); - } - } -} diff --git a/src/NUnitCommon/nunit.agent.core/Drivers/IDriverService.cs b/src/NUnitCommon/nunit.agent.core/Drivers/IDriverService.cs deleted file mode 100644 index e9d57cd78..000000000 --- a/src/NUnitCommon/nunit.agent.core/Drivers/IDriverService.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using System; -using NUnit.Engine.Extensibility; - -namespace NUnit.Engine.Drivers -{ - /// - /// The IDriverService interface is implemented by the driver service, which is able - /// to provide drivers for loading and running tests using various frameworks. - /// - public interface IDriverService - { - /// - /// Get a driver suitable for loading and running tests in the specified assembly. - /// - /// The application domain in which to run the tests - /// The package for which the driver is to be used - /// The path to the test assembly - /// The value of any TargetFrameworkAttribute on the assembly, or null - /// True if non-test assemblies should simply be skipped rather than reporting an error - IFrameworkDriver GetDriver(AppDomain domain, TestPackage package, string assemblyPath, string? targetFramework, bool skipNonTestAssemblies); - } -} diff --git a/src/NUnitCommon/nunit.agent.core/Drivers/InvalidAssemblyFrameworkDriver.cs b/src/NUnitCommon/nunit.agent.core/Drivers/InvalidAssemblyFrameworkDriver.cs deleted file mode 100644 index ae01a4001..000000000 --- a/src/NUnitCommon/nunit.agent.core/Drivers/InvalidAssemblyFrameworkDriver.cs +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using System; -using System.Collections.Generic; -using System.IO; -using NUnit.Common; -using NUnit.Engine.Extensibility; - -namespace NUnit.Engine.Drivers -{ - public sealed class InvalidAssemblyFrameworkDriver : IFrameworkDriver - { - private readonly string _name; - private readonly string _fullname; - private readonly string _message; - private readonly string _type; - - private const string RUNSTATE = "NotRunnable"; - private const string RESULT = "FAILED"; - private const string LABEL = "INVALID"; - - public InvalidAssemblyFrameworkDriver(string assemblyPath, string id, string message) - { - _name = Escape(Path.GetFileName(assemblyPath)); - _fullname = Escape(Path.GetFullPath(assemblyPath)); - _message = Escape(message); - _type = PathUtils.IsAssemblyFileType(assemblyPath) ? "Assembly" : "Unknown"; - ID = id; - } - - public string ID { get; } - - public string Load(string assemblyPath, IDictionary settings) - { - return GetLoadResult(); - } - - public int CountTestCases(string filter) - { - return 0; - } - - public string Run(ITestEventListener? listener, string filter) - { - return GetRunResult(); - } - - public void RunAsync(ITestEventListener? listener, string filter) - { - listener?.OnTestEvent(GetRunResult()); - } - - public string Explore(string filter) - { - return GetLoadResult(); - } - - public void RequestStop() - { - } - - public void ForcedStop() - { - } - - private static string Escape(string original) - { - return original - .Replace("&", "&") - .Replace("\"", """) - .Replace("'", "'") - .Replace("<", "<") - .Replace(">", ">"); - } - - private string GetLoadResult() => - $"" + - "" + - $"" + - "" + - ""; - - private string GetRunResult() => - $"" + - "" + - $"" + - "" + - "" + - $"{_message}" + - "" + - ""; - - private string TestID => ID + "-1"; - } -} diff --git a/src/NUnitCommon/nunit.agent.core/Drivers/NUnit2DriverFactory.cs b/src/NUnitCommon/nunit.agent.core/Drivers/NUnit2DriverFactory.cs deleted file mode 100644 index 3d730da50..000000000 --- a/src/NUnitCommon/nunit.agent.core/Drivers/NUnit2DriverFactory.cs +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -#if NETFRAMEWORK -using System; -using System.Reflection; -using NUnit.Engine.Extensibility; -using NUnit.Extensibility; - -namespace NUnit.Engine.Drivers -{ - public class NUnit2DriverFactory : IDriverFactory - { - private const string NUNIT_FRAMEWORK = "nunit.framework"; - private const string NUNITLITE_FRAMEWORK = "nunitlite"; - private readonly IExtensionNode _driverNode; - - // TODO: This should be a central service but for now it's local - private ProvidedPathsAssemblyResolver? _resolver; - - public NUnit2DriverFactory(IExtensionNode driverNode) - { - _driverNode = driverNode; - } - - /// - /// Gets a flag indicating whether a given assembly name and version - /// represent a test framework supported by this factory. - /// - /// An AssemblyName referring to the possible test framework. - public bool IsSupportedTestFramework(AssemblyName reference) - { - return NUNIT_FRAMEWORK.Equals(reference.Name, StringComparison.OrdinalIgnoreCase) && reference.Version?.Major == 2 - || NUNITLITE_FRAMEWORK.Equals(reference.Name, StringComparison.OrdinalIgnoreCase) && reference.Version?.Major == 1; - } - - /// - /// Gets a driver for a given test assembly and a framework - /// which the assembly is already known to reference. - /// - /// The domain in which the assembly will be loaded - /// The name of the test framework reference - public IFrameworkDriver GetDriver(AppDomain domain, string id, AssemblyName reference) - { - if (!IsSupportedTestFramework(reference)) - throw new ArgumentException("Invalid framework", nameof(reference)); - - if (_resolver is null) - { - _resolver = new ProvidedPathsAssemblyResolver(); - _resolver.Install(); - _resolver.AddPathFromFile(_driverNode.AssemblyPath); - } - - return (IFrameworkDriver)AppDomain.CurrentDomain.CreateInstanceFromAndUnwrap( - _driverNode.AssemblyPath, - _driverNode.TypeName, - false, - 0, - null, - new object[] { domain, id, reference }, - null, - null).ShouldNotBeNull(); - } - } -} -#endif diff --git a/src/NUnitCommon/nunit.agent.core/Drivers/NUnit3DriverFactory.cs b/src/NUnitCommon/nunit.agent.core/Drivers/NUnit3DriverFactory.cs deleted file mode 100644 index d51c19cae..000000000 --- a/src/NUnitCommon/nunit.agent.core/Drivers/NUnit3DriverFactory.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using System; -using System.Reflection; -using NUnit.Engine.Extensibility; - -namespace NUnit.Engine.Drivers -{ - public class NUnit3DriverFactory : IDriverFactory - { - internal const string NUNIT_FRAMEWORK = "nunit.framework"; - private static readonly Logger log = InternalTrace.GetLogger(typeof(NUnit3DriverFactory)); - - /// - /// Gets a flag indicating whether a given assembly name and version - /// represent a test framework supported by this factory. - /// - /// An AssemblyName referring to the possible test framework. - public bool IsSupportedTestFramework(AssemblyName reference) - { - return NUNIT_FRAMEWORK.Equals(reference.Name, StringComparison.OrdinalIgnoreCase) && reference.Version?.Major is 3 or 4; - } - -#if NETFRAMEWORK - /// - /// Gets a driver for a given test framework. - /// - /// The domain in which the assembly will be loaded - /// An AssemblyName referring to the test framework. - /// An IFrameworkDriver - public IFrameworkDriver GetDriver(AppDomain domain, string id, AssemblyName reference) - { - Guard.ArgumentNotNullOrEmpty(id); - Guard.ArgumentValid(IsSupportedTestFramework(reference), "Invalid framework", nameof(reference)); - - log.Info("Using NUnitFrameworkDriver"); - return new NUnitFrameworkDriver(domain, id, reference); - } -#else - /// - /// Gets a driver for a given test framework. - /// - /// An AssemblyName referring to the test framework. - public IFrameworkDriver GetDriver(string id, AssemblyName reference) - { - Guard.ArgumentNotNullOrEmpty(id); - Guard.ArgumentValid(IsSupportedTestFramework(reference), "Invalid framework", nameof(reference)); - log.Info("Using NUnitFrameworkDriver"); - return new NUnitFrameworkDriver(id, reference); - } -#endif - } -} diff --git a/src/NUnitCommon/nunit.agent.core/Drivers/NUnitFrameworkApi.cs b/src/NUnitCommon/nunit.agent.core/Drivers/NUnitFrameworkApi.cs deleted file mode 100644 index d3a0a6006..000000000 --- a/src/NUnitCommon/nunit.agent.core/Drivers/NUnitFrameworkApi.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using System; -using System.Collections.Generic; - -namespace NUnit.Engine.Drivers -{ - /// - /// Driver API for the NUnit Framework. Provides a common interface to al - /// versions of the framework, in spite of differences in their own API. - /// - public interface NUnitFrameworkApi - { - /// - /// Loads the tests in an assembly. - /// - /// An Xml string representing the loaded test - string Load(string testAssemblyPath, IDictionary settings); - - /// - /// Count the test cases that would be executed. - /// - /// An XML string representing the TestFilter to use in counting the tests - /// The number of test cases counted - int CountTestCases(string filter); - - /// - /// Executes the tests in an assembly synchronously. - /// - /// An ITestEventHandler that receives progress notices - /// A XML string representing the filter that controls which tests are executed - /// An Xml string representing the result - string Run(ITestEventListener? listener, string filter); - - /// - /// Executes the tests in an assembly asynchronously. - /// - /// A callback that receives XML progress notices - /// A filter that controls which tests are executed - void RunAsync(Action? callback, string filter); - - /// - /// Returns information about the tests in an assembly. - /// - /// An XML string representing the filter that controls which tests are included - /// An Xml string representing the tests - string Explore(string filter); - - /// - /// Cancel the ongoing test run. If no test is running, the call is ignored. - /// - void RequestStop(); - - /// - /// Force the current test run to stop, killing threads or processes if necessary. - /// - /// - void ForcedStop(); - - /// - /// Gets a flag indicating whether ForcedStop is supported for the framework version in use. - /// - bool ForcedStopSupported { get; } - } -} diff --git a/src/NUnitCommon/nunit.agent.core/Drivers/NUnitFrameworkApi2009.cs b/src/NUnitCommon/nunit.agent.core/Drivers/NUnitFrameworkApi2009.cs deleted file mode 100644 index fa908d6e4..000000000 --- a/src/NUnitCommon/nunit.agent.core/Drivers/NUnitFrameworkApi2009.cs +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -#if NETFRAMEWORK -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Runtime.Serialization; -using NUnit.Common; - -namespace NUnit.Engine.Drivers -{ - /// - /// This is the original NUnit 3 API, which only works for .NET Framework. - /// As far as I can discover, it first appeared in pre-release 2.9.1, - /// on launchpad in 2009, hence the name. - /// - internal class NUnitFrameworkApi2009 : NUnitFrameworkApi - { - private static readonly Logger log = InternalTrace.GetLogger(nameof(NUnitFrameworkApi2009)); - - private const string LOAD_MESSAGE = "Method called without calling Load first. Possible error in runner."; - private const string INVALID_FRAMEWORK_MESSAGE = "Running tests against this version of the framework using this driver is not supported. Please update NUnit.Framework to the latest version."; - private const string FAILED_TO_LOAD_ASSEMBLY = "Failed to load assembly "; - private const string FAILED_TO_LOAD_NUNIT = "Failed to load the NUnit Framework in the test assembly"; - - private const string CONTROLLER_TYPE = "NUnit.Framework.Api.FrameworkController"; - - private readonly string _driverId; - - private readonly AppDomain _testDomain; - private readonly AssemblyName _nunitRef; - - private string? _testAssemblyPath; - - private object? _frameworkController; - private Type? _frameworkControllerType; - - public NUnitFrameworkApi2009(AppDomain testDomain, string driverId, AssemblyName nunitRef) - { - Guard.ArgumentNotNull(testDomain); - Guard.ArgumentNotNull(driverId); - Guard.ArgumentNotNull(nunitRef); - - _testDomain = testDomain; - _driverId = driverId; - _nunitRef = nunitRef; - } - - public string Load(string testAssemblyPath, IDictionary settings) - { - Guard.ArgumentValid(File.Exists(testAssemblyPath), "Framework driver called with a file name that doesn't exist.", nameof(testAssemblyPath)); - - log.Info($"Loading {testAssemblyPath} - see separate log file"); - - _testAssemblyPath = testAssemblyPath; - - // Normally, the caller should check for an invalid requested runtime, but to be sure, - // we check it. The setting value is only used for an error message. - settings.TryGetValue(SettingDefinitions.RequestedRuntimeFramework.Name, out object? requestedRuntime); - - var idPrefix = _driverId + "-"; - - try - { - _frameworkController = _testDomain.CreateInstanceAndUnwrap( - _nunitRef.FullName, - CONTROLLER_TYPE, - false, - 0, - null, - new object[] { _testAssemblyPath, idPrefix, settings }, - null, - null).ShouldNotBeNull(); - } - catch (BadImageFormatException ex) when (requestedRuntime is not null) - { - throw new NUnitEngineException($"Requested runtime {requestedRuntime} is not suitable for use with test assembly {_testAssemblyPath}", ex); - } - catch (SerializationException ex) - { - throw new NUnitEngineException("The NUnit 3 driver cannot support this test assembly. Use a platform specific runner.", ex); - } - - _frameworkControllerType = _frameworkController.GetType(); - log.Debug($"Created FrameworkController {_frameworkControllerType.Name}"); - - return ExecuteAction(LOAD_ACTION); - } - - public int CountTestCases(string filter) - { - CheckLoadWasCalled(); - return int.Parse(ExecuteAction(COUNT_ACTION, filter)); - } - - public string Run(ITestEventListener? listener, string filter) - { - CheckLoadWasCalled(); - log.Info("Running {0} - see separate log file", Path.GetFileName(_testAssemblyPath.ShouldNotBeNull())); - return ExecuteAction(RUN_ACTION, listener, filter); - } - - public void RunAsync(Action? callback, string filter) => throw new NotImplementedException(); - - public void RequestStop() => ExecuteAction(STOP_RUN_ACTION, false); - - public void ForcedStop() => ExecuteAction(STOP_RUN_ACTION, true); - - public bool ForcedStopSupported => true; - - public string Explore(string filter) - { - CheckLoadWasCalled(); - log.Info("Exploring {0} - see separate log file", Path.GetFileName(_testAssemblyPath.ShouldNotBeNull())); - return ExecuteAction(EXPLORE_ACTION, filter); - } - - private void CheckLoadWasCalled() - { - if (_frameworkController is null) - throw new InvalidOperationException(LOAD_MESSAGE); - } - - // Actions with no extra arguments beyond controller and handler - private const string LOAD_ACTION = CONTROLLER_TYPE + "+LoadTestsAction"; - private string ExecuteAction(string action) - { - CallbackHandler handler = new CallbackHandler(); - CreateObject(action, _frameworkController, handler); - return handler.Result.ShouldNotBeNull(); - } - - // Actions with one extra argument - private const string EXPLORE_ACTION = CONTROLLER_TYPE + "+ExploreTestsAction"; - private const string COUNT_ACTION = CONTROLLER_TYPE + "+CountTestsAction"; - private const string STOP_RUN_ACTION = CONTROLLER_TYPE + "+StopRunAction"; - private string ExecuteAction(string action, object arg1) - { - CallbackHandler handler = new CallbackHandler(); - CreateObject(action, _frameworkController, arg1, handler); - return handler.Result.ShouldNotBeNull(); - } - - // Run action has two extra arguments and uses a special handler - private const string RUN_ACTION = CONTROLLER_TYPE + "+RunTestsAction"; - private string ExecuteAction(string action, ITestEventListener? listener, string filter) - { - RunTestsCallbackHandler handler = new RunTestsCallbackHandler(listener); - CreateObject(action, _frameworkController, filter, handler); - return handler.Result.ShouldNotBeNull(); - } - - private object CreateObject(string typeName, params object?[]? args) - { - try - { - return _testDomain.CreateInstanceAndUnwrap( - _nunitRef.FullName, typeName, false, 0, null, args, null, null)!; - } - catch (TargetInvocationException ex) - { - throw new NUnitEngineException("The NUnit 3 driver encountered an error while executing reflected code.", ex.InnerException); - } - } - } -} -#endif diff --git a/src/NUnitCommon/nunit.agent.core/Drivers/NUnitFrameworkApi2018.cs b/src/NUnitCommon/nunit.agent.core/Drivers/NUnitFrameworkApi2018.cs deleted file mode 100644 index e521755fb..000000000 --- a/src/NUnitCommon/nunit.agent.core/Drivers/NUnitFrameworkApi2018.cs +++ /dev/null @@ -1,306 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using NUnit.Common; -#if NETCOREAPP -using System.Runtime.Loader; -using NUnit.Engine.Internal; -#endif - -namespace NUnit.Engine.Drivers -{ - /// - /// This is the revised API, designed for use with .NET Core. It first - /// appears in our source code in 2018. This implementation is modified - /// to make it work under the .NET Framework as well as .NET Core. It - /// may be used for NUnit 3.10 or higher. - /// -#if NETFRAMEWORK - public class NUnitFrameworkApi2018 : MarshalByRefObject, NUnitFrameworkApi -#else - public class NUnitFrameworkApi2018 : NUnitFrameworkApi -#endif - { - private static readonly Logger log = InternalTrace.GetLogger(nameof(NUnitFrameworkApi2018)); - - private const string LOAD_MESSAGE = "Method called without calling Load first. Possible error in runner."; - private const string INVALID_FRAMEWORK_MESSAGE = "Running tests against this version of the framework using this driver is not supported. Please update NUnit.Framework to the latest version."; - private const string FAILED_TO_LOAD_ASSEMBLY = "Failed to load assembly "; - private const string FAILED_TO_LOAD_NUNIT = "Failed to load the NUnit Framework in the test assembly"; - - private const string CONTROLLER_TYPE = "NUnit.Framework.Api.FrameworkController"; - - private readonly string _driverId; - - private readonly AssemblyName _nunitRef; - - private object? _frameworkController; - private Type? _frameworkControllerType; - -#if NETCOREAPP - private AssemblyLoadContext? _assemblyLoadContext; - private TestAssemblyResolver? _testAssemblyResolver; - private Assembly? _testAssembly; - private Assembly? _frameworkAssembly; - - internal List? ResolutionStrategies => _testAssemblyResolver?.ResolutionStrategies; -#endif - - private string? _testAssemblyPath; - - public NUnitFrameworkApi2018(string driverId, AssemblyName nunitRef) - { - Guard.ArgumentNotNull(driverId); - Guard.ArgumentNotNull(nunitRef); - - _driverId = driverId; - _nunitRef = nunitRef; - } - - public string Load(string testAssemblyPath, IDictionary settings) - { - Guard.ArgumentNotNull(testAssemblyPath); - Guard.ArgumentNotNull(settings); - Guard.ArgumentValid(File.Exists(testAssemblyPath), "Framework driver called with a file name that doesn't exist.", nameof(testAssemblyPath)); - log.Info($"Loading {testAssemblyPath} - see separate log file"); - - _testAssemblyPath = Path.GetFullPath(testAssemblyPath); - var idPrefix = _driverId + "-"; - - bool useDefaultAssemblyLoadContext = false; - if (settings.TryGetValue(SettingDefinitions.UseDefaultAssemblyLoadContext, out var val)) - useDefaultAssemblyLoadContext = (bool)val; - -#if NETFRAMEWORK - try - { - log.Debug("Creating FrameworkController"); - _frameworkController = AppDomain.CurrentDomain.CreateInstanceAndUnwrap( - _nunitRef.FullName, - CONTROLLER_TYPE, - false, - 0, - null, - new object[] { _testAssemblyPath, idPrefix, settings }, - null, - null).ShouldNotBeNull(); - log.Debug("Created FrameworkController"); - } - catch (Exception ex) - { - log.Debug($"Got Exception {ex}"); - string msg = $"Failed to load {_nunitRef.FullName}\r\n Codebase: {_nunitRef.CodeBase}"; - throw new Exception(msg, ex); - } - - _frameworkControllerType = _frameworkController?.GetType(); - log.Debug($"Created FrameworkController {_frameworkControllerType?.Name}"); - - var controllerAssembly = _frameworkControllerType?.Assembly?.GetName(); - log.Debug($"Controller assembly is {controllerAssembly}"); -#else - try - { - _testAssembly = AssemblyHelper.FindLoadedAssemblyByPath(_testAssemblyPath); - - if (_testAssembly is not null) - { - _assemblyLoadContext = AssemblyLoadContext.GetLoadContext(_testAssembly); - log.Debug($" Already loaded in context {_assemblyLoadContext}"); - } - else - { - _assemblyLoadContext = useDefaultAssemblyLoadContext - ? AssemblyLoadContext.Default - : new AssemblyLoadContext(Path.GetFileNameWithoutExtension(testAssemblyPath)); - _testAssembly = _assemblyLoadContext.LoadFromAssemblyPath(testAssemblyPath); - log.Debug($" Loaded into new context {_assemblyLoadContext}"); - } - - _testAssemblyResolver = new TestAssemblyResolver(_assemblyLoadContext.ShouldNotBeNull(), testAssemblyPath); - } - catch (Exception e) - { - var msg = $"Failed to load test assembly {testAssemblyPath}"; - log.Error(msg); - throw new NUnitEngineException(msg, e); - } - log.Debug($"Loaded {testAssemblyPath}"); - - try - { - _frameworkAssembly = LoadAssembly(_nunitRef); - } - catch (Exception e) - { - log.Error($"{FAILED_TO_LOAD_NUNIT}\r\n{e}"); - throw new NUnitEngineException(FAILED_TO_LOAD_NUNIT, e); - } - log.Debug("Loaded nunit.framework"); - - _frameworkController = CreateInstance(CONTROLLER_TYPE, _testAssembly, idPrefix, settings); - if (_frameworkController is null) - { - log.Error(INVALID_FRAMEWORK_MESSAGE); - throw new NUnitEngineException(INVALID_FRAMEWORK_MESSAGE); - } -#endif - - _frameworkControllerType = _frameworkController?.GetType(); - log.Debug($"Created FrameworkController {_frameworkControllerType?.Name}"); - - log.Debug($"Loaded {testAssemblyPath}"); - return (string)ExecuteMethod(LOAD_METHOD); - } - - public int CountTestCases(string filter) - { - CheckLoadWasCalled(); - object? count = ExecuteMethod(COUNT_METHOD, filter); - return count is not null ? (int)count : 0; - } - - public string Run(ITestEventListener? listener, string filter) - { - CheckLoadWasCalled(); - log.Info("Running {0} - see separate log file", Path.GetFileName(_testAssemblyPath.ShouldNotBeNull())); - Action? callback = listener is not null ? listener.OnTestEvent : null; - return (string)ExecuteMethod(RUN_METHOD, [typeof(Action), typeof(string)], callback, filter); - } - - public void RunAsync(Action? callback, string filter) - { - CheckLoadWasCalled(); - log.Info("Running {0} - see separate log file", Path.GetFileName(_testAssemblyPath.ShouldNotBeNull())); - ExecuteMethod(RUN_ASYNC_METHOD, [typeof(Action), typeof(string)], callback, filter); - } - - public void RequestStop() - { - ExecuteMethod(STOP_RUN_METHOD, false); - } - - public void ForcedStop() - { - ExecuteMethod(STOP_RUN_METHOD, true); - } - - public bool ForcedStopSupported => _nunitRef.Version.ShouldNotBeNull().Major is 3 or 4; - - public string Explore(string filter) - { - CheckLoadWasCalled(); - log.Info("Exploring {0} - see separate log file", Path.GetFileName(_testAssemblyPath.ShouldNotBeNull())); - return (string)ExecuteMethod(EXPLORE_METHOD, filter); - } - - private void CheckLoadWasCalled() - { - if (_frameworkController is null) - throw new InvalidOperationException(LOAD_MESSAGE); - } - -#if NETCOREAPP - private object CreateInstance(string typeName, params object?[]? args) - { - var type = _frameworkAssembly.ShouldNotBeNull().GetType(typeName, throwOnError: true)!; - return Activator.CreateInstance(type, args)!; - } - - private Assembly LoadAssembly(string assemblyPath) - { - Assembly assembly; - - try - { - assembly = _assemblyLoadContext?.LoadFromAssemblyPath(assemblyPath)!; - if (assembly is null) - throw new Exception("LoadFromAssemblyPath returned null"); - } - catch (Exception e) - { - var msg = string.Format(FAILED_TO_LOAD_ASSEMBLY + assemblyPath); - log.Error(msg); - throw new NUnitEngineException(msg, e); - } - - log.Debug($"Loaded {assemblyPath}"); - return assembly; - } - - private Assembly LoadAssembly(AssemblyName assemblyName) - { - Assembly assembly; - - try - { - assembly = _assemblyLoadContext?.LoadFromAssemblyName(assemblyName)!; - if (assembly is null) - throw new Exception("LoadFromAssemblyName returned null"); - } - catch (Exception e) - { - log.Error($"{FAILED_TO_LOAD_ASSEMBLY}\r\n{e}"); - throw new NUnitEngineException(FAILED_TO_LOAD_NUNIT, e); - } - - log.Debug($"Loaded {assemblyName.FullName}"); - return assembly; - } -#endif - - // API methods with no overloads - private static readonly string LOAD_METHOD = "LoadTests"; - private static readonly string EXPLORE_METHOD = "ExploreTests"; - private static readonly string COUNT_METHOD = "CountTests"; - private static readonly string STOP_RUN_METHOD = "StopRun"; - - // Execute methods with no overloads - private object ExecuteMethod(string methodName, params object?[] args) - { - log.Debug($"Calling API method {methodName} with args {string.Join("+", args)}"); - var method = _frameworkControllerType.ShouldNotBeNull().GetMethod(methodName, BindingFlags.Public | BindingFlags.Instance); - return ExecuteMethod(method, args); - } - - // API methods with overloads - private static readonly string RUN_METHOD = "RunTests"; - // Framework RunAsync method is not public - private static readonly string RUN_ASYNC_METHOD = "RunTests"; - - // Execute overloaded methods specifying argument types - private object ExecuteMethod(string methodName, Type[] ptypes, params object?[] args) - { - log.Debug($"Calling API method {methodName} with arg types {string.Join("+", ptypes)}"); - var method = _frameworkControllerType.ShouldNotBeNull().GetMethod(methodName, ptypes); - return ExecuteMethod(method, args); - } - - private object ExecuteMethod(MethodInfo? method, params object?[] args) - { - if (method is null) - throw new NUnitEngineException(INVALID_FRAMEWORK_MESSAGE); - - log.Debug($"Executing {method.DeclaringType}.{method.Name}"); - -#if NETFRAMEWORK - return method.Invoke(_frameworkController, args).ShouldNotBeNull(); -#else - //using (_assemblyLoadContext.ShouldNotBeNull().EnterContextualReflection()) - //{ - return method.Invoke(_frameworkController, args).ShouldNotBeNull(); - //} -#endif - } - -#if NETFRAMEWORK - public override object InitializeLifetimeService() - { - return null!; - } -#endif - } -} diff --git a/src/NUnitCommon/nunit.agent.core/Drivers/NUnitFrameworkDriver.cs b/src/NUnitCommon/nunit.agent.core/Drivers/NUnitFrameworkDriver.cs deleted file mode 100644 index 53505b659..000000000 --- a/src/NUnitCommon/nunit.agent.core/Drivers/NUnitFrameworkDriver.cs +++ /dev/null @@ -1,251 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using NUnit.Common; -using NUnit.Engine.Extensibility; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Reflection; - -#if NETCOREAPP3_1_OR_GREATER -using NUnit.Engine.Internal; -#endif - -namespace NUnit.Engine.Drivers -{ - /// - /// NUnitFrameworkDriver is used by the test-runner to load and run - /// tests using the NUnit framework assembly, versions 3 and up. - /// - public class NUnitFrameworkDriver : IFrameworkDriver - { - private static readonly Version MINIMUM_NUNIT_VERSION_FOR_2018_API = new(3, 2, 0); - private static readonly Logger log = InternalTrace.GetLogger(nameof(NUnitFrameworkDriver)); - - private readonly Version _nunitVersion; - -#if NETFRAMEWORK - private readonly NUnitFrameworkApi _api; - - /// - /// Construct an NUnitFrameworkDriver - /// - /// The application domain in which to create the FrameworkController - /// An AssemblyName referring to the test framework. - public NUnitFrameworkDriver(AppDomain testDomain, string id, AssemblyName nunitRef) - { - Guard.ArgumentNotNull(testDomain); - Guard.ArgumentNotNullOrEmpty(id); - Guard.ArgumentNotNull(nunitRef); - - ID = id; - _nunitVersion = nunitRef.Version.ShouldNotBeNull(); - - if (_nunitVersion >= MINIMUM_NUNIT_VERSION_FOR_2018_API) - { - API = "2018"; - _api = (NUnitFrameworkApi)testDomain.CreateInstanceFromAndUnwrap( - Assembly.GetExecutingAssembly().Location, - "NUnit.Engine.Drivers.NUnitFrameworkApi2018", - false, - 0, - null, - new object[] { ID, nunitRef }, - null, - null).ShouldNotBeNull(); - } - else - { - API = "2009"; - _api = new NUnitFrameworkApi2009(testDomain, ID, nunitRef); - } - } - - /// - /// Internal generic constructor used by our tests. - /// - /// The application domain in which to create the FrameworkController - /// An AssemblyName referring to the test framework. - internal NUnitFrameworkDriver(AppDomain testDomain, string api, string id, AssemblyName nunitRef) - { - Guard.ArgumentNotNull(testDomain); - Guard.ArgumentNotNull(api); - Guard.ArgumentValid(api == "2009" || api == "2018", $"Invalid API specified: {api}", nameof(api)); - Guard.ArgumentNotNullOrEmpty(id); - Guard.ArgumentNotNull(nunitRef); - - _nunitVersion = nunitRef.Version.ShouldNotBeNull(); - - ID = id; - API = api; - - _api = api == "2018" - ? (NUnitFrameworkApi)testDomain.CreateInstanceFromAndUnwrap( - Assembly.GetExecutingAssembly().Location, - typeof(NUnitFrameworkApi2018).FullName!, - false, - 0, - null, - new object[] { ID, nunitRef }, - null, - null).ShouldNotBeNull() - : new NUnitFrameworkApi2009(testDomain, ID, nunitRef); - } -#else - private readonly NUnitFrameworkApi2018 _api; - - /// - /// Construct an NUnitFrameworkDriver - /// - /// An AssemblyName referring to the test framework. - public NUnitFrameworkDriver(string id, AssemblyName nunitRef) - { - Guard.ArgumentNotNullOrEmpty(id); - Guard.ArgumentNotNull(nunitRef); - - ID = id; - API = "2018"; - - _nunitVersion = nunitRef.Version.ShouldNotBeNull(); - _api = new NUnitFrameworkApi2018(ID, nunitRef); - } - - internal List? ResolutionStrategies => _api?.ResolutionStrategies; -#endif - - /// - /// String naming the API in use, for use by tests - /// - internal string API { get; } = string.Empty; - - /// - /// An id prefix that will be passed to the test framework and used as part of the - /// test ids created. - /// - public string ID { get; } - - /// - /// Loads the tests in an assembly. - /// - /// The path to the test assembly - /// The test settings - /// An XML string representing the loaded test - public string Load(string testAssemblyPath, IDictionary settings) - => _api.Load(testAssemblyPath, settings); - - /// - /// Counts the number of test cases for the loaded test assembly - /// - /// The XML test filter - /// The number of test cases - public int CountTestCases(string filter) => _api.CountTestCases(filter); - - /// - /// Executes the tests in an assembly. - /// - /// An ITestEventHandler that receives progress notices - /// A filter that controls which tests are executed - /// An Xml string representing the result - public string Run(ITestEventListener? listener, string filter) => - _api.Run(listener is not null ? new EventInterceptor(listener) : null, filter); - - /// - /// Executes the tests in an assembly asynchronously. - /// - /// A callback that receives XML progress notices - /// A filter that controls which tests are executed - public void RunAsync(ITestEventListener? listener, string filter) => - _api.RunAsync(listener is not null ? new Action(listener.OnTestEvent) : null, filter); - - /// - /// Cancel the ongoing test run. If no test is running, the call is ignored. - /// - public void RequestStop() => _api.RequestStop(); - - /// - /// Force the current test run to stop, killing threads or processes if necessary. - /// If no tests are running, the call is ignored. - /// - public void ForcedStop() - { - if (_api.ForcedStopSupported) - _api.ForcedStop(); - else - Environment.Exit(AgentExitCodes.CANCELLED_BY_FORCED_STOP); - } - - /// - /// Returns information about the tests in an assembly. - /// - /// A filter indicating which tests to include - /// An Xml string representing the tests - public string Explore(string filter) => _api.Explore(filter); - - /// - /// Nested class used to intercept progress reports received from the test - /// framework and resend them to the actual listener, normally located in - /// the runner that is using the engine. - /// - /// - /// This class is absolutely needed when the 2018 NUnit API is used under - /// the .NET Framework using Windows Remoting as a communication protocol. - /// In particular, the MarshalByRef object implementing the listener must - /// be convertible to ITestEventListener via the IConvertible interface. - /// - /// In other cases, the interceptor is not essential, but we use it anyway - /// for several reasons: - /// - /// 1. We have no control over the implementation of runners using the engine. - /// They may not implement IConvertible and may not even derive from - /// MarshaByRefObject. - /// - /// 2. The interceptor provides a point of control for checking what events - /// are received from the framework and for possible future modifications to - /// the events before they are forwarded. - /// - public class EventInterceptor : MarshalByRefObject, ITestEventListener, IConvertible - { - private ITestEventListener _listener; - - public EventInterceptor(ITestEventListener listener) - { - _listener = listener; - } - - #region ITestEventListener and IConvertible Implementations - - void ITestEventListener.OnTestEvent(string report) - { - _listener.OnTestEvent(report); - } - - // Conversion to ITestEventListener is the only one that makes sense - object IConvertible.ToType(Type conversionType, IFormatProvider? provider) => - conversionType == typeof(ITestEventListener) ? this : InvalidCast(conversionType); - - TypeCode IConvertible.GetTypeCode() => TypeCode.Object; - bool IConvertible.ToBoolean(IFormatProvider? provider) => InvalidCast(); - char IConvertible.ToChar(IFormatProvider? provider) => InvalidCast(); - sbyte IConvertible.ToSByte(IFormatProvider? provider) => InvalidCast(); - byte IConvertible.ToByte(IFormatProvider? provider) => InvalidCast(); - short IConvertible.ToInt16(IFormatProvider? provider) => InvalidCast(); - ushort IConvertible.ToUInt16(IFormatProvider? provider) => InvalidCast(); - int IConvertible.ToInt32(IFormatProvider? provider) => InvalidCast(); - uint IConvertible.ToUInt32(IFormatProvider? provider) => InvalidCast(); - long IConvertible.ToInt64(IFormatProvider? provider) => InvalidCast(); - ulong IConvertible.ToUInt64(IFormatProvider? provider) => InvalidCast(); - float IConvertible.ToSingle(IFormatProvider? provider) => InvalidCast(); - double IConvertible.ToDouble(IFormatProvider? provider) => InvalidCast(); - decimal IConvertible.ToDecimal(IFormatProvider? provider) => InvalidCast(); - DateTime IConvertible.ToDateTime(IFormatProvider? provider) => InvalidCast(); - string IConvertible.ToString(IFormatProvider? provider) => InvalidCast(); - - private static T InvalidCast() => (T)InvalidCast(typeof(T)); - - private static object InvalidCast(Type type) => - throw new InvalidCastException($"{nameof(EventInterceptor)} is not convertible to {nameof(type)}"); - - #endregion - } - } -} diff --git a/src/NUnitCommon/nunit.agent.core/Drivers/ProvidedPathsAssemblyResolver.cs b/src/NUnitCommon/nunit.agent.core/Drivers/ProvidedPathsAssemblyResolver.cs deleted file mode 100644 index 42a16afb2..000000000 --- a/src/NUnitCommon/nunit.agent.core/Drivers/ProvidedPathsAssemblyResolver.cs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.IO; -using System.Diagnostics; - -namespace NUnit.Engine.Drivers -{ - public class ProvidedPathsAssemblyResolver - { - private static readonly Logger log = InternalTrace.GetLogger(typeof(ProvidedPathsAssemblyResolver)); - - private static readonly string THIS_ASSEMBLY_LOCATION = Assembly.GetExecutingAssembly().Location; - - public ProvidedPathsAssemblyResolver() - { - _resolutionPaths = new List(); - } - - public void Install() - { - Debug.Assert(AppDomain.CurrentDomain.IsDefaultAppDomain()); - AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolve; - - AddPath(THIS_ASSEMBLY_LOCATION); - } - - public void AddPath(string dirPath) - { - if (!_resolutionPaths.Contains(dirPath)) - { - _resolutionPaths.Add(dirPath); - log.Debug("Added path " + dirPath); - } - } - - public void AddPathFromFile(string filePath) - { - string dirPath = Path.GetDirectoryName(filePath)!; - AddPath(dirPath); - } - - public void RemovePath(string dirPath) - { - _resolutionPaths.Remove(dirPath); - } - - public void RemovePathFromFile(string filePath) - { - string dirPath = Path.GetDirectoryName(filePath)!; - RemovePath(dirPath); - } - - private Assembly? AssemblyResolve(object? sender, ResolveEventArgs args) - { - foreach (string path in _resolutionPaths) - { - string filename = new AssemblyName(args.Name!).Name + ".dll"; - string fullPath = Path.Combine(path, filename); - try - { - if (File.Exists(fullPath)) - { - return Assembly.LoadFrom(fullPath); - } - } - catch (Exception) - { - // Resolution at this path failed. Do not interrupt the process; try the next path. - } - } - - return null; - } - - private readonly List _resolutionPaths; - } -} diff --git a/src/NUnitCommon/nunit.agent.core/NUnitAgent.cs b/src/NUnitCommon/nunit.agent.core/NUnitAgent.cs deleted file mode 100644 index 0d7a56c89..000000000 --- a/src/NUnitCommon/nunit.agent.core/NUnitAgent.cs +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using System; -using System.Diagnostics; -using System.IO; -using System.Security; -using System.Reflection; -using NUnit.Common; -using NUnit.Engine.Agents; -using NUnit.Engine.Communication.Transports.Tcp; - -namespace NUnit.Agents -{ - public class NUnitAgent - { - private static Process? AgencyProcess; - private static RemoteTestAgent? Agent; -#if NET6_0_OR_GREATER - private static readonly int _pid = Environment.ProcessId; -#else - private static readonly int _pid = Process.GetCurrentProcess().Id; -#endif - private static readonly Logger log = InternalTrace.GetLogger(typeof(TestAgent)); - - /// - /// The main entry point for the application. - /// - [STAThread] - public static void Execute(string[] args) - { - var options = new AgentOptions(args); - var logName = $"nunit-agent_{_pid}.log"; - - InternalTrace.Initialize(Path.Combine(options.WorkDirectory, logName), options.TraceLevel); - log.Info($"{typeof(TAgent).Name} process {_pid} starting"); - log.Info($" Agent Path: {Assembly.GetExecutingAssembly().Location}"); - - if (options.DebugAgent || options.DebugTests) - TryLaunchDebugger(); - - if (!string.IsNullOrEmpty(options.AgencyUrl)) - RegisterAndWaitForCommands(options); - else if (options.Files.Count != 0) - new AgentDirectRunner(options).ExecuteTestsDirectly(); - else - throw new ArgumentException("No file specified for direct execution"); - } - - private static void RegisterAndWaitForCommands(AgentOptions options) - { - log.Info($" AgentId: {options.AgentId}"); - log.Info($" AgencyUrl: {options.AgencyUrl}"); - log.Info($" AgencyPid: {options.AgencyPid}"); - - if (!string.IsNullOrEmpty(options.AgencyPid)) - LocateAgencyProcess(options.AgencyPid); - - log.Info("Starting RemoteTestAgent"); - Agent = new RemoteTestAgent(options.AgentId); - Agent.Transport = new TestAgentTcpTransport(Agent, options.AgencyUrl); - - try - { - if (Agent.Start()) - WaitForStop(Agent, AgencyProcess.ShouldNotBeNull()); - else - { - log.Error("Failed to start RemoteTestAgent"); - Environment.Exit(AgentExitCodes.FAILED_TO_START_REMOTE_AGENT); - } - } - catch (Exception ex) - { - log.Error("Exception in RemoteTestAgent. {0}", ExceptionHelper.BuildMessageAndStackTrace(ex)); - Environment.Exit(AgentExitCodes.UNEXPECTED_EXCEPTION); - } - log.Info("Agent process {0} exiting cleanly", _pid); - - Environment.Exit(AgentExitCodes.OK); - } - - private static void LocateAgencyProcess(string agencyPid) - { - var agencyProcessId = int.Parse(agencyPid); - try - { - AgencyProcess = Process.GetProcessById(agencyProcessId); - } - catch (Exception e) - { - log.Error($"Unable to connect to agency process with PID: {agencyProcessId}"); - log.Error($"Failed with exception: {e.Message} {e.StackTrace}"); - Environment.Exit(AgentExitCodes.UNABLE_TO_LOCATE_AGENCY); - } - } - - private static void WaitForStop(RemoteTestAgent agent, Process agencyProcess) - { - log.Debug("Waiting for stopSignal"); - - while (!agent.WaitForStop(500)) - { - if (agencyProcess.HasExited) - { - log.Error("Parent process has been terminated."); - Environment.Exit(AgentExitCodes.PARENT_PROCESS_TERMINATED); - } - } - - log.Debug("Stop signal received"); - } - - private static void TryLaunchDebugger() - { - if (Debugger.IsAttached) - return; - - try - { - Debugger.Launch(); - } - catch (SecurityException se) - { - if (InternalTrace.Initialized) - { - log.Error($"System.Security.Permissions.UIPermission is not set to start the debugger. {se} {se.StackTrace}"); - } - Environment.Exit(AgentExitCodes.DEBUGGER_SECURITY_VIOLATION); - } - catch (NotImplementedException nie) //Debugger is not implemented on mono - { - if (InternalTrace.Initialized) - { - log.Error($"Debugger is not available on all platforms. {nie} {nie.StackTrace}"); - } - Environment.Exit(AgentExitCodes.DEBUGGER_NOT_IMPLEMENTED); - } - } - } -} diff --git a/src/NUnitCommon/nunit.agent.core/RunTestsCallbackHandler.cs b/src/NUnitCommon/nunit.agent.core/RunTestsCallbackHandler.cs deleted file mode 100644 index a5c279d66..000000000 --- a/src/NUnitCommon/nunit.agent.core/RunTestsCallbackHandler.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -#if NETFRAMEWORK -using System; -using System.Diagnostics; -using System.Web.UI; - -namespace NUnit.Engine -{ - public class RunTestsCallbackHandler : MarshalByRefObject, ICallbackEventHandler - { - private readonly ITestEventListener? _listener; - - public string? Result { get; private set; } - - public RunTestsCallbackHandler(ITestEventListener? listener) - { - _listener = listener; - } - - public override object InitializeLifetimeService() - { - return null!; - } - - public string GetCallbackResult() - { - throw new NotImplementedException(); - } - - public void RaiseCallbackEvent(string eventArgument) - { - if (IsFinalResult(eventArgument)) - Result = eventArgument; - else - ReportProgress(eventArgument); - } - - private void ReportProgress(string state) - { - _listener?.OnTestEvent(state); - } - - private static bool IsFinalResult(string eventArgument) - { - // TODO: If we add a prefix to the final result in the next framework - // release, then we can immediately recognize the final result but we - // would need to continue to examine the non-final result in case the - // the framework in use were an older version. Building in more knowledge - // of framework versions is probably not a good idea, since it would be - // potentially fragile as changes were made. - - // Eliminate all events except for test-suite - if (!eventArgument.StartsWith(" 0; - } - } -} -#endif \ No newline at end of file diff --git a/src/NUnitCommon/nunit.agent.core/Runners/DomainDetailsBuilder.cs b/src/NUnitCommon/nunit.agent.core/Runners/DomainDetailsBuilder.cs deleted file mode 100644 index 868f67d6b..000000000 --- a/src/NUnitCommon/nunit.agent.core/Runners/DomainDetailsBuilder.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; - -namespace NUnit.Engine -{ - /// - /// DomainDetailsBuilder provides human readable information on - /// an application domain, to assist with debugging. - /// - internal static class DomainDetailsBuilder - { - private static readonly Logger Log = InternalTrace.GetLogger(nameof(DomainDetailsBuilder)); - - /// - /// Get human readable string containing details of application domain. - /// - /// Application domain to get details on. - /// An optional overall error message. - public static string DetailsFor(AppDomain domain, string? errMsg = null) - { - var sb = new StringBuilder(); - if (errMsg is not null) - sb.AppendLine(errMsg); - - try - { - sb.AppendLine($"Application domain name: {domain.FriendlyName}"); - sb.AppendLine($"Application domain BaseDirectory: {domain.BaseDirectory}"); - - var reflectionLoadedAssemblies = new List(domain.ReflectionOnlyGetAssemblies()); - - if (reflectionLoadedAssemblies.Count != 0) - { - sb.AppendLine("--- Assemblies loaded in current application domain via reflection ---"); - foreach (var assembly in reflectionLoadedAssemblies) - WriteAssemblyInformation(sb, assembly); - } - } - catch (AppDomainUnloadedException ex) - { - sb.AppendLine("Application domain was unloaded before all details could be read."); - Log.Error(ExceptionHelper.BuildMessageAndStackTrace(ex)); - } - catch (Exception ex) - { - sb.AppendLine($"Error trying to read application domain details: {ex.Message}"); - Log.Error(ExceptionHelper.BuildMessageAndStackTrace(ex)); - } - return sb.ToString(); - } - - private static void WriteAssemblyInformation(StringBuilder sb, Assembly assembly) - { - sb.AppendLine(assembly.FullName); - sb.AppendLine(assembly.ImageRuntimeVersion); - sb.AppendLine(assembly.Location); - sb.AppendLine("-----------------"); - } - } -} diff --git a/src/NUnitCommon/nunit.agent.core/Runners/DomainManager.cs b/src/NUnitCommon/nunit.agent.core/Runners/DomainManager.cs deleted file mode 100644 index 12896cc5a..000000000 --- a/src/NUnitCommon/nunit.agent.core/Runners/DomainManager.cs +++ /dev/null @@ -1,332 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt -#if NETFRAMEWORK -using System; -using System.IO; -using System.Collections.Generic; -using System.Text; -using System.Threading; -using System.Reflection; -using System.Diagnostics; -using System.Security; -using System.Security.Policy; -using System.Security.Principal; -using System.Linq; -using NUnit.Common; - -namespace NUnit.Engine.Runners -{ - /// - /// The DomainManager class handles the creation and unloading - /// of domains as needed and keeps track of all existing domains. - /// - public class DomainManager - { - private static readonly Logger log = InternalTrace.GetLogger(typeof(DomainManager)); - - private static readonly PropertyInfo TargetFrameworkNameProperty = - typeof(AppDomainSetup).GetProperty("TargetFrameworkName", BindingFlags.Public | BindingFlags.Instance)!; - - /// - /// Construct an application domain for running a test package - /// - /// The TestPackage to be run - public AppDomain CreateDomain(TestPackage package) - { - AppDomainSetup setup = CreateAppDomainSetup(package); - - string hashCode = string.Empty; - if (package.Name is not null) - { - hashCode = package.Name.GetHashCode().ToString("x") + "-"; - } - - string domainName = "domain-" + hashCode + package.Name; - Evidence evidence = new Evidence(AppDomain.CurrentDomain.Evidence); - - log.Info("Creating application domain " + domainName); - - AppDomain runnerDomain = AppDomain.CreateDomain(domainName, evidence, setup); - - // Set PrincipalPolicy for the domain if called for in the package settings - string policyName = package.Settings.GetValueOrDefault(SettingDefinitions.PrincipalPolicy); - if (policyName != string.Empty) - { - PrincipalPolicy policy = (PrincipalPolicy)Enum.Parse(typeof(PrincipalPolicy), policyName); - - runnerDomain.SetPrincipalPolicy(policy); - } - - return runnerDomain; - } - - // Made separate and internal for testing - private static AppDomainSetup CreateAppDomainSetup(TestPackage package) - { - AppDomainSetup setup = new AppDomainSetup(); - - //For parallel tests, we need to use distinct application name - setup.ApplicationName = "Tests" + "_" + Environment.TickCount; - - string appBase = GetApplicationBase(package).ShouldNotBeNull(); - setup.ApplicationBase = appBase; - setup.ConfigurationFile = GetConfigFile(appBase, package); - setup.PrivateBinPath = GetPrivateBinPath(appBase, package); - - if (!string.IsNullOrEmpty(package.FullName)) - { - // Setting the target framework is only supported when running with - // multiple AppDomains, one per assembly. - // TODO: Remove this limitation - - // .NET versions greater than v4.0 report as v4.0, so look at - // the TargetFrameworkAttribute on the assembly if it exists - // If property is null, .NET 4.5+ is not installed, so there is no need - if (TargetFrameworkNameProperty is not null) - { - var frameworkName = package.Settings.GetValueOrDefault(SettingDefinitions.ImageTargetFrameworkName); - if (frameworkName != string.Empty) - TargetFrameworkNameProperty.SetValue(setup, frameworkName, null); - } - } - - if (package.Settings.GetValueOrDefault(SettingDefinitions.ShadowCopyFiles)) - { - setup.ShadowCopyFiles = "true"; - setup.ShadowCopyDirectories = setup.ApplicationBase; - } - else - setup.ShadowCopyFiles = "false"; - - return setup; - } - - public static void Unload(AppDomain domain) - { - new DomainUnloader(domain).Unload(); - } - - private class DomainUnloader - { - private readonly AppDomain _domain; - private Thread? _unloadThread; - private NUnitEngineException? _unloadException; - - public DomainUnloader(AppDomain domain) - { - _domain = domain; - } - - public void Unload() - { - _unloadThread = new Thread(new ThreadStart(UnloadOnThread)); - _unloadThread.Start(); - - var timeout = TimeSpan.FromSeconds(30); - - if (!_unloadThread.Join(timeout)) - { - var msg = DomainDetailsBuilder.DetailsFor(_domain, - $"Unable to unload application domain: unload thread timed out after {timeout.TotalSeconds} seconds."); - - log.Error(msg); - Kill(_unloadThread); - - throw new NUnitEngineUnloadException(msg); - } - - if (_unloadException is not null) - throw new NUnitEngineUnloadException("Exception encountered unloading application domain", _unloadException); - } - - private void UnloadOnThread() - { - try - { - // Uncomment to simulate an error in unloading - //throw new CannotUnloadAppDomainException("Testing: simulated unload error"); - - // Uncomment to simulate a timeout while unloading - //while (true) ; - - AppDomain.Unload(_domain); - } - catch (Exception ex) - { - // We assume that the tests did something bad and just leave - // the orphaned AppDomain "out there". - var msg = DomainDetailsBuilder.DetailsFor(_domain, - $"Exception encountered unloading application domain: {ex.Message}"); - - _unloadException = new NUnitEngineException(msg); - log.Error(msg); - } - } - } - - /// - /// Figure out the ApplicationBase for a package - /// - /// The package - /// The ApplicationBase - public static string? GetApplicationBase(TestPackage package) - { - Guard.ArgumentNotNull(package); - - var appBase = package.Settings.GetValueOrDefault(SettingDefinitions.BasePath); - - if (string.IsNullOrEmpty(appBase)) - appBase = string.IsNullOrEmpty(package.FullName) - ? GetCommonAppBase(package.SubPackages) - : Path.GetDirectoryName(package.FullName); - - if (!string.IsNullOrEmpty(appBase)) - { - char lastChar = appBase[appBase.Length - 1]; - if (lastChar != Path.DirectorySeparatorChar && lastChar != Path.AltDirectorySeparatorChar) - appBase += Path.DirectorySeparatorChar; - } - - return appBase; - } - - public static string? GetConfigFile(string appBase, TestPackage package) - { - Guard.ArgumentNotNullOrEmpty(appBase); - Guard.ArgumentNotNull(package); - - // Use provided setting if available - string configFile = package.Settings.GetValueOrDefault(SettingDefinitions.ConfigurationFile); - if (configFile != string.Empty) - return Path.Combine(appBase, configFile); - - // The ProjectService adds any project config to the settings. - // So, at this point, we only want to handle assemblies or an - // anonymous package created from the command-line. - string? fullName = package.FullName; - if (IsExecutable(fullName)) - return fullName + ".config"; - - // Command-line package gets no config unless it's a single assembly - if (string.IsNullOrEmpty(fullName) && package.SubPackages.Count == 1) - { - fullName = package.SubPackages[0].FullName; - if (IsExecutable(fullName)) - return fullName + ".config"; - } - - // No config file will be specified - return null; - } - - private static bool IsExecutable(string? fileName) - { - if (string.IsNullOrEmpty(fileName)) - return false; - - string ext = Path.GetExtension(fileName).ToLower(); - return ext == ".dll" || ext == ".exe"; - } - - public static string? GetCommonAppBase(IList packages) - { - var assemblies = new List(); - - // All subpackages have full names, but this is a public method in a public class so we have no control. - foreach (var package in packages.Where(p => p.FullName is not null)) - assemblies.Add(package.FullName!); - - return GetCommonAppBase(assemblies); - } - - public static string? GetCommonAppBase(IList assemblies) - { - string? commonBase = null; - - foreach (string assembly in assemblies) - { - string? dir = Path.GetDirectoryName(Path.GetFullPath(assembly))!; - if (commonBase is null) - commonBase = dir; - else - while (commonBase is not null && !PathUtils.SamePathOrUnder(commonBase, dir)) - commonBase = Path.GetDirectoryName(commonBase)!; - } - - return commonBase; - } - - public static string? GetPrivateBinPath(string basePath, string fileName) - { - return GetPrivateBinPath(basePath, new string[] { fileName }); - } - - public static string? GetPrivateBinPath(string appBase, TestPackage package) - { - var binPath = package.Settings.GetValueOrDefault(SettingDefinitions.PrivateBinPath); - - if (binPath == string.Empty || package.Settings.GetValueOrDefault(SettingDefinitions.AutoBinPath)) - binPath = package.SubPackages.Count > 0 - ? GetPrivateBinPath(appBase, package.SubPackages) - : package.FullName is not null - ? GetPrivateBinPath(appBase, package.FullName) - : null; - - return binPath; - } - - public static string? GetPrivateBinPath(string basePath, IList packages) - { - var assemblies = new List(); - foreach (var package in packages.Where(p => p.FullName is not null)) - assemblies.Add(package.FullName!); - - return GetPrivateBinPath(basePath, assemblies); - } - - public static string? GetPrivateBinPath(string basePath, IList assemblies) - { - List dirList = new List(); - StringBuilder sb = new StringBuilder(200); - - foreach (string assembly in assemblies) - { - string? dir = PathUtils.RelativePath( - Path.GetFullPath(basePath), - Path.GetDirectoryName(Path.GetFullPath(assembly))!); - if (dir is not null && dir != string.Empty && dir != "." && !dirList.Contains(dir)) - { - dirList.Add(dir); - if (sb.Length > 0) - sb.Append(Path.PathSeparator); - sb.Append(dir); - } - } - - return sb.Length == 0 ? null : sb.ToString(); - } - - /// - /// Do our best to kill a thread, passing state info - /// - /// The thread to kill - private static void Kill(Thread thread) - { - try - { - thread.Abort(); - } - catch (ThreadStateException) - { - // Although obsolete, this use of Resume() takes care of - // the odd case where a ThreadStateException is received. -#pragma warning disable 0618, 0612 // Thread.Resume has been deprecated - thread.Resume(); -#pragma warning restore 0618, 0612 // Thread.Resume has been deprecated - } - - if ((thread.ThreadState & System.Threading.ThreadState.WaitSleepJoin) != 0) - thread.Interrupt(); - } - } -} -#endif \ No newline at end of file diff --git a/src/NUnitCommon/nunit.agent.core/Runners/LocalTestRunner.cs b/src/NUnitCommon/nunit.agent.core/Runners/LocalTestRunner.cs deleted file mode 100644 index ded26d930..000000000 --- a/src/NUnitCommon/nunit.agent.core/Runners/LocalTestRunner.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using System; - -namespace NUnit.Engine.Runners -{ - /// - /// LocalTestRunner runs tests in the current application domain. - /// - public class LocalTestRunner : TestAgentRunner - { - public LocalTestRunner(TestPackage package) : base(package) - { - TestDomain = AppDomain.CurrentDomain; - } - } -} diff --git a/src/NUnitCommon/nunit.agent.core/Runners/TestAgentRunner.cs b/src/NUnitCommon/nunit.agent.core/Runners/TestAgentRunner.cs deleted file mode 100644 index 149415949..000000000 --- a/src/NUnitCommon/nunit.agent.core/Runners/TestAgentRunner.cs +++ /dev/null @@ -1,310 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -using NUnit.Common; -using NUnit.Engine.Drivers; -using NUnit.Engine.Extensibility; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Linq; -using System.Xml; -//using static NUnit.Engine.Drivers.NUnitFrameworkDriver; - -namespace NUnit.Engine.Runners -{ - /// - /// TestAgentRunner is the abstract base for runners used by agents, which - /// deal directly with a framework driver. It loads and runs tests in a single - /// assembly, creating an to do so. - /// - public abstract class TestAgentRunner : ITestEngineRunner - { - private readonly Logger log = InternalTrace.GetLogger(typeof(TestAgentRunner)); - - private readonly ProvidedPathsAssemblyResolver? _assemblyResolver; - - private IFrameworkDriver? _driver; - - private static SettingDefinition[] _frameworkSettingDefinitions = [ - SettingDefinitions.DefaultTimeout, - SettingDefinitions.DefaultCulture, - SettingDefinitions.DefaultUICulture, - SettingDefinitions.InternalTraceWriter, - SettingDefinitions.LOAD, - SettingDefinitions.NumberOfTestWorkers, - SettingDefinitions.RandomSeed, - SettingDefinitions.StopOnError, - SettingDefinitions.ThrowOnEachFailureUnderDebugger, - SettingDefinitions.SynchronousEvents, - SettingDefinitions.DefaultTestNamePattern, - SettingDefinitions.TestParameters, - SettingDefinitions.TestParametersDictionary, - SettingDefinitions.RunOnMainThread - ]; - - protected AppDomain? TestDomain { get; set; } - - // Used to inject DriverService for testing - protected IDriverService? DriverService { get; set; } - - /// - /// The TestPackage for which this is the runner - /// - protected TestPackage TestPackage { get; } - - /// - /// The result of the last call to Load - /// - protected TestEngineResult? LoadResult { get; set; } - - /// - /// Gets an indicator of whether the package has been loaded. - /// - public bool IsPackageLoaded - { - get { return LoadResult is not null; } - } - - public TestAgentRunner(TestPackage package) - { - Guard.ArgumentNotNull(package); - var assemblyPackages = package.Select(p => !p.HasSubPackages); - Guard.ArgumentValid(assemblyPackages.Count == 1, "TestAgentRunner requires a package with a single assembly", nameof(package)); - - TestPackage = package; - - // Bypass the resolver if not in the default AppDomain. This prevents trying to use the resolver within - // NUnit's own automated tests (in a test AppDomain) which does not make sense anyway. - if (AppDomain.CurrentDomain.IsDefaultAppDomain()) - { - _assemblyResolver = new ProvidedPathsAssemblyResolver(); - _assemblyResolver.Install(); - } - } - - /// - /// Explores a previously loaded TestPackage and returns information - /// about the tests found. - /// - /// The TestFilter to be used to select tests - /// - /// A TestEngineResult. - /// - public TestEngineResult Explore(TestFilter filter) - { - try - { - var result = new TestEngineResult(GetLoadedDriver().Explore(filter.Text)); - -#if NETCOREAPP - if (TestPackage.Settings.HasSetting(SettingDefinitions.ListResolutionStats)) - InsertResolutionStatistics(result.Xml); -#endif - - return result; - } - catch (Exception ex) when (!(ex is NUnitEngineException)) - { - throw new NUnitEngineException("An exception occurred in the driver while exploring tests.", ex); - } - } - - /// - /// Load a TestPackage for exploration or execution - /// - /// A TestEngineResult. - public virtual TestEngineResult Load() - { - Guard.OperationValid(TestDomain is not null, "TestDomain is not set"); - - var result = new TestEngineResult(); - - // The TestAgentRunner constructor guarantees that TestPackage has - // only a single assembly. - var assemblyPackage = TestPackage.Select(p => !p.HasSubPackages).First(); - - if (DriverService is null) - DriverService = new DriverService(); - - var testFile = assemblyPackage.FullName!; // We know it's an assembly - var packageSettings = assemblyPackage.Settings; - - string? targetFramework = packageSettings.GetValueOrDefault(SettingDefinitions.ImageTargetFrameworkName); - bool skipNonTestAssemblies = packageSettings.GetValueOrDefault(SettingDefinitions.SkipNonTestAssemblies); - - if (_assemblyResolver is not null && !TestDomain.IsDefaultAppDomain() - && packageSettings.GetValueOrDefault(SettingDefinitions.ImageRequiresDefaultAppDomainAssemblyResolver)) - { - // It's OK to do this in the loop because the Add method - // checks to see if the path is already present. - _assemblyResolver.AddPathFromFile(testFile); - } - - _driver = DriverService.GetDriver(TestDomain, assemblyPackage, testFile, targetFramework, skipNonTestAssemblies); - var settingsDictionary = new Dictionary(); - - foreach (var settingDefinition in _frameworkSettingDefinitions) - { - string key = settingDefinition.Name; - if (packageSettings.HasSetting(key)) - settingsDictionary.Add( - key, packageSettings.GetSetting(key)); - } - - try - { - LoadResult = new TestEngineResult(_driver.Load(testFile, settingsDictionary)); - -#if NETCOREAPP - if (TestPackage.Settings.HasSetting(SettingDefinitions.ListResolutionStats)) - InsertResolutionStatistics(LoadResult.Xml); -#endif - - return LoadResult; - } - catch (Exception ex) when (ex is not NUnitEngineException) - { - throw new NUnitEngineException("An exception occurred in the driver while loading tests.", ex); - } - } - - public virtual void Unload() - { - } - - public TestEngineResult Reload() => Load(); - - /// - /// Count the test cases that would be run under - /// the specified filter. - /// - /// A TestFilter - /// The count of test cases - public int CountTestCases(TestFilter filter) - { - try - { - return GetLoadedDriver().CountTestCases(filter.Text); - } - catch (Exception ex) when (!(ex is NUnitEngineException)) - { - throw new NUnitEngineException("An exception occurred in the driver while counting test cases.", ex); - } - } - - /// - /// Run the tests in the loaded TestPackage. - /// - /// An ITestEventHandler to receive events - /// A TestFilter used to select tests - /// - /// A TestEngineResult giving the result of the test execution - /// - public TestEngineResult Run(ITestEventListener? listener, TestFilter filter) - { - try - { - log.Debug($"Running"); - var result = new TestEngineResult(GetLoadedDriver().Run(listener, filter.Text)); - -#if NETCOREAPP - if (TestPackage.Settings.HasSetting(SettingDefinitions.ListResolutionStats)) - InsertResolutionStatistics(result.Xml); -#endif - - return result; - } - catch (Exception ex) when (!(ex is NUnitEngineException)) - { - string msg = "An exception occurred in the driver while running tests."; - log.Error(msg, ex); - throw new NUnitEngineException(msg, ex); - } - } - - public AsyncTestEngineResult RunAsync(ITestEventListener? listener, TestFilter filter) - { - var testRun = new AsyncTestEngineResult(); - - using (var worker = new BackgroundWorker()) - { - worker.DoWork += (s, ea) => - { - var result = Run(listener, filter); - testRun.SetResult(result); - }; - worker.RunWorkerAsync(); - } - - return testRun; - } - - /// - /// Request the current test run to stop. If no tests are running, - /// the call is ignored. - /// - public void RequestStop() => GetLoadedDriver().RequestStop(); - - /// - /// Force the current test run to stop, killing threads or processes if necessary. - /// If no tests are running, the call is ignored. - /// - public void ForcedStop() => GetLoadedDriver().ForcedStop(); - - private IFrameworkDriver GetLoadedDriver() - { - if (!IsPackageLoaded) - LoadResult = Load(); - - return _driver.ShouldNotBeNull(); - } - -#if NETCOREAPP3_1_OR_GREATER - private void InsertResolutionStatistics(XmlNode resultNode) - { - log.Debug("Inserting ResolutionStatistics"); - var doc = resultNode.OwnerDocument; - if (doc is null) - return; - - log.Debug("Creating resolver-stats element"); - XmlNode resolverStatistics = doc.CreateElement("resolver-stats"); - resultNode.InsertAfter(resolverStatistics, null); - log.Debug("Inserted resolver-stats element"); - - var nunitDriver = _driver as NUnitFrameworkDriver; - foreach (var strategy in nunitDriver?.ResolutionStrategies!) - { - log.Debug($"Processing stats for {strategy.Name}"); - XmlNode resolver = doc.CreateElement("resolver"); - log.Debug(" Created resolver element"); - resolver.AddAttribute("name", strategy.Name); - resolver.AddAttribute("calls", strategy.Calls.ToString()); - resolver.AddAttribute("resolved", strategy.Resolved.ToString()); - resolverStatistics.AppendChild(resolver); - log.Debug(" Appended resolver element"); - } - } -#endif - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected bool _disposed = false; - - protected virtual void Dispose(bool disposing) - { - if (!_disposed) - { - if (disposing) - Unload(); - - _disposed = true; - } - } - } -} \ No newline at end of file diff --git a/src/NUnitCommon/nunit.agent.core/Runners/TestDomainRunner.cs b/src/NUnitCommon/nunit.agent.core/Runners/TestDomainRunner.cs deleted file mode 100644 index b48a9ff65..000000000 --- a/src/NUnitCommon/nunit.agent.core/Runners/TestDomainRunner.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -#if NETFRAMEWORK - -namespace NUnit.Engine.Runners -{ - /// - /// TestDomainRunner loads and runs tests in a separate - /// domain whose lifetime it controls. - /// - public class TestDomainRunner : TestAgentRunner - { - private static readonly Logger log = InternalTrace.GetLogger(typeof(TestDomainRunner)); - - private readonly DomainManager _domainManager; - - public TestDomainRunner(TestPackage package) : base(package) - { - _domainManager = new DomainManager(); - } - - public override TestEngineResult Load() - { - TestDomain = _domainManager.CreateDomain(TestPackage); - return base.Load(); - } - - /// - /// Unload any loaded TestPackage as well as the application domain. - /// - public override void Unload() - { - if (this.TestDomain is not null) - { - DomainManager.Unload(this.TestDomain); - this.TestDomain = null; - } - } - } -} -#endif \ No newline at end of file diff --git a/src/NUnitCommon/nunit.agent.core/TestAssemblyLoadContext.cs b/src/NUnitCommon/nunit.agent.core/TestAssemblyLoadContext.cs deleted file mode 100644 index 354d44ed9..000000000 --- a/src/NUnitCommon/nunit.agent.core/TestAssemblyLoadContext.cs +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -#if NETCOREAPP3_1_OR_GREATER && false - -using System.Reflection; -using System.Runtime.InteropServices; -using System.Runtime.Loader; -using System.IO; -using System; -using System.Linq; -using System.Collections.Generic; - -namespace NUnit.Engine.Internal -{ - internal sealed class TestAssemblyLoadContext : AssemblyLoadContext - { - private static readonly Logger log = InternalTrace.GetLogger(typeof(TestAssemblyLoadContext)); - - private readonly string _basePath; - private readonly TestAssemblyResolver _resolver; - private readonly System.Runtime.Loader.AssemblyDependencyResolver _runtimeResolver; - - public TestAssemblyLoadContext(string testAssemblyPath) - { - _resolver = new TestAssemblyResolver(this, testAssemblyPath); - _basePath = Path.GetDirectoryName(testAssemblyPath)!; - _runtimeResolver = new AssemblyDependencyResolver(testAssemblyPath); -#if NET8_0_OR_GREATER - AppContext.SetData("APP_CONTEXT_BASE_DIRECTORY", _basePath); -#endif - } - - internal List ResolutionStrategies => _resolver.ResolutionStrategies; - - protected override Assembly? Load(AssemblyName name) - { - log.Debug("Loading {0} assembly", name); - - var loadedAssembly = base.Load(name); - if (loadedAssembly is not null) - { - log.Info("Assembly {0} ({1}) is loaded using default base.Load()", name, GetAssemblyLocationInfo(loadedAssembly)); - return loadedAssembly; - } - - var runtimeResolverPath = _runtimeResolver.ResolveAssemblyToPath(name); - if (string.IsNullOrEmpty(runtimeResolverPath) == false && - File.Exists(runtimeResolverPath)) - { - loadedAssembly = LoadFromAssemblyPath(runtimeResolverPath); - } - - if (loadedAssembly is not null) - { - log.Info("Assembly {0} ({1}) is loaded using the deps.json info", name, GetAssemblyLocationInfo(loadedAssembly)); - return loadedAssembly; - } - - loadedAssembly = _resolver.Resolve(this, name); - if (loadedAssembly is not null) - { - log.Info("Assembly {0} ({1}) is loaded using the TestAssembliesResolver", name, GetAssemblyLocationInfo(loadedAssembly)); - - return loadedAssembly; - } - - // Load assemblies that are dependencies, and in the same folder as the test assembly, - // but are not fully specified in test assembly deps.json file. This happens when the - // dependencies reference in the csproj file has CopyLocal=false, and for example, the - // reference is a projectReference and has the same output directory as the parent. - string assemblyPath = Path.Combine(_basePath, name.Name + ".dll"); - if (File.Exists(assemblyPath)) - { - loadedAssembly = LoadFromAssemblyPath(assemblyPath); - } - - if (loadedAssembly is not null) - { - log.Info("Assembly {0} ({1}) is loaded using base path", name, GetAssemblyLocationInfo(loadedAssembly)); - return loadedAssembly; - } - - return null; - } - - protected override IntPtr LoadUnmanagedDll(string name) - { - log.Debug("Loading {0} unmanaged dll", name); - - IntPtr loadedDllHandle = base.LoadUnmanagedDll(name); - if (loadedDllHandle != IntPtr.Zero) - { - log.Info("Unmanaged DLL {0} is loaded using default base.LoadUnmanagedDll()", name); - return loadedDllHandle; - } - - string? runtimeResolverPath = _runtimeResolver.ResolveUnmanagedDllToPath(name); - if (string.IsNullOrEmpty(runtimeResolverPath) == false && - File.Exists(runtimeResolverPath)) - { - loadedDllHandle = LoadUnmanagedDllFromPath(runtimeResolverPath); - } - - if (loadedDllHandle != IntPtr.Zero) - { - log.Info("Unmanaged DLL {0} ({1}) is loaded using the deps.json info", name, runtimeResolverPath!); - return loadedDllHandle; - } - - string unmanagedDllPath = Path.Combine(_basePath, name + ".dll"); - if (File.Exists(unmanagedDllPath)) - { - loadedDllHandle = LoadUnmanagedDllFromPath(unmanagedDllPath); - } - - if (loadedDllHandle != IntPtr.Zero) - { - log.Info("Unmanaged DLL {0} ({1}) is loaded using base path", name, unmanagedDllPath); - return loadedDllHandle; - } - - return IntPtr.Zero; - } - - private static string GetAssemblyLocationInfo(Assembly assembly) - { - if (assembly.IsDynamic) - { - return $"Dynamic {assembly.FullName}"; - } - - if (string.IsNullOrEmpty(assembly.Location)) - { - return $"No location for {assembly.FullName}"; - } - - return $"{assembly.FullName} from {assembly.Location}"; - } - } -} - -#endif diff --git a/src/NUnitCommon/nunit.agent.core/TestAssemblyResolver.cs b/src/NUnitCommon/nunit.agent.core/TestAssemblyResolver.cs deleted file mode 100644 index e983d41ed..000000000 --- a/src/NUnitCommon/nunit.agent.core/TestAssemblyResolver.cs +++ /dev/null @@ -1,292 +0,0 @@ -// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt - -#if NETCOREAPP3_1_OR_GREATER - -using Microsoft.Extensions.DependencyModel; -using Microsoft.Extensions.DependencyModel.Resolution; -using Microsoft.Win32; -using NUnit.Common; -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Runtime.Loader; -using System.Xml.Linq; -using TestCentric.Metadata; - -namespace NUnit.Engine.Internal -{ - internal sealed class TestAssemblyResolver : IDisposable - { - private static readonly Logger log = InternalTrace.GetLogger(typeof(TestAssemblyResolver)); - - private readonly AssemblyLoadContext _loadContext; - private readonly string _basePath; - private readonly AssemblyDependencyResolver _assemblyDependencyResolver; - - // Our Strategies for resolving references - internal List ResolutionStrategies = new List(); - - public TestAssemblyResolver(AssemblyLoadContext loadContext, string testAssemblyPath) - { - _loadContext = loadContext; - _basePath = Path.GetDirectoryName(testAssemblyPath).ShouldNotBeNull(); - _assemblyDependencyResolver = new AssemblyDependencyResolver(testAssemblyPath); -#if NET8_0_OR_GREATER - AppContext.SetData("APP_CONTEXT_BASE_DIRECTORY", _basePath); -#endif - - InitializeResolutionStrategies(loadContext, testAssemblyPath); - - _loadContext.Resolving += OnResolving; - } - - private void InitializeResolutionStrategies(AssemblyLoadContext loadContext, string testAssemblyPath) - { - // Decide whether to try WindowsDeskTop and/or AspNetCore runtimes before any others. - // We base this on direct references only, so we will eventually try each of them - // later in case there are any indirect references. - AssemblyDefinition assemblyDef = AssemblyDefinition.ReadAssembly(testAssemblyPath); - bool tryWindowsDesktopFirst = false; - bool tryAspNetCoreFirst = false; - foreach (var reference in assemblyDef.MainModule.GetTypeReferences()) - { - string fn = reference.FullName; - if (fn.StartsWith("System.Windows.") || fn.StartsWith("PresentationFramework")) - tryWindowsDesktopFirst = true; - if (fn.StartsWith("Microsoft.AspNetCore.")) - tryAspNetCoreFirst = true; - } - - // Initialize the list of ResolutionStrategies in the best order depending on - // what we learned from examining direct references. - if (tryWindowsDesktopFirst) - ResolutionStrategies.Add(new WindowsDesktopStrategy(false)); - if (tryAspNetCoreFirst) - ResolutionStrategies.Add(new AspNetCoreStrategy(false)); - - ResolutionStrategies.Add(new TrustedPlatformAssembliesStrategy()); - ResolutionStrategies.Add(new RuntimeLibrariesStrategy(loadContext, testAssemblyPath)); - - if (!tryWindowsDesktopFirst) - ResolutionStrategies.Add(new WindowsDesktopStrategy(false)); - if (!tryAspNetCoreFirst) - ResolutionStrategies.Add(new AspNetCoreStrategy(false)); - } - - public void Dispose() - { - _loadContext.Resolving -= OnResolving; - } - - private Assembly? OnResolving(AssemblyLoadContext loadContext, AssemblyName assemblyName) - { - Guard.ArgumentNotNull(loadContext); - - var runtimeResolverPath = _assemblyDependencyResolver.ResolveAssemblyToPath(assemblyName); - if (!string.IsNullOrEmpty(runtimeResolverPath) && File.Exists(runtimeResolverPath)) - { - var loadedAssembly = _loadContext.LoadFromAssemblyPath(runtimeResolverPath); - if (loadedAssembly is not null) - { - log.Info($"Assembly {assemblyName} ({loadedAssembly}) is loaded using the deps.json info"); - return loadedAssembly; - } - } - - foreach (var strategy in ResolutionStrategies) - { - strategy.Calls++; - if (strategy.TryToResolve(loadContext, assemblyName, out Assembly? loadedAssembly)) - { - log.Info($"Assembly {assemblyName} ({GetAssemblyLocationInfo(loadedAssembly)}) is loaded using strategy {strategy.Name}"); - strategy.Resolved++; - return loadedAssembly; - } - } - - log.Info("Cannot resolve assembly '{0}'", assemblyName); - return null; - } - - private static string GetAssemblyLocationInfo(Assembly assembly) - { - if (assembly.IsDynamic) - { - return $"Dynamic {assembly.FullName}"; - } - - if (string.IsNullOrEmpty(assembly.Location)) - { - return $"No location for {assembly.FullName}"; - } - - return $"{assembly.FullName} from {assembly.Location}"; - } - } - - #region ResolutionStrategy Classes - - public abstract class ResolutionStrategy - { - public string Name => GetType().Name; - public int Calls { get; set; } - public int Resolved { get; set; } - - public abstract bool TryToResolve( - AssemblyLoadContext loadContext, AssemblyName assemblyName, [NotNullWhen(true)] out Assembly? loadedAssembly); - } - - public class TrustedPlatformAssembliesStrategy : ResolutionStrategy - { - private static readonly Logger log = InternalTrace.GetLogger(typeof(TrustedPlatformAssembliesStrategy)); - public override bool TryToResolve( - AssemblyLoadContext loadContext, AssemblyName assemblyName, [NotNullWhen(true)] out Assembly? loadedAssembly) - { - return TryLoadFromTrustedPlatformAssemblies(loadContext, assemblyName, out loadedAssembly); - } - - private static bool TryLoadFromTrustedPlatformAssemblies( - AssemblyLoadContext loadContext, AssemblyName assemblyName, [NotNullWhen(true)] out Assembly? loadedAssembly) - { - // https://learn.microsoft.com/en-us/dotnet/core/dependency-loading/default-probing - loadedAssembly = null; - var trustedAssemblies = System.AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES") as string; - if (string.IsNullOrEmpty(trustedAssemblies)) - { - return false; - } - - var separator = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ";" : ":"; - foreach (var assemblyPath in trustedAssemblies.Split(separator)) - { - var fileName = Path.GetFileNameWithoutExtension(assemblyPath); - if (FileMatchesAssembly(fileName) && File.Exists(assemblyPath)) - { - loadedAssembly = loadContext.LoadFromAssemblyPath(assemblyPath); - log.Info("'{0}' assembly is loaded from trusted path '{1}'", assemblyPath, loadedAssembly.Location); - - return true; - } - } - - return false; - - bool FileMatchesAssembly(string fileName) => - string.Equals(fileName, assemblyName.Name, StringComparison.InvariantCultureIgnoreCase); - } - } - - public class RuntimeLibrariesStrategy : ResolutionStrategy - { - private static readonly Logger log = InternalTrace.GetLogger(typeof(RuntimeLibrariesStrategy)); - - private DependencyContext? _dependencyContext; - private readonly CompositeCompilationAssemblyResolver _assemblyResolver; - - public RuntimeLibrariesStrategy(AssemblyLoadContext loadContext, string testAssemblyPath) - { - _dependencyContext = DependencyContext.Load(loadContext.LoadFromAssemblyPath(testAssemblyPath)); - - _assemblyResolver = new CompositeCompilationAssemblyResolver( - [ - new AppBaseCompilationAssemblyResolver(Path.GetDirectoryName(testAssemblyPath)!), - new ReferenceAssemblyPathResolver(), - new PackageCompilationAssemblyResolver() - ]); - } - - public override bool TryToResolve( - AssemblyLoadContext loadContext, AssemblyName assemblyName, [NotNullWhen(true)] out Assembly? loadedAssembly) - { - if (_dependencyContext is null) - { - // TODO: Is this the intended behavior? - loadedAssembly = null; - return false; - } - - foreach (var library in _dependencyContext.RuntimeLibraries) - { - var wrapper = new CompilationLibrary( - library.Type, - library.Name, - library.Version, - library.Hash, - library.RuntimeAssemblyGroups.SelectMany(g => g.AssetPaths), - library.Dependencies, - library.Serviceable); - - var assemblies = new List(); - _assemblyResolver.TryResolveAssemblyPaths(wrapper, assemblies); - - foreach (var assemblyPath in assemblies) - { - if (assemblyName.Name == Path.GetFileNameWithoutExtension(assemblyPath)) - { - loadedAssembly = loadContext.LoadFromAssemblyPath(assemblyPath); - log.Info("'{0}' ({1}) assembly is loaded from runtime libraries {2} dependencies", - assemblyName, - loadedAssembly.Location, - library.Name); - - return true; - } - } - } - - loadedAssembly = null; - return false; - } - } - - public class AdditionalRuntimesStrategy : ResolutionStrategy - { - private string _runtimeName; - private bool _x86; - - public AdditionalRuntimesStrategy(string runtimeName, bool x86) - { - _runtimeName = runtimeName; - _x86 = x86; - } - - public override bool TryToResolve(AssemblyLoadContext loadContext, AssemblyName assemblyName, [NotNullWhen(true)] out Assembly? loadedAssembly) - { - loadedAssembly = null; - if (assemblyName.Version is null) - return false; - - if (!DotNet.FindBestRuntime(assemblyName.Version, _runtimeName, _x86, out DotNet.RuntimeInfo? runtime)) - return false; - - string candidate = Path.Combine(runtime.Path, runtime.Version.ToString(), assemblyName.Name + ".dll"); - if (!File.Exists(candidate)) - return false; - - loadedAssembly = loadContext.LoadFromAssemblyPath(candidate); - return true; - } - } - - public class WindowsDesktopStrategy : AdditionalRuntimesStrategy - { - public WindowsDesktopStrategy(bool x86) : base("Microsoft.WindowsDesktop.App", x86) - { - } - } - - public class AspNetCoreStrategy : AdditionalRuntimesStrategy - { - public AspNetCoreStrategy(bool x86) : base("Microsoft.AspNetCore.App", x86) - { - } - } - - #endregion -} -#endif diff --git a/src/NUnitCommon/nunit.agent.core/nunit.agent.core.csproj b/src/NUnitCommon/nunit.agent.core/nunit.agent.core.csproj deleted file mode 100644 index 0198b25ac..000000000 --- a/src/NUnitCommon/nunit.agent.core/nunit.agent.core.csproj +++ /dev/null @@ -1,41 +0,0 @@ - - - - NUnit.Engine - net462;netcoreapp3.1;net6.0;net8.0 - - - - NUnit.Agent.Core - Agent Core - Contains Types used by agents. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/NUnitCommon/nunit.common.tests/nunit.common.tests.csproj b/src/NUnitCommon/nunit.common.tests/nunit.common.tests.csproj index 46f2b9d5e..4798e11b0 100644 --- a/src/NUnitCommon/nunit.common.tests/nunit.common.tests.csproj +++ b/src/NUnitCommon/nunit.common.tests/nunit.common.tests.csproj @@ -14,8 +14,8 @@ - - + + diff --git a/src/NUnitCommon/nunit.common/nunit.common.csproj b/src/NUnitCommon/nunit.common/nunit.common.csproj index a9a005fda..431dad9bb 100644 --- a/src/NUnitCommon/nunit.common/nunit.common.csproj +++ b/src/NUnitCommon/nunit.common/nunit.common.csproj @@ -21,7 +21,7 @@ - + diff --git a/src/NUnitCommon/nunit.extensibility.tests/nunit.extensibility.tests.csproj b/src/NUnitCommon/nunit.extensibility.tests/nunit.extensibility.tests.csproj index 2d38735ea..0cbcf89c5 100644 --- a/src/NUnitCommon/nunit.extensibility.tests/nunit.extensibility.tests.csproj +++ b/src/NUnitCommon/nunit.extensibility.tests/nunit.extensibility.tests.csproj @@ -8,8 +8,8 @@ - - + + diff --git a/src/NUnitCommon/nunit.extensibility/nunit.extensibility.csproj b/src/NUnitCommon/nunit.extensibility/nunit.extensibility.csproj index 1c310f328..fbc53d441 100644 --- a/src/NUnitCommon/nunit.extensibility/nunit.extensibility.csproj +++ b/src/NUnitCommon/nunit.extensibility/nunit.extensibility.csproj @@ -13,8 +13,8 @@ - - + + diff --git a/src/NUnitConsole/nunit4-console.tests/nunit4-console.tests.csproj b/src/NUnitConsole/nunit4-console.tests/nunit4-console.tests.csproj index deb5b9a08..a6459c1a4 100644 --- a/src/NUnitConsole/nunit4-console.tests/nunit4-console.tests.csproj +++ b/src/NUnitConsole/nunit4-console.tests/nunit4-console.tests.csproj @@ -14,8 +14,8 @@ - - + + diff --git a/src/NUnitEngine/nunit.engine.tests/Runners/TestAgentRunnerTests.cs b/src/NUnitEngine/nunit.engine.tests/Runners/TestAgentRunnerTests.cs index 9def0551e..d5ecf25b4 100644 --- a/src/NUnitEngine/nunit.engine.tests/Runners/TestAgentRunnerTests.cs +++ b/src/NUnitEngine/nunit.engine.tests/Runners/TestAgentRunnerTests.cs @@ -1,5 +1,8 @@ // Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt +// TODO: Move tests to agent core repository and remove this file. These tests are not +// really testing the engine, but rather the agents, which are tested in the agent core repository. +#if false using System; using System.Collections.Generic; using System.IO; @@ -143,3 +146,4 @@ private static void CheckRunResult(XmlNode result) } } } +#endif diff --git a/src/NUnitEngine/nunit.engine.tests/Services/RuntimeFrameworkServiceTests.cs b/src/NUnitEngine/nunit.engine.tests/Services/RuntimeFrameworkServiceTests.cs index d44f0df6e..7f6c1d914 100644 --- a/src/NUnitEngine/nunit.engine.tests/Services/RuntimeFrameworkServiceTests.cs +++ b/src/NUnitEngine/nunit.engine.tests/Services/RuntimeFrameworkServiceTests.cs @@ -51,7 +51,6 @@ public void ServiceIsStarted() private const string AGENTS_DIR = "../../../../nunit.engine/bin/Release/agents/"; #endif - [TestCase("net35", false, ".NETFramework,Version=v2.0")] [TestCase("net462", false, ".NETFramework,Version=v4.6.2")] [TestCase("net462", true, ".NETFramework,Version=v4.6.2")] public void SelectRuntimeFramework(string runtime, bool runAsX86, string expectedFrameworkName) diff --git a/src/NUnitEngine/nunit.engine.tests/nunit.engine.tests.csproj b/src/NUnitEngine/nunit.engine.tests/nunit.engine.tests.csproj index 1c2fc4378..cb8d0cc15 100644 --- a/src/NUnitEngine/nunit.engine.tests/nunit.engine.tests.csproj +++ b/src/NUnitEngine/nunit.engine.tests/nunit.engine.tests.csproj @@ -12,10 +12,11 @@ - - + + + @@ -27,7 +28,6 @@ - diff --git a/src/NUnitEngine/nunit.engine/nunit.engine.csproj b/src/NUnitEngine/nunit.engine/nunit.engine.csproj index 36d98b1c5..821821b0d 100644 --- a/src/NUnitEngine/nunit.engine/nunit.engine.csproj +++ b/src/NUnitEngine/nunit.engine/nunit.engine.csproj @@ -17,13 +17,13 @@ - - + + \ No newline at end of file diff --git a/src/TestData/AppContextTest/AppContextTest.csproj b/src/TestData/AppContextTest/AppContextTest.csproj index 4bef27ef1..a247a120f 100644 --- a/src/TestData/AppContextTest/AppContextTest.csproj +++ b/src/TestData/AppContextTest/AppContextTest.csproj @@ -1,12 +1,12 @@  - net462;netcoreapp3.1;net6.0;net8.0;net9.0 + net462;net6.0;net8.0;net9.0 ..\..\..\bin\$(Configuration)\testdata\ - + diff --git a/src/TestData/FakeExtensions/2.0/FakeExtensions.csproj b/src/TestData/FakeExtensions/2.0/FakeExtensions.csproj index e64081247..c7d189f3c 100644 --- a/src/TestData/FakeExtensions/2.0/FakeExtensions.csproj +++ b/src/TestData/FakeExtensions/2.0/FakeExtensions.csproj @@ -14,7 +14,7 @@ - + diff --git a/src/TestData/InvalidTestNames/InvalidTestNames.csproj b/src/TestData/InvalidTestNames/InvalidTestNames.csproj index d0212eebe..a4bb3f3e8 100644 --- a/src/TestData/InvalidTestNames/InvalidTestNames.csproj +++ b/src/TestData/InvalidTestNames/InvalidTestNames.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/TestData/WpfApp/WpfApp.csproj b/src/TestData/WpfApp/WpfApp.csproj index dd182afd4..131db5d09 100644 --- a/src/TestData/WpfApp/WpfApp.csproj +++ b/src/TestData/WpfApp/WpfApp.csproj @@ -1,4 +1,4 @@ - + WinExe diff --git a/src/TestData/aspnetcore-test/aspnetcore-test.csproj b/src/TestData/aspnetcore-test/aspnetcore-test.csproj index c9254e189..3649b41a1 100644 --- a/src/TestData/aspnetcore-test/aspnetcore-test.csproj +++ b/src/TestData/aspnetcore-test/aspnetcore-test.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/TestData/mock-assembly-x86/mock-assembly-x86.csproj b/src/TestData/mock-assembly-x86/mock-assembly-x86.csproj index 766fc196d..79013f6bf 100644 --- a/src/TestData/mock-assembly-x86/mock-assembly-x86.csproj +++ b/src/TestData/mock-assembly-x86/mock-assembly-x86.csproj @@ -2,7 +2,7 @@ NUnit.TestData - net35;net462;netcoreapp3.1;net6.0;net7.0;net8.0;net9.0 + net462;net6.0;net7.0;net8.0;net9.0 ../../../bin/$(Configuration)/testdata true ..\..\nunit.snk @@ -17,8 +17,8 @@ - - + + diff --git a/src/TestData/mock-assembly/mock-assembly.csproj b/src/TestData/mock-assembly/mock-assembly.csproj index c1af71a9b..8cb75ac03 100644 --- a/src/TestData/mock-assembly/mock-assembly.csproj +++ b/src/TestData/mock-assembly/mock-assembly.csproj @@ -2,7 +2,7 @@ NUnit.TestData - net35;net462;netcoreapp3.1;net6.0;net7.0;net8.0;net9.0 + net462;net6.0;net7.0;net8.0;net9.0 ../../../bin/$(Configuration)/testdata true ..\..\nunit.snk @@ -16,8 +16,8 @@ - - + + diff --git a/src/TestData/notest-assembly/notest-assembly.csproj b/src/TestData/notest-assembly/notest-assembly.csproj index 14740057a..a03151368 100644 --- a/src/TestData/notest-assembly/notest-assembly.csproj +++ b/src/TestData/notest-assembly/notest-assembly.csproj @@ -14,7 +14,7 @@ - + \ No newline at end of file diff --git a/src/TestData/windows-test/windows-test.csproj b/src/TestData/windows-test/windows-test.csproj index 5ef15395d..8c8f292a5 100644 --- a/src/TestData/windows-test/windows-test.csproj +++ b/src/TestData/windows-test/windows-test.csproj @@ -1,4 +1,4 @@ - + net6.0-windows;net8.0-windows;net9.0-windows @@ -7,7 +7,7 @@ - + diff --git a/src/TestData/wpf-test/WpfTest.csproj b/src/TestData/wpf-test/WpfTest.csproj index abac18521..c5ec9a23e 100644 --- a/src/TestData/wpf-test/WpfTest.csproj +++ b/src/TestData/wpf-test/WpfTest.csproj @@ -7,7 +7,7 @@ - +