Skip to content

Commit

Permalink
Port issue 1468 to V4
Browse files Browse the repository at this point in the history
  • Loading branch information
CharliePoole committed Dec 29, 2024
1 parent 307f3a2 commit 90301b7
Show file tree
Hide file tree
Showing 9 changed files with 219 additions and 34 deletions.
7 changes: 7 additions & 0 deletions NUnitConsole.sln
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InvalidTestNames", "src\Tes
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WpfTest", "src\TestData\wpf-test\WpfTest.csproj", "{2F9D8932-2186-464F-BED6-7D7979C8FFA6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WpfApp", "src\TestData\WpfApp\WpfApp.csproj", "{93D182B7-2F63-4661-BB32-94F1716CF03F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -259,6 +261,10 @@ Global
{2F9D8932-2186-464F-BED6-7D7979C8FFA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2F9D8932-2186-464F-BED6-7D7979C8FFA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2F9D8932-2186-464F-BED6-7D7979C8FFA6}.Release|Any CPU.Build.0 = Release|Any CPU
{93D182B7-2F63-4661-BB32-94F1716CF03F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{93D182B7-2F63-4661-BB32-94F1716CF03F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{93D182B7-2F63-4661-BB32-94F1716CF03F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{93D182B7-2F63-4661-BB32-94F1716CF03F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -300,6 +306,7 @@ Global
{E79A3CCD-07E2-4C50-B8BF-1C5844720725} = {37D508B2-91E0-4B32-869B-DFF9E68EA213}
{48DF1E40-93BA-436A-B460-5D1130316ADA} = {37D508B2-91E0-4B32-869B-DFF9E68EA213}
{2F9D8932-2186-464F-BED6-7D7979C8FFA6} = {37D508B2-91E0-4B32-869B-DFF9E68EA213}
{93D182B7-2F63-4661-BB32-94F1716CF03F} = {37D508B2-91E0-4B32-869B-DFF9E68EA213}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D8E4FC26-5422-4C51-8BBC-D1AC0A578711}
Expand Down
21 changes: 14 additions & 7 deletions package-tests.cake
Original file line number Diff line number Diff line change
Expand Up @@ -239,13 +239,20 @@ AddToBothLists(new PackageTest(
// new MockAssemblyExpectedResult("netcore-6.0", "netcore-8.0"),
// KnownExtensions.NUnitProjectLoader));

//// V2 Result Writer Test
//StandardRunnerTests.Add(new PackageTest(
// 1, "V2ResultWriterTest",
// "Run mock-assembly under .NET 6.0 and produce V2 output",
// "testdata/net6.0/mock-assembly.dll --result=TestResult.xml --result=NUnit2TestResult.xml;format=nunit2",
// new MockAssemblyExpectedResult("netcore-6.0"),
// KnownExtensions.NUnitV2ResultWriter));
// V2 Result Writer Test
StandardRunnerTests.Add(new PackageTest(
1, "V2ResultWriterTest",
"Run mock-assembly under .NET 4.6.2 and produce V2 output",
"testdata/net462/mock-assembly.dll --result=TestResult.xml --result=NUnit2TestResult.xml;format=nunit2",
new MockAssemblyExpectedResult("net-4.6.2"),
KnownExtensions.NUnitV2ResultWriter));

StandardRunnerTests.Add(new PackageTest(
1, "V2ResultWriterTest",
"Run mock-assembly under .NET 6.0 and produce V2 output",
"testdata/net6.0/mock-assembly.dll --result=TestResult.xml --result=NUnit2TestResult.xml;format=nunit2",
new MockAssemblyExpectedResult("netcore-6.0"),
KnownExtensions.NUnitV2ResultWriter));

//// VS Project Loader Tests
//StandardRunnerTests.Add(new PackageTest(
Expand Down
20 changes: 10 additions & 10 deletions src/NUnitEngine/nunit.engine.core/Drivers/DriverService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,19 @@ public class DriverService : IDriverService
public DriverService()
{
#if NETFRAMEWORK // TODO: Restore extensibility to .NET 8.0 build
var thisAssembly = Assembly.GetExecutingAssembly();
var extensionManager = new ExtensionManager();
//var thisAssembly = Assembly.GetExecutingAssembly();
//var extensionManager = new ExtensionManager();

extensionManager.FindExtensionPoints(thisAssembly);
extensionManager.FindExtensionAssemblies(thisAssembly);
//extensionManager.FindExtensionPoints(thisAssembly);
//extensionManager.FindExtensionAssemblies(thisAssembly);

foreach (IDriverFactory factory in extensionManager.GetExtensions<IDriverFactory>())
_factories.Add(factory);
//foreach (IDriverFactory factory in extensionManager.GetExtensions<IDriverFactory>())
// _factories.Add(factory);

// HACK
var node = extensionManager.GetExtensionNode("/NUnit/Engine/NUnitV2Driver") as ExtensionNode;
if (node != null)
_factories.Add(new NUnit2DriverFactory(node));
//// HACK
//var node = extensionManager.GetExtensionNode("/NUnit/Engine/NUnitV2Driver") as ExtensionNode;
//if (node != null)
// _factories.Add(new NUnit2DriverFactory(node));
#endif

_factories.Add(new NUnit3DriverFactory());
Expand Down
131 changes: 131 additions & 0 deletions src/NUnitEngine/nunit.engine.core/Runners/NotRunnableTestRunner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection.Emit;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace NUnit.Engine.Runners
{
public abstract class NotRunnableTestRunner : ITestEngineRunner
{
private const string LOAD_RESULT_FORMAT =
"<test-suite type='{0}' id='{1}' name='{2}' fullname='{3}' testcasecount='0' runstate='{4}'>" +
"<properties>" +
"<property name='_SKIPREASON' value='{5}'/>" +
"</properties>" +
"</test-suite>";

private const string RUN_RESULT_FORMAT =
"<test-suite type='{0}' id='{1}' name='{2}' fullname='{3}' testcasecount='0' runstate='{4}' result='{5}' label='{6}'>" +
"<properties>" +
"<property name='_SKIPREASON' value='{7}'/>" +
"</properties>" +
"<reason>" +
"<message>{7}</message>" +
"</reason>" +
"</test-suite>";

private string _name;
private string _fullname;
private string _message;
private string _type;

protected string _runstate;
protected string _result;
protected string _label;

public NotRunnableTestRunner(string assemblyPath, string message)
{
_name = Escape(Path.GetFileName(assemblyPath));
_fullname = Escape(Path.GetFullPath(assemblyPath));
_message = Escape(message);
_type = new List<string> { ".dll", ".exe" }.Contains(Path.GetExtension(assemblyPath)) ? "Assembly" : "Unknown";
}

public string ID { get; set; }

TestEngineResult ITestEngineRunner.Load()
{
return GetLoadResult();
}

void ITestEngineRunner.Unload()
{
}

TestEngineResult ITestEngineRunner.Reload()
{
return GetLoadResult();
}

int ITestEngineRunner.CountTestCases(TestFilter filter)
{
return 0;
}

TestEngineResult ITestEngineRunner.Run(ITestEventListener listener, TestFilter filter)
{
return new TestEngineResult(string.Format(RUN_RESULT_FORMAT,
_type, TestID, _name, _fullname, _runstate, _result, _label, _message));
}

AsyncTestEngineResult ITestEngineRunner.RunAsync(ITestEventListener listener, TestFilter filter)
{
throw new NotImplementedException();
}

void ITestEngineRunner.StopRun(bool force)
{
}

TestEngineResult ITestEngineRunner.Explore(TestFilter filter)
{
return GetLoadResult();
}

void IDisposable.Dispose()
{
// Nothing to do here
}

private static string Escape(string original)
{
return original
.Replace("&", "&amp;")
.Replace("\"", "&quot;")
.Replace("'", "&apos;")
.Replace("<", "&lt;")
.Replace(">", "&gt;");
}

private TestEngineResult GetLoadResult()
{
return new TestEngineResult(string.Format(
LOAD_RESULT_FORMAT,
_type, TestID, _name, _fullname, _runstate, _message));
}

private string TestID
{
get
{
return string.IsNullOrEmpty(ID)
? "1"
: ID + "-1";
}
}
}

public class UnmanagedExecutableTestRunner : NotRunnableTestRunner
{
public UnmanagedExecutableTestRunner(string assemblyPath)
: base(assemblyPath, "Unmanaged libraries or applications are not supported")
{ }
}
}
2 changes: 1 addition & 1 deletion src/NUnitEngine/nunit.engine/Runners/MasterTestRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class MasterTestRunner : ITestRunner
// MasterTestRunner is the only runner that is passed back
// to users asking for an ITestRunner. The actual details of
// execution are handled by various internal runners, which
// impement ITestEngineRunner.
// implement ITestEngineRunner.
//
// Explore and execution results from MasterTestRunner are
// returned as XmlNodes, created from the internal
Expand Down
43 changes: 27 additions & 16 deletions src/NUnitEngine/nunit.engine/Services/RuntimeFrameworkService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ private RuntimeFramework SelectRuntimeFrameworkInner(TestPackage package)
targetRuntime = Runtime.NetCore;
targetVersion = new Version(3, 1);
break;
case "Unmanaged":
return null;
default:
throw new NUnitEngineException("Unsupported Target Framework: " + imageTargetFrameworkNameSetting);
}
Expand Down Expand Up @@ -379,26 +381,35 @@ private static void ApplyImageData(TestPackage package)
if (!File.Exists(packageName))
log.Error($"Could not find {packageName}");
else
using (var assembly = AssemblyDefinition.ReadAssembly(packageName))
try
{
targetVersion = assembly.GetRuntimeVersion();
log.Debug($"Assembly {packageName} uses version {targetVersion}");

frameworkName = assembly.GetFrameworkName();
log.Debug($"Assembly {packageName} targets {frameworkName}");

if (assembly.RequiresX86())
using (var assembly = AssemblyDefinition.ReadAssembly(packageName))
{
requiresX86 = true;
log.Debug($"Assembly {packageName} will be run x86");
}

if (assembly.HasAttribute("NUnit.Framework.TestAssemblyDirectoryResolveAttribute"))
{
requiresAssemblyResolver = true;
log.Debug($"Assembly {packageName} requires default app domain assembly resolver");
targetVersion = assembly.GetRuntimeVersion();
log.Debug($"Assembly {packageName} uses version {targetVersion}");

frameworkName = assembly.GetFrameworkName();
log.Debug($"Assembly {packageName} targets {frameworkName}");

if (assembly.RequiresX86())
{
requiresX86 = true;
log.Debug($"Assembly {packageName} will be run x86");
}

if (assembly.HasAttribute("NUnit.Framework.TestAssemblyDirectoryResolveAttribute"))
{
requiresAssemblyResolver = true;
log.Debug($"Assembly {packageName} requires default app domain assembly resolver");
}
}
}
catch (BadImageFormatException)
{
// "Unmanaged" is not a valid framework identifier but we handle it upstream
// using UnmanagedCodeTestRunner, which doesn't actually try to run it.
frameworkName = "Unmanaged,Version=0.0";
}
}

if (targetVersion.Major > 0)
Expand Down
2 changes: 2 additions & 0 deletions src/NUnitEngine/nunit.engine/Services/TestRunnerFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ public ITestEngineRunner MakeTestRunner(TestPackage package)
}
}
#else
if (package.GetSetting(InternalEnginePackageSettings.ImageTargetFrameworkName, "").StartsWith("Unmanaged,"))
return new UnmanagedExecutableTestRunner(package.FullName);

bool isNested = false;
foreach (TestPackage subPackage in package.SubPackages)
Expand Down
17 changes: 17 additions & 0 deletions src/TestData/WpfApp/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt

namespace WpfApp
{
internal class Program
{
static void Main() { }
}
}
10 changes: 10 additions & 0 deletions src/TestData/WpfApp/WpfApp.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<OutputPath>..\..\..\bin\$(Configuration)\testdata\</OutputPath>
<UseWPF>true</UseWPF>
</PropertyGroup>

</Project>

0 comments on commit 90301b7

Please sign in to comment.