diff --git a/TestPlatform.sln b/TestPlatform.sln index ab2597f00a..8f2bb70cd0 100644 --- a/TestPlatform.sln +++ b/TestPlatform.sln @@ -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 @@ -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 @@ -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} diff --git a/src/Microsoft.TestPlatform.Common/Microsoft.TestPlatform.Common.csproj b/src/Microsoft.TestPlatform.Common/Microsoft.TestPlatform.Common.csproj index 1729412020..982e0e7d36 100644 --- a/src/Microsoft.TestPlatform.Common/Microsoft.TestPlatform.Common.csproj +++ b/src/Microsoft.TestPlatform.Common/Microsoft.TestPlatform.Common.csproj @@ -15,6 +15,7 @@ + diff --git a/src/Microsoft.TestPlatform.Common/Utilities/PEReaderHelper.cs b/src/Microsoft.TestPlatform.Common/Utilities/PEReaderHelper.cs new file mode 100644 index 0000000000..7498d526db --- /dev/null +++ b/src/Microsoft.TestPlatform.Common/Utilities/PEReaderHelper.cs @@ -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; + + /// + /// Initializes a new instance of the class. + /// + public PEReaderHelper() : this(new FileHelper()) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// File helper. + public PEReaderHelper(IFileHelper fileHelper) + { + this.fileHelper = fileHelper; + } + + /// + /// Determines assembly type from file. + /// + 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; + } + } +} diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Helpers/FileHelper.cs b/src/Microsoft.TestPlatform.CoreUtilities/Helpers/FileHelper.cs index c324607f50..de8b1bac5b 100644 --- a/src/Microsoft.TestPlatform.CoreUtilities/Helpers/FileHelper.cs +++ b/src/Microsoft.TestPlatform.CoreUtilities/Helpers/FileHelper.cs @@ -48,6 +48,13 @@ public Stream GetStream(string filePath, FileMode mode, FileAccess access = File return new FileStream(filePath, mode, access); } + /// + public Stream GetStream(string filePath, FileMode mode, FileAccess access, FileShare share) + { + return new FileStream(filePath, mode, access, share); + } + + /// public IEnumerable EnumerateFiles( string directory, diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Helpers/Interfaces/IFileHelper.cs b/src/Microsoft.TestPlatform.CoreUtilities/Helpers/Interfaces/IFileHelper.cs index c130248fc2..fa7393242e 100644 --- a/src/Microsoft.TestPlatform.CoreUtilities/Helpers/Interfaces/IFileHelper.cs +++ b/src/Microsoft.TestPlatform.CoreUtilities/Helpers/Interfaces/IFileHelper.cs @@ -49,6 +49,16 @@ public interface IFileHelper /// A that supports read/write on the file. Stream GetStream(string filePath, FileMode mode, FileAccess access = FileAccess.ReadWrite); + /// + /// Gets a stream for the file. + /// + /// Path to the file. + /// for file operations. + /// for file operations. + /// for file operations. + /// A that supports read/write on the file. + Stream GetStream(string filePath, FileMode mode, FileAccess access, FileShare share); + /// /// Enumerates files which match a pattern (case insensitive) in a directory. /// diff --git a/test/Microsoft.TestPlatform.Common.PlatformTests/Microsoft.TestPlatform.Common.PlatformTests.csproj b/test/Microsoft.TestPlatform.Common.PlatformTests/Microsoft.TestPlatform.Common.PlatformTests.csproj new file mode 100644 index 0000000000..a60bcbe10d --- /dev/null +++ b/test/Microsoft.TestPlatform.Common.PlatformTests/Microsoft.TestPlatform.Common.PlatformTests.csproj @@ -0,0 +1,26 @@ + + + + ..\..\ + true + + + + netcoreapp1.0;net451 + Microsoft.TestPlatform.Common.PlatformTests + true + + + + + 2.0.0 + + + + + + + + + + diff --git a/test/Microsoft.TestPlatform.Common.PlatformTests/PEReaderHelperTests.cs b/test/Microsoft.TestPlatform.Common.PlatformTests/PEReaderHelperTests.cs new file mode 100644 index 0000000000..c3ce517c48 --- /dev/null +++ b/test/Microsoft.TestPlatform.Common.PlatformTests/PEReaderHelperTests.cs @@ -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); + } + } +} diff --git a/test/TestAssets/CPPSimpleTestProject/CPPSimpleProj/CPPSimpleProj.vcxproj b/test/TestAssets/CPPSimpleTestProject/CPPSimpleProj/CPPSimpleProj.vcxproj index 8d03529bc8..64881bccfa 100644 --- a/test/TestAssets/CPPSimpleTestProject/CPPSimpleProj/CPPSimpleProj.vcxproj +++ b/test/TestAssets/CPPSimpleTestProject/CPPSimpleProj/CPPSimpleProj.vcxproj @@ -22,7 +22,7 @@ {076CE7E6-92E8-49FD-9D98-57D377FAA46E} Win32Proj CPPSimpleProj - 10.0.15063.0 + 10.0.16299.0 Microsoft.TestPlatform.TestAsset.NativeCPP diff --git a/test/TestAssets/CPPSimpleTestProject/ConsoleNativeApp/ConsoleNativeApp.cpp b/test/TestAssets/CPPSimpleTestProject/ConsoleNativeApp/ConsoleNativeApp.cpp new file mode 100644 index 0000000000..bad0955883 --- /dev/null +++ b/test/TestAssets/CPPSimpleTestProject/ConsoleNativeApp/ConsoleNativeApp.cpp @@ -0,0 +1,11 @@ +// ConsoleNativeApp.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" + + +int main() +{ + return 0; +} + diff --git a/test/TestAssets/CPPSimpleTestProject/ConsoleNativeApp/ConsoleNativeApp.vcxproj b/test/TestAssets/CPPSimpleTestProject/ConsoleNativeApp/ConsoleNativeApp.vcxproj new file mode 100644 index 0000000000..e52de0bb3d --- /dev/null +++ b/test/TestAssets/CPPSimpleTestProject/ConsoleNativeApp/ConsoleNativeApp.vcxproj @@ -0,0 +1,165 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {84935EDB-ADBF-4438-815B-1E75EF608816} + Win32Proj + ConsoleNativeApp + 10.0.16299.0 + Microsoft.TestPlatform.TestAsset.ConsoleNativeApp + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Use + Level3 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Use + Level3 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Use + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Use + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + Create + Create + Create + Create + + + + + + \ No newline at end of file diff --git a/test/TestAssets/CPPSimpleTestProject/ConsoleNativeApp/ConsoleNativeApp.vcxproj.filters b/test/TestAssets/CPPSimpleTestProject/ConsoleNativeApp/ConsoleNativeApp.vcxproj.filters new file mode 100644 index 0000000000..5e29ba0d45 --- /dev/null +++ b/test/TestAssets/CPPSimpleTestProject/ConsoleNativeApp/ConsoleNativeApp.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/test/TestAssets/CPPSimpleTestProject/ConsoleNativeApp/stdafx.cpp b/test/TestAssets/CPPSimpleTestProject/ConsoleNativeApp/stdafx.cpp new file mode 100644 index 0000000000..8d211a4969 --- /dev/null +++ b/test/TestAssets/CPPSimpleTestProject/ConsoleNativeApp/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// ConsoleNativeApp.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/test/TestAssets/CPPSimpleTestProject/ConsoleNativeApp/stdafx.h b/test/TestAssets/CPPSimpleTestProject/ConsoleNativeApp/stdafx.h new file mode 100644 index 0000000000..b005a839de --- /dev/null +++ b/test/TestAssets/CPPSimpleTestProject/ConsoleNativeApp/stdafx.h @@ -0,0 +1,15 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#include +#include + + + +// TODO: reference additional headers your program requires here diff --git a/test/TestAssets/CPPSimpleTestProject/ConsoleNativeApp/targetver.h b/test/TestAssets/CPPSimpleTestProject/ConsoleNativeApp/targetver.h new file mode 100644 index 0000000000..87c0086de7 --- /dev/null +++ b/test/TestAssets/CPPSimpleTestProject/ConsoleNativeApp/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include diff --git a/test/TestAssets/CPPSimpleTestProject/Microsoft.TestPlatform.Asset.NativeCPP.nuspec b/test/TestAssets/CPPSimpleTestProject/Microsoft.TestPlatform.Asset.NativeCPP.nuspec index aff044584e..1aa97e694e 100644 --- a/test/TestAssets/CPPSimpleTestProject/Microsoft.TestPlatform.Asset.NativeCPP.nuspec +++ b/test/TestAssets/CPPSimpleTestProject/Microsoft.TestPlatform.Asset.NativeCPP.nuspec @@ -19,5 +19,7 @@ + + diff --git a/test/TestAssets/ConsoleManagedApp/ConsoleManagedApp.csproj b/test/TestAssets/ConsoleManagedApp/ConsoleManagedApp.csproj new file mode 100644 index 0000000000..39d9d2d398 --- /dev/null +++ b/test/TestAssets/ConsoleManagedApp/ConsoleManagedApp.csproj @@ -0,0 +1,12 @@ + + + + + + + ConsoleManagedApp + Exe + netcoreapp1.0;netcoreapp1.1;netcoreapp2.0;net451 + + + diff --git a/test/TestAssets/ConsoleManagedApp/Program.cs b/test/TestAssets/ConsoleManagedApp/Program.cs new file mode 100644 index 0000000000..247024f0a0 --- /dev/null +++ b/test/TestAssets/ConsoleManagedApp/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace ConsoleManagedApp +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + } + } +} diff --git a/test/TestAssets/TestAssets.sln/TestAssets.sln b/test/TestAssets/TestAssets.sln/TestAssets.sln index 35396765d0..c969b472f1 100644 --- a/test/TestAssets/TestAssets.sln/TestAssets.sln +++ b/test/TestAssets/TestAssets.sln/TestAssets.sln @@ -39,6 +39,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DisableAppdomainTest1", ".. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DisableAppdomainTest2", "..\DisableAppdomainTest2\DisableAppdomainTest2.csproj", "{A09B21CC-F726-413A-B185-3AE1172BAED0}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleManagedApp", "..\ConsoleManagedApp\ConsoleManagedApp.csproj", "{132E4690-DE43-4684-BA05-6942155EEAB5}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -117,6 +119,10 @@ Global {A09B21CC-F726-413A-B185-3AE1172BAED0}.Debug|Any CPU.Build.0 = Debug|Any CPU {A09B21CC-F726-413A-B185-3AE1172BAED0}.Release|Any CPU.ActiveCfg = Release|Any CPU {A09B21CC-F726-413A-B185-3AE1172BAED0}.Release|Any CPU.Build.0 = Release|Any CPU + {132E4690-DE43-4684-BA05-6942155EEAB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {132E4690-DE43-4684-BA05-6942155EEAB5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {132E4690-DE43-4684-BA05-6942155EEAB5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {132E4690-DE43-4684-BA05-6942155EEAB5}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE