Skip to content

Commit

Permalink
Understanding assembly type from source (#1529)
Browse files Browse the repository at this point in the history
* Understanding assembly type from source

* review comments

* review comments
  • Loading branch information
abhishkk authored Apr 9, 2018
1 parent 1547583 commit 534026f
Show file tree
Hide file tree
Showing 18 changed files with 482 additions and 1 deletion.
15 changes: 15 additions & 0 deletions TestPlatform.sln
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "perf", "perf", "{0D4DF78D-7
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "vstest.console.PlatformTests", "test\vstest.console.PlatformTests\vstest.console.PlatformTests.csproj", "{8C068694-23A2-47A2-A0DD-DB82D0AF0142}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TestPlatform.Common.PlatformTests", "test\Microsoft.TestPlatform.Common.PlatformTests\Microsoft.TestPlatform.Common.PlatformTests.csproj", "{24C7683D-2607-4901-B8EB-83A57E49E93D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -781,6 +783,18 @@ Global
{8C068694-23A2-47A2-A0DD-DB82D0AF0142}.Release|x64.Build.0 = Release|Any CPU
{8C068694-23A2-47A2-A0DD-DB82D0AF0142}.Release|x86.ActiveCfg = Release|Any CPU
{8C068694-23A2-47A2-A0DD-DB82D0AF0142}.Release|x86.Build.0 = Release|Any CPU
{24C7683D-2607-4901-B8EB-83A57E49E93D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{24C7683D-2607-4901-B8EB-83A57E49E93D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{24C7683D-2607-4901-B8EB-83A57E49E93D}.Debug|x64.ActiveCfg = Debug|Any CPU
{24C7683D-2607-4901-B8EB-83A57E49E93D}.Debug|x64.Build.0 = Debug|Any CPU
{24C7683D-2607-4901-B8EB-83A57E49E93D}.Debug|x86.ActiveCfg = Debug|Any CPU
{24C7683D-2607-4901-B8EB-83A57E49E93D}.Debug|x86.Build.0 = Debug|Any CPU
{24C7683D-2607-4901-B8EB-83A57E49E93D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{24C7683D-2607-4901-B8EB-83A57E49E93D}.Release|Any CPU.Build.0 = Release|Any CPU
{24C7683D-2607-4901-B8EB-83A57E49E93D}.Release|x64.ActiveCfg = Release|Any CPU
{24C7683D-2607-4901-B8EB-83A57E49E93D}.Release|x64.Build.0 = Release|Any CPU
{24C7683D-2607-4901-B8EB-83A57E49E93D}.Release|x86.ActiveCfg = Release|Any CPU
{24C7683D-2607-4901-B8EB-83A57E49E93D}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -849,6 +863,7 @@ Global
{826CD5AF-44FA-40F6-B731-3980CADED8C0} = {8DA7CBD9-F17E-41B6-90C4-CFF55848A25A}
{0D4DF78D-7E5F-4516-B19F-E6AA71A1DBF4} = {EE49F5DC-5835-4AE3-B3BA-8BDE0AD56330}
{8C068694-23A2-47A2-A0DD-DB82D0AF0142} = {376C19DE-31E2-4FF6-88FC-0D0D6233C999}
{24C7683D-2607-4901-B8EB-83A57E49E93D} = {376C19DE-31E2-4FF6-88FC-0D0D6233C999}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0541B30C-FF51-4E28-B172-83F5F3934BCD}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<ItemGroup Condition=" '$(TargetFramework)' == 'net451' ">
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.IO" />
<Reference Include="System.Runtime" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Xml" />
Expand Down
72 changes: 72 additions & 0 deletions src/Microsoft.TestPlatform.Common/Utilities/PEReaderHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Microsoft.VisualStudio.TestPlatform.Common.Utilities
{
using System;
using System.IO;
using System.Reflection.PortableExecutable;

using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers;
using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces;

public class PEReaderHelper
{
private readonly IFileHelper fileHelper;

/// <summary>
/// Initializes a new instance of the <see cref="PEReaderHelper"/> class.
/// </summary>
public PEReaderHelper() : this(new FileHelper())
{
}

/// <summary>
/// Initializes a new instance of the <see cref="PEReaderHelper"/> class.
/// </summary>
/// <param name="fileHelper">File helper.</param>
public PEReaderHelper(IFileHelper fileHelper)
{
this.fileHelper = fileHelper;
}

/// <summary>
/// Determines assembly type from file.
/// </summary>
public AssemblyType GetAssemblyType(string filePath)
{
var assemblyType = AssemblyType.None;

try
{
using (var fileStream = this.fileHelper.GetStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var peReader = new PEReader(fileStream))
{
// Resources for PEReader:
// 1. https://msdn.microsoft.com/library/windows/desktop/ms680547(v=vs.85).aspx?id=19509
// 2. https://github.com/dotnet/corefx/tree/master/src/System.Reflection.Metadata

var peHeaders = peReader.PEHeaders;
var corHeader = peHeaders.CorHeader;
var corHeaderStartOffset = peHeaders.CorHeaderStartOffset;

assemblyType = (corHeader != null && corHeaderStartOffset >= 0) ?
AssemblyType.Managed :
AssemblyType.Native;
}
}
catch (Exception ex)
{
EqtTrace.Warning("PEReaderHelper.GetAssemblyType: failed to determine assembly type: {0} for assembly: {1}", ex, filePath);
}

if (EqtTrace.IsInfoEnabled)
{
EqtTrace.Info("PEReaderHelper.GetAssemblyType: Determined assemblyType:'{0}' for source: '{1}'", assemblyType, filePath);
}

return assemblyType;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ public Stream GetStream(string filePath, FileMode mode, FileAccess access = File
return new FileStream(filePath, mode, access);
}

/// <inheritdoc/>
public Stream GetStream(string filePath, FileMode mode, FileAccess access, FileShare share)
{
return new FileStream(filePath, mode, access, share);
}


/// <inheritdoc/>
public IEnumerable<string> EnumerateFiles(
string directory,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@ public interface IFileHelper
/// <returns>A <see cref="Stream"/> that supports read/write on the file.</returns>
Stream GetStream(string filePath, FileMode mode, FileAccess access = FileAccess.ReadWrite);

/// <summary>
/// Gets a stream for the file.
/// </summary>
/// <param name="filePath">Path to the file.</param>
/// <param name="mode"><see cref="FileMode"/> for file operations.</param>
/// <param name="access"><see cref="FileAccess"/> for file operations.</param>
/// <param name="share"><see cref="FileShare"/> for file operations.</param>
/// <returns>A <see cref="Stream"/> that supports read/write on the file.</returns>
Stream GetStream(string filePath, FileMode mode, FileAccess access, FileShare share);

/// <summary>
/// Enumerates files which match a pattern (case insensitive) in a directory.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TestPlatformRoot Condition="$(TestPlatformRoot) == ''">..\..\</TestPlatformRoot>
<TestProject>true</TestProject>
</PropertyGroup>
<Import Project="$(TestPlatformRoot)scripts/build/TestPlatform.Settings.targets" />
<PropertyGroup>
<TargetFrameworks>netcoreapp1.0;net451</TargetFrameworks>
<AssemblyName>Microsoft.TestPlatform.Common.PlatformTests</AssemblyName>
<EnableCodeAnalysis>true</EnableCodeAnalysis>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.TestPlatform.TestUtilities\Microsoft.TestPlatform.TestUtilities.csproj" />
<PackageReference Include="Microsoft.TestPlatform.TestAsset.NativeCPP">
<Version>2.0.0</Version>
</PackageReference>
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net451' ">
<Reference Include="System.Runtime" />
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Runtime.Serialization" />
</ItemGroup>
<Import Project="$(TestPlatformRoot)scripts\build\TestPlatform.targets" />
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace TestPlatform.Common.UnitTests.Utilities
{
using Microsoft.TestPlatform.TestUtilities;
using Microsoft.VisualStudio.TestPlatform.Common.Utilities;
using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
public class PEReaderHelperTests : IntegrationTestBase
{
private PEReaderHelper peReaderHelper;

public PEReaderHelperTests()
{
this.peReaderHelper = new PEReaderHelper();
}

[TestMethod]
[DataRow("net451")]
[DataRow("netcoreapp1.0")]
[DataRow("netcoreapp2.0")]
public void GetAssemblyTypeForManagedDll(string framework)
{
var assemblyPath = this.testEnvironment.GetTestAsset("SimpleTestProject3.dll", framework);
var assemblyType = this.peReaderHelper.GetAssemblyType(assemblyPath);

Assert.AreEqual(AssemblyType.Managed, assemblyType);
}

[TestMethod]
public void GetAssemblyTypeForNativeDll()
{
var assemblyPath = $@"{this.testEnvironment.PackageDirectory}\microsoft.testplatform.testasset.nativecpp\2.0.0\contentFiles\any\any\Microsoft.TestPlatform.TestAsset.NativeCPP.dll";
var assemblyType = this.peReaderHelper.GetAssemblyType(assemblyPath);

Assert.AreEqual(AssemblyType.Native, assemblyType);
}

[TestMethod]
public void GetAssemblyTypeForManagedExe()
{
var assemblyPath = this.testEnvironment.GetTestAsset("ConsoleManagedApp.exe", "net451");
var assemblyType = this.peReaderHelper.GetAssemblyType(assemblyPath);

Assert.AreEqual(AssemblyType.Managed, assemblyType);
}

[TestMethod]
[DataRow("netcoreapp1.0")]
[DataRow("netcoreapp2.0")]
public void GetAssemblyTypeForNetCoreManagedExe(string framework)
{
var assemblyPath = this.testEnvironment.GetTestAsset("ConsoleManagedApp.dll", framework);
var assemblyType = this.peReaderHelper.GetAssemblyType(assemblyPath);

Assert.AreEqual(AssemblyType.Managed, assemblyType);
}

[TestMethod]
public void GetAssemblyTypeForNativeExe()
{
var assemblyPath = $@"{this.testEnvironment.PackageDirectory}\microsoft.testplatform.testasset.nativecpp\2.0.0\contentFiles\any\any\Microsoft.TestPlatform.TestAsset.ConsoleNativeApp.exe";
var assemblyType = this.peReaderHelper.GetAssemblyType(assemblyPath);

Assert.AreEqual(AssemblyType.Native, assemblyType);
}

[TestMethod]
public void GetAssemblyTypeShouldReturnNoneInCaseOfError()
{
var assemblyType = this.peReaderHelper.GetAssemblyType("invalidFile.dll");

Assert.AreEqual(AssemblyType.None, assemblyType);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<ProjectGuid>{076CE7E6-92E8-49FD-9D98-57D377FAA46E}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>CPPSimpleProj</RootNamespace>
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
<ProjectName>Microsoft.TestPlatform.TestAsset.NativeCPP</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// ConsoleNativeApp.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"


int main()
{
return 0;
}

Loading

0 comments on commit 534026f

Please sign in to comment.