Replace use of ReflectionOnlyLoad as well as AssemblyReader class by using mono.cecil.
This commit is contained in:
Родитель
12d688830e
Коммит
6671ba59de
|
@ -134,6 +134,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "nunit.framework.tests-porta
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "nunitlite.runner-portable", "src\NUnitFramework\nunitlite.runner\nunitlite.runner-portable.csproj", "{D339BFC2-AF3F-46FA-899A-14BAD4BCA35B}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "targets", "targets", "{2821D6DA-4F95-4002-BC35-00E8B7F9961A}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
targets\Build.Targets = targets\Build.Targets
|
||||
targets\Common.Properties = targets\Common.Properties
|
||||
targets\Packaging.Targets = targets\Packaging.Targets
|
||||
targets\Testing.Targets = targets\Testing.Targets
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -354,6 +362,7 @@ Global
|
|||
{A4F0C741-6ED4-46C8-AE75-57E1C7197E22} = {A21BFC37-44FC-41A0-B6E7-6F949F45A635}
|
||||
{C4D16DF1-B6FA-42F5-834E-B01DA1BAA1FF} = {A21BFC37-44FC-41A0-B6E7-6F949F45A635}
|
||||
{A972031D-2F61-4183-AF75-99EE1A9F6B32} = {49D441DF-39FD-4F4D-AECA-86CF8EFE23AF}
|
||||
{2821D6DA-4F95-4002-BC35-00E8B7F9961A} = {49D441DF-39FD-4F4D-AECA-86CF8EFE23AF}
|
||||
{775FAD50-3623-4922-97C4-DFB29A8BE4C7} = {31B45C4C-206F-4F31-9CC6-33BF11DFEE39}
|
||||
{372A3447-D657-40FF-A089-77C19FEC30C8} = {31B45C4C-206F-4F31-9CC6-33BF11DFEE39}
|
||||
{D694CB69-6CFB-4762-86C2-EB27B808B282} = {31B45C4C-206F-4F31-9CC6-33BF11DFEE39}
|
||||
|
|
Двоичный файл не отображается.
|
@ -4,6 +4,8 @@
|
|||
<repository path="../src/NUnitFramework/tests/packages.config" />
|
||||
<repository path="..\src\NUnitEngine\Addins\nunit.v2.driver.tests\packages.config" />
|
||||
<repository path="..\src\NUnitEngine\mock-v2-assembly\packages.config" />
|
||||
<repository path="..\src\NUnitEngine\nunit.core.engine\packages.config" />
|
||||
<repository path="..\src\NUnitEngine\nunit.engine\packages.config" />
|
||||
<repository path="..\src\NUnitEngine\nunit.v2.driver.tests\packages.config" />
|
||||
<repository path="..\src\NUnitFramework\testdata\packages.config" />
|
||||
<repository path="..\src\NUnitFramework\tests\packages.config" />
|
||||
|
|
|
@ -34,13 +34,13 @@ namespace NUnit.Engine.Drivers
|
|||
private const string NUNITLITE_FRAMEWORK = "nunitlite";
|
||||
|
||||
/// <summary>
|
||||
/// Gets a flag indicating whether a given AssemblyName
|
||||
/// represents a test framework supported by this factory.
|
||||
/// Gets a flag indicating whether a given assembly name and version
|
||||
/// represent a test framework supported by this factory.
|
||||
/// </summary>
|
||||
public bool IsSupportedFramework(AssemblyName reference)
|
||||
public bool IsSupportedTestFramework(string assemblyName, Version version)
|
||||
{
|
||||
return reference.Name == NUNIT_FRAMEWORK && reference.Version.Major == 2
|
||||
|| reference.Name == NUNITLITE_FRAMEWORK && reference.Version.Major == 1;
|
||||
return assemblyName == NUNIT_FRAMEWORK && version.Major == 2
|
||||
|| assemblyName == NUNITLITE_FRAMEWORK && version.Major == 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -48,11 +48,12 @@ namespace NUnit.Engine.Drivers
|
|||
/// which the assembly is already known to reference.
|
||||
/// </summary>
|
||||
/// <param name="domain">The domain in which the assembly will be loaded</param>
|
||||
/// <param name="frameworkReference">The name of the test framework reference</param>
|
||||
/// <param name="assemblyName">The name of the test framework reference</param>
|
||||
/// <param name="version">The version of the test framework reference</param>
|
||||
/// <returns></returns>
|
||||
public IFrameworkDriver GetDriver(AppDomain domain, AssemblyName frameworkReference)
|
||||
public IFrameworkDriver GetDriver(AppDomain domain, string assemblyName, Version version)
|
||||
{
|
||||
if (!IsSupportedFramework(frameworkReference))
|
||||
if (!IsSupportedTestFramework(assemblyName, version))
|
||||
throw new ArgumentException("Invalid framework name", "frameworkAssemblyName");
|
||||
|
||||
return new NUnit2FrameworkDriver(domain);
|
||||
|
|
|
@ -39,6 +39,18 @@
|
|||
<NoWarn>1685</NoWarn>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\packages\Mono.Cecil.0.9.6.1\lib\net20\Mono.Cecil.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Mono.Cecil.Mdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\packages\Mono.Cecil.0.9.6.1\lib\net20\Mono.Cecil.Mdb.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Mono.Cecil.Pdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\packages\Mono.Cecil.0.9.6.1\lib\net20\Mono.Cecil.Pdb.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
|
@ -202,6 +214,9 @@
|
|||
<Folder Include="Agents\" />
|
||||
<Folder Include="Services\ResultWriters\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Mono.Cecil" version="0.9.6.1" targetFramework="net20" />
|
||||
</packages>
|
|
@ -32,18 +32,19 @@ namespace NUnit.Engine.Extensibility
|
|||
public interface IDriverFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a flag indicating whether a given AssemblyName
|
||||
/// represents a test framework supported by this factory.
|
||||
/// Gets a flag indicating whether a given assembly name and version
|
||||
/// represent a test framework supported by this factory.
|
||||
/// </summary>
|
||||
bool IsSupportedFramework(AssemblyName refAssembly);
|
||||
bool IsSupportedTestFramework(string assemblyName, Version version);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a driver for a given test assembly and a framework
|
||||
/// which the assembly is already known to reference.
|
||||
/// </summary>
|
||||
/// <param name="domain">The domain in which the assembly will be loaded</param>
|
||||
/// <param name="frameworkReference">The AssemblyName of the test framework reference</param>
|
||||
/// <param name="assemblyName">The Name of the test framework reference</param>
|
||||
/// <param name="version">The version of the test framework reference</param>
|
||||
/// <returns></returns>
|
||||
IFrameworkDriver GetDriver(AppDomain domain, AssemblyName frameworkReference);
|
||||
IFrameworkDriver GetDriver(AppDomain domain, string assemblyName, Version version);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,130 +0,0 @@
|
|||
// ***********************************************************************
|
||||
// Copyright (c) 2011 Charlie Poole
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// ***********************************************************************
|
||||
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using System.IO;
|
||||
|
||||
namespace NUnit.Engine.Internal.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class AssemblyReaderTests
|
||||
{
|
||||
private AssemblyReader rdr;
|
||||
|
||||
[SetUp]
|
||||
public void CreateReader()
|
||||
{
|
||||
rdr = new AssemblyReader( this.GetType().Assembly );
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void DisposeReader()
|
||||
{
|
||||
if ( rdr != null )
|
||||
rdr.Dispose();
|
||||
|
||||
rdr = null;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateFromPath()
|
||||
{
|
||||
string path = AssemblyHelper.GetAssemblyPath(System.Reflection.Assembly.GetAssembly(GetType()));
|
||||
Assert.AreEqual(path, new AssemblyReader(path).AssemblyPath);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateFromAssembly()
|
||||
{
|
||||
string path = AssemblyHelper.GetAssemblyPath(System.Reflection.Assembly.GetAssembly(GetType()));
|
||||
Assert.AreEqual(path, rdr.AssemblyPath);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsValidPeFile()
|
||||
{
|
||||
Assert.IsTrue(rdr.IsValidPeFile);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsValidPeFile_Fails()
|
||||
{
|
||||
string path = AssemblyHelper.GetAssemblyPath(System.Reflection.Assembly.GetAssembly(GetType()));
|
||||
path = Path.Combine(Path.GetDirectoryName(path), "nunit.engine.api.xml");
|
||||
Assert.IsFalse(new AssemblyReader(path).IsValidPeFile);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsDotNetFile()
|
||||
{
|
||||
Assert.IsTrue( rdr.IsDotNetFile );
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ImageRuntimeVersion()
|
||||
{
|
||||
string runtimeVersion = rdr.ImageRuntimeVersion;
|
||||
|
||||
StringAssert.StartsWith( "v", runtimeVersion );
|
||||
new Version( runtimeVersion.Substring( 1 ) );
|
||||
// This fails when we force running under a prior version
|
||||
// Assert.LessOrEqual( version, Environment.Version );
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShouldRun32BitAnyCpuCSharpAssembly()
|
||||
{
|
||||
string path = AssemblyHelper.GetAssemblyPath(System.Reflection.Assembly.GetAssembly(GetType()));
|
||||
path = Path.Combine(Path.GetDirectoryName(path), "nunit-agent.exe");
|
||||
Assert.That(new AssemblyReader(path).ShouldRun32Bit, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShouldRun32Bit32BitCSharpAssembly()
|
||||
{
|
||||
string path = AssemblyHelper.GetAssemblyPath(System.Reflection.Assembly.GetAssembly(GetType()));
|
||||
path = Path.Combine(Path.GetDirectoryName(path), "nunit-agent-x86.exe");
|
||||
Assert.That(new AssemblyReader(path).ShouldRun32Bit, Is.True);
|
||||
}
|
||||
|
||||
[Ignore("This test started failing on AppVeyor for no apparent reason. Ignoring until we figure out why.")]
|
||||
[Test]
|
||||
public void ShouldRun32Bit64BitCppAssembly()
|
||||
{
|
||||
string path = AssemblyHelper.GetAssemblyPath(System.Reflection.Assembly.GetAssembly(GetType()));
|
||||
path = Path.Combine(Path.GetDirectoryName(path), "mock-cpp-clr-x64.dll");
|
||||
Assume.That(path, Does.Exist);
|
||||
Assert.That(new AssemblyReader(path).ShouldRun32Bit, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShouldRun32Bit32BitCppAssembly()
|
||||
{
|
||||
string path = AssemblyHelper.GetAssemblyPath(System.Reflection.Assembly.GetAssembly(GetType()));
|
||||
path = Path.Combine(Path.GetDirectoryName(path), "mock-cpp-clr-x86.dll");
|
||||
Assume.That(path, Does.Exist);
|
||||
Assert.That(new AssemblyReader(path).ShouldRun32Bit, Is.True);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -41,10 +41,37 @@ namespace NUnit.Engine.Services.Tests
|
|||
services.ServiceManager.StartServices();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void StopService()
|
||||
{
|
||||
_runtimeService.StopService();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ServiceIsStarted()
|
||||
{
|
||||
Assert.That(_runtimeService.Status, Is.EqualTo(ServiceStatus.Started));
|
||||
}
|
||||
|
||||
[TestCase("mock-nunit-assembly.exe", "net-2.0", false)]
|
||||
[TestCase("net-2.0/mock-nunit-assembly.exe", "net-2.0", false)]
|
||||
[TestCase("net-4.0/mock-nunit-assembly.exe", "net-4.0", false)]
|
||||
// TODO: Change this case when the 4.0/4.5 bug is fixed
|
||||
[TestCase("net-4.5/mock-nunit-assembly.exe", "net-4.0", false)]
|
||||
[TestCase("mock-cpp-clr-x64.dll", "net-4.0", false)]
|
||||
[TestCase("mock-cpp-clr-x86.dll", "net-4.0", true)]
|
||||
[TestCase("nunit-agent.exe", "net-2.0", false)]
|
||||
[TestCase("nunit-agent-x86.exe", "net-2.0", true)]
|
||||
// TODO: Make the following cases work correctly in case we want to use
|
||||
// the engine to run them in the future.
|
||||
[TestCase("netcf-3.5/mock-nunit-assembly.exe", "net-2.0", false)]
|
||||
[TestCase("sl-5.0/mock-nunit-assembly.dll", "net-4.0", false)]
|
||||
[TestCase("portable/mock-nunit-assembly.dll", "net-4.0", false)]
|
||||
public void SelectRuntimeFramework(string assemblyName, string expectedRuntime, bool runAsX86)
|
||||
{
|
||||
var package = new TestPackage(assemblyName);
|
||||
Assert.That(_runtimeService.SelectRuntimeFramework(package), Is.EqualTo(expectedRuntime));
|
||||
Assert.That(package.GetSetting("RunAsX86", false), Is.EqualTo(runAsX86));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,7 +63,6 @@
|
|||
<Compile Include="Api\TestFilterTests.cs" />
|
||||
<Compile Include="Api\TestPackageTests.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Internal\AssemblyReaderTests.cs" />
|
||||
<Compile Include="Drivers\NotRunnableFrameworkDriverTests.cs" />
|
||||
<Compile Include="Drivers\NUnit3FrameworkDriverTests.cs" />
|
||||
<Compile Include="Internal\PathUtilTests.cs" />
|
||||
|
|
|
@ -32,12 +32,12 @@ namespace NUnit.Engine.Drivers
|
|||
private const string NUNIT_FRAMEWORK = "nunit.framework";
|
||||
|
||||
/// <summary>
|
||||
/// Gets a flag indicating whether a given AssemblyName
|
||||
/// represents a test framework supported by this factory.
|
||||
/// Gets a flag indicating whether a given assembly name and version
|
||||
/// represent a test framework supported by this factory.
|
||||
/// </summary>
|
||||
public bool IsSupportedFramework(AssemblyName reference)
|
||||
public bool IsSupportedTestFramework(string assemblyName, Version version)
|
||||
{
|
||||
return reference.Name == NUNIT_FRAMEWORK && reference.Version.Major == 3;
|
||||
return assemblyName == NUNIT_FRAMEWORK && version.Major == 3;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -45,12 +45,13 @@ namespace NUnit.Engine.Drivers
|
|||
/// which the assembly is already known to reference.
|
||||
/// </summary>
|
||||
/// <param name="domain">The domain in which the assembly will be loaded</param>
|
||||
/// <param name="frameworkReference">The AssemblyName of the test framework reference</param>
|
||||
/// <param name="assemblyName">The Name of the test framework reference</param>
|
||||
/// <param name="version">The version of the test framework reference</param>
|
||||
/// <returns></returns>
|
||||
public IFrameworkDriver GetDriver(AppDomain domain, AssemblyName frameworkReference)
|
||||
public IFrameworkDriver GetDriver(AppDomain domain, string assemblyName, Version version)
|
||||
{
|
||||
Guard.ArgumentValid(IsSupportedFramework(frameworkReference), "Invalid framework name", "frameworkAssemblyName");
|
||||
|
||||
Guard.ArgumentValid(IsSupportedTestFramework(assemblyName, version), "Invalid framework name", "frameworkAssemblyName");
|
||||
|
||||
return new NUnit3FrameworkDriver(domain);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,230 +0,0 @@
|
|||
// ***********************************************************************
|
||||
// Copyright (c) 2011 Charlie Poole
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// ***********************************************************************
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace NUnit.Engine.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// AssemblyReader knows how to find various things in an assembly header
|
||||
/// </summary>
|
||||
public class AssemblyReader : IDisposable
|
||||
{
|
||||
private readonly string assemblyPath;
|
||||
private BinaryReader rdr;
|
||||
private FileStream fs;
|
||||
|
||||
private UInt16 dos_magic = 0xffff;
|
||||
private UInt32 pe_signature = 0xffffffff;
|
||||
private UInt16 numberOfSections;
|
||||
private UInt16 optionalHeaderSize;
|
||||
private PEType peType;
|
||||
private UInt32 numDataDirectoryEntries;
|
||||
private CorFlags corFlags;
|
||||
|
||||
private uint peHeader;
|
||||
private uint fileHeader;
|
||||
private uint optionalHeader;
|
||||
private uint dataDirectory;
|
||||
private uint dataSections;
|
||||
|
||||
private struct DataSection
|
||||
{
|
||||
public uint VirtualAddress;
|
||||
public uint VirtualSize;
|
||||
public uint FileOffset;
|
||||
};
|
||||
|
||||
private enum PEType : ushort
|
||||
{
|
||||
PE32 = 0x10b,
|
||||
PE32Plus = 0x20b
|
||||
}
|
||||
|
||||
[Flags]
|
||||
private enum CorFlags : uint
|
||||
{
|
||||
// CorHdr.h
|
||||
COMIMAGE_FLAGS_ILONLY = 0x00000001,
|
||||
COMIMAGE_FLAGS_32BITREQUIRED = 0x00000002,
|
||||
COMIMAGE_FLAGS_IL_LIBRARY = 0x00000004,
|
||||
COMIMAGE_FLAGS_STRONGNAMESIGNED = 0x00000008,
|
||||
COMIMAGE_FLAGS_NATIVE_ENTRYPOINT = 0x00000010,
|
||||
COMIMAGE_FLAGS_TRACKDEBUGDATA = 0x00010000,
|
||||
COMIMAGE_FLAGS_32BITPREFERRED = 0x00020000,
|
||||
}
|
||||
|
||||
private DataSection[] sections;
|
||||
|
||||
public AssemblyReader( string assemblyPath )
|
||||
{
|
||||
this.assemblyPath = assemblyPath;
|
||||
CalcHeaderOffsets();
|
||||
}
|
||||
|
||||
public AssemblyReader( Assembly assembly )
|
||||
{
|
||||
this.assemblyPath = AssemblyHelper.GetAssemblyPath( assembly );
|
||||
CalcHeaderOffsets();
|
||||
}
|
||||
|
||||
private void CalcHeaderOffsets()
|
||||
{
|
||||
this.fs = new FileStream( assemblyPath, FileMode.Open, FileAccess.Read );
|
||||
this.rdr = new BinaryReader( fs );
|
||||
dos_magic = rdr.ReadUInt16();
|
||||
if ( dos_magic == 0x5a4d )
|
||||
{
|
||||
fs.Position = 0x3c;
|
||||
peHeader = rdr.ReadUInt32();
|
||||
fileHeader = peHeader + 4;
|
||||
optionalHeader = fileHeader + 20;
|
||||
|
||||
fs.Position = optionalHeader;
|
||||
peType = (PEType)rdr.ReadUInt16();
|
||||
|
||||
dataDirectory = peType == PEType.PE32Plus
|
||||
? optionalHeader + 112
|
||||
: optionalHeader + 96;
|
||||
|
||||
fs.Position = dataDirectory - 4;
|
||||
numDataDirectoryEntries = rdr.ReadUInt32();
|
||||
|
||||
fs.Position = peHeader;
|
||||
pe_signature = rdr.ReadUInt32();
|
||||
rdr.ReadUInt16(); // machine
|
||||
numberOfSections = rdr.ReadUInt16();
|
||||
fs.Position += 12;
|
||||
optionalHeaderSize = rdr.ReadUInt16();
|
||||
dataSections = optionalHeader + optionalHeaderSize;
|
||||
|
||||
sections = new DataSection[numberOfSections];
|
||||
fs.Position = dataSections;
|
||||
for( int i = 0; i < numberOfSections; i++ )
|
||||
{
|
||||
fs.Position += 8;
|
||||
sections[i].VirtualSize = rdr.ReadUInt32();
|
||||
sections[i].VirtualAddress = rdr.ReadUInt32();
|
||||
uint rawDataSize = rdr.ReadUInt32();
|
||||
sections[i].FileOffset = rdr.ReadUInt32();
|
||||
if ( sections[i].VirtualSize == 0 )
|
||||
sections[i].VirtualSize = rawDataSize;
|
||||
|
||||
fs.Position += 16;
|
||||
}
|
||||
|
||||
if (IsDotNetFile)
|
||||
{
|
||||
uint rva = DataDirectoryRva(14);
|
||||
if (rva != 0)
|
||||
{
|
||||
fs.Position = RvaToLfa(rva) + 8;
|
||||
uint metadata = rdr.ReadUInt32();
|
||||
fs.Position = RvaToLfa(metadata);
|
||||
if (rdr.ReadUInt32() == 0x424a5342)
|
||||
{
|
||||
// Copy string representing runtime version
|
||||
fs.Position += 12;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
char c;
|
||||
while ((c = rdr.ReadChar()) != '\0')
|
||||
sb.Append(c);
|
||||
|
||||
if (sb[0] == 'v') // Last sanity check
|
||||
ImageRuntimeVersion = sb.ToString();
|
||||
|
||||
// Could do fixups here for bad values in older files
|
||||
// like 1.x86, 1.build, etc. But we are only using
|
||||
// the major version anyway
|
||||
|
||||
// Jump back and find the CorFlags
|
||||
fs.Position = RvaToLfa(rva) + 16;
|
||||
corFlags = (CorFlags)rdr.ReadUInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private uint DataDirectoryRva( int n )
|
||||
{
|
||||
fs.Position = dataDirectory + n * 8;
|
||||
return rdr.ReadUInt32();
|
||||
}
|
||||
|
||||
private uint RvaToLfa(uint rva)
|
||||
{
|
||||
foreach (var section in sections)
|
||||
if (rva >= section.VirtualAddress && rva < section.VirtualAddress + section.VirtualSize)
|
||||
return rva - section.VirtualAddress + section.FileOffset;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public string AssemblyPath
|
||||
{
|
||||
get { return assemblyPath; }
|
||||
}
|
||||
|
||||
public bool IsValidPeFile
|
||||
{
|
||||
get { return dos_magic == 0x5a4d && pe_signature == 0x00004550; }
|
||||
}
|
||||
|
||||
public bool IsDotNetFile
|
||||
{
|
||||
get { return IsValidPeFile && numDataDirectoryEntries > 14 && DataDirectoryRva(14) != 0; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Will return true if the assembly is 32 bit, or if it prefers to run 32-bit
|
||||
/// </summary>
|
||||
public bool ShouldRun32Bit
|
||||
{
|
||||
get
|
||||
{
|
||||
// C++/CLI
|
||||
if ((corFlags & CorFlags.COMIMAGE_FLAGS_NATIVE_ENTRYPOINT) != 0)
|
||||
return peType != PEType.PE32Plus;
|
||||
|
||||
return peType != PEType.PE32Plus && (corFlags & CorFlags.COMIMAGE_FLAGS_32BITREQUIRED) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
public string ImageRuntimeVersion { get; private set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if ( fs != null )
|
||||
fs.Close();
|
||||
if ( rdr != null )
|
||||
rdr.Close();
|
||||
|
||||
fs = null;
|
||||
rdr = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,6 +25,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using Mono.Cecil;
|
||||
using NUnit.Engine.Drivers;
|
||||
using NUnit.Engine.Extensibility;
|
||||
|
||||
|
@ -57,14 +58,14 @@ namespace NUnit.Engine.Services
|
|||
|
||||
try
|
||||
{
|
||||
var references = GetAssemblyReferences(assemblyPath);
|
||||
var references = AssemblyDefinition.ReadAssembly(assemblyPath).MainModule.AssemblyReferences;
|
||||
|
||||
foreach (var factory in _factories)
|
||||
{
|
||||
foreach (var reference in references)
|
||||
{
|
||||
if (factory.IsSupportedFramework(reference))
|
||||
return factory.GetDriver(domain, reference);
|
||||
if (factory.IsSupportedTestFramework(reference.Name, reference.Version))
|
||||
return factory.GetDriver(domain, reference.Name, reference.Version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -76,34 +77,8 @@ namespace NUnit.Engine.Services
|
|||
return new NotRunnableFrameworkDriver(assemblyPath, "Unable to locate a driver for " + assemblyPath);
|
||||
}
|
||||
|
||||
private static AssemblyName[] GetAssemblyReferences(string assemblyPath)
|
||||
{
|
||||
var reflectionDomain = AppDomain.CreateDomain("ReflectionDomain");
|
||||
|
||||
try
|
||||
{
|
||||
var agentType = typeof(ReflectionAgent);
|
||||
var agent = reflectionDomain.CreateInstanceAndUnwrap(agentType.Assembly.FullName, agentType.FullName) as ReflectionAgent;
|
||||
return agent.GetReferencedAssemblies(assemblyPath);
|
||||
}
|
||||
finally
|
||||
{
|
||||
AppDomain.Unload(reflectionDomain);
|
||||
}
|
||||
}
|
||||
|
||||
private class ReflectionAgent : MarshalByRefObject
|
||||
{
|
||||
public AssemblyName[] GetReferencedAssemblies(string assemblyPath)
|
||||
{
|
||||
var testAssembly = Assembly.ReflectionOnlyLoadFrom(assemblyPath);
|
||||
var references = testAssembly.GetReferencedAssemblies();
|
||||
return references;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Service Overrides
|
||||
|
||||
public override void StartService()
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
using System;
|
||||
using System.IO;
|
||||
using Mono.Cecil;
|
||||
using NUnit.Common;
|
||||
using NUnit.Engine.Internal;
|
||||
|
||||
|
@ -114,34 +115,25 @@ namespace NUnit.Engine.Services
|
|||
// contribute any information to the decision, so we skip it.
|
||||
if (PathUtils.IsAssemblyFileType(assembly) && File.Exists(assembly))
|
||||
{
|
||||
using (var reader = new AssemblyReader(assembly))
|
||||
var module = AssemblyDefinition.ReadAssembly(assembly).MainModule;
|
||||
var NativeEntryPoint = (ModuleAttributes)16;
|
||||
var mask = ModuleAttributes.Required32Bit | NativeEntryPoint;
|
||||
if (module.Architecture != TargetArchitecture.AMD64 &&
|
||||
module.Architecture != TargetArchitecture.IA64 &&
|
||||
(module.Attributes & mask) != 0)
|
||||
{
|
||||
if (!reader.IsValidPeFile)
|
||||
log.Debug("{0} is not a valid PE file", assembly);
|
||||
else if (!reader.IsDotNetFile)
|
||||
log.Debug("{0} is not a managed assembly", assembly);
|
||||
else
|
||||
{
|
||||
if (reader.ShouldRun32Bit)
|
||||
{
|
||||
package.Settings[PackageSettings.RunAsX86] = true;
|
||||
log.Debug("Assembly {0} will be run x86", assembly);
|
||||
}
|
||||
|
||||
var imageRuntimeVersion = reader.ImageRuntimeVersion;
|
||||
if (imageRuntimeVersion != null)
|
||||
{
|
||||
var v = new Version(imageRuntimeVersion.Substring(1));
|
||||
log.Debug("Assembly {0} uses version {1}", assembly, v);
|
||||
|
||||
// TODO: We are doing two jobs here: (1) getting the
|
||||
// target version and (2) applying a policy that says
|
||||
// we run under the highest version of all assemblies.
|
||||
// We should implement the policy at a higher level.
|
||||
if (v > targetVersion) targetVersion = v;
|
||||
}
|
||||
}
|
||||
package.Settings[PackageSettings.RunAsX86] = true;
|
||||
log.Debug("Assembly {0} will be run x86", assembly);
|
||||
}
|
||||
|
||||
var v = new Version(module.RuntimeVersion.Substring(1));
|
||||
log.Debug("Assembly {0} uses version {1}", assembly, v);
|
||||
|
||||
// TODO: We are doing two jobs here: (1) getting the
|
||||
// target version and (2) applying a policy that says
|
||||
// we run under the highest version of all assemblies.
|
||||
// We should implement the policy at a higher level.
|
||||
if (v > targetVersion) targetVersion = v;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,15 @@
|
|||
<NoWarn>1685</NoWarn>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Mono.Cecil">
|
||||
<HintPath>..\..\..\packages\Mono.Cecil.0.9.6.1\lib\net20\Mono.Cecil.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Mono.Cecil.Mdb">
|
||||
<HintPath>..\..\..\packages\Mono.Cecil.0.9.6.1\lib\net20\Mono.Cecil.Mdb.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Mono.Cecil.Pdb">
|
||||
<HintPath>..\..\..\packages\Mono.Cecil.0.9.6.1\lib\net20\Mono.Cecil.Pdb.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
|
@ -83,7 +92,6 @@
|
|||
<Compile Include="Agents\TestAgent.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="CallbackHandler.cs" />
|
||||
<Compile Include="Internal\AssemblyReader.cs" />
|
||||
<Compile Include="Internal\DomainUsage.cs" />
|
||||
<Compile Include="Internal\NUnitConfiguration.cs" />
|
||||
<Compile Include="Internal\PathUtils.cs" />
|
||||
|
@ -150,7 +158,9 @@
|
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Mono.Cecil" version="0.9.6.1" targetFramework="net20" />
|
||||
</packages>
|
Загрузка…
Ссылка в новой задаче