diff --git a/src/Microsoft.DotNet.Tools.Pack/Program.cs b/src/Microsoft.DotNet.Tools.Pack/Program.cs index 838b7b9b8..3136461c0 100644 --- a/src/Microsoft.DotNet.Tools.Pack/Program.cs +++ b/src/Microsoft.DotNet.Tools.Pack/Program.cs @@ -51,7 +51,7 @@ namespace Microsoft.DotNet.Tools.Compiler var configValue = configuration.Value() ?? Cli.Utils.Constants.DefaultConfiguration; var outputValue = output.Value(); - return BuildPackage(path, configValue, outputValue, intermediateOutput.Value()) ? 0 : 1; + return BuildPackage(path, configValue, outputValue, intermediateOutput.Value()) ? 1 : 0; }); try diff --git a/src/Microsoft.DotNet.Tools.Test/Properties/AssemblyInfo.cs b/src/Microsoft.DotNet.Tools.Test/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..cdbb8074c --- /dev/null +++ b/src/Microsoft.DotNet.Tools.Test/Properties/AssemblyInfo.cs @@ -0,0 +1,8 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Reflection; +using System.Resources; + +[assembly: AssemblyMetadata("Serviceable", "True")] +[assembly: NeutralResourcesLanguage("en-us")] \ No newline at end of file diff --git a/src/Microsoft.DotNet.Tools.Test/ReportingChannel.cs b/src/Microsoft.DotNet.Tools.Test/ReportingChannel.cs new file mode 100644 index 000000000..cf2f2d33c --- /dev/null +++ b/src/Microsoft.DotNet.Tools.Test/ReportingChannel.cs @@ -0,0 +1,150 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Concurrent; +using System.Diagnostics; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using Microsoft.Extensions.Testing.Abstractions; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Microsoft.DotNet.Tools.Test +{ + public class ReportingChannel : IDisposable + { + public static ReportingChannel ListenOn(int port) + { + // This fixes the mono incompatibility but ties it to ipv4 connections + using (var listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) + { + listenSocket.Bind(new IPEndPoint(IPAddress.Loopback, port)); + listenSocket.Listen(10); + + var socket = listenSocket.Accept(); + + return new ReportingChannel(socket); + } + } + + private readonly BinaryWriter _writer; + private readonly BinaryReader _reader; + private readonly ManualResetEventSlim _ackWaitHandle; + + private ReportingChannel(Socket socket) + { + Socket = socket; + + var stream = new NetworkStream(Socket); + _writer = new BinaryWriter(stream); + _reader = new BinaryReader(stream); + _ackWaitHandle = new ManualResetEventSlim(); + + ReadQueue = new BlockingCollection(boundedCapacity: 1); + + // Read incoming messages on the background thread + new Thread(ReadMessages) { IsBackground = true }.Start(); + } + + public BlockingCollection ReadQueue { get; } + + public Socket Socket { get; private set; } + + public void Send(Message message) + { + lock (_writer) + { + try + { + TestHostTracing.Source.TraceEvent( + TraceEventType.Verbose, + 0, + "[ReportingChannel]: Send({0})", + message); + + _writer.Write(JsonConvert.SerializeObject(message)); + } + catch (Exception ex) + { + TestHostTracing.Source.TraceEvent( + TraceEventType.Error, + 0, + "[ReportingChannel]: Error sending {0}", + ex); + throw; + } + } + } + + public void SendError(string error) + { + Send(new Message() + { + MessageType = "Error", + Payload = JToken.FromObject(new ErrorMessage() + { + Message = error, + }), + }); + } + + public void SendError(Exception ex) + { + SendError(ex.ToString()); + } + + private void ReadMessages() + { + while (true) + { + try + { + var message = JsonConvert.DeserializeObject(_reader.ReadString()); + ReadQueue.Add(message); + + if (string.Equals(message.MessageType, "TestHost.Acknowledge")) + { + _ackWaitHandle.Set(); + ReadQueue.CompleteAdding(); + break; + } + } + catch (Exception ex) + { + TestHostTracing.Source.TraceEvent( + TraceEventType.Error, + 0, + "[ReportingChannel]: Waiting for message failed {0}", + ex); + throw; + } + } + } + + public void Dispose() + { + // Wait for a graceful disconnect - drain the queue until we get an 'ACK' + Message message; + while (ReadQueue.TryTake(out message, millisecondsTimeout: 1)) + { + } + + if (_ackWaitHandle.Wait(TimeSpan.FromSeconds(10))) + { + TestHostTracing.Source.TraceInformation("[ReportingChannel]: Received for ack from test host"); + } + else + { + TestHostTracing.Source.TraceEvent( + TraceEventType.Error, + 0, + "[ReportingChannel]: Timed out waiting for ack from test host"); + } + + Socket.Dispose(); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Tools.Test/TestHostTracing.cs b/src/Microsoft.DotNet.Tools.Test/TestHostTracing.cs new file mode 100644 index 000000000..809c3f70b --- /dev/null +++ b/src/Microsoft.DotNet.Tools.Test/TestHostTracing.cs @@ -0,0 +1,24 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Diagnostics; + +namespace Microsoft.DotNet.Tools.Test +{ + public static class TestHostTracing + { + public static readonly string TracingEnvironmentVariable = "DOTNET_TEST_TRACE"; + + public static readonly TraceSource Source; + + static TestHostTracing() + { + Source = Environment.GetEnvironmentVariable(TracingEnvironmentVariable) == "1" + ? new TraceSource("dotnet-test", SourceLevels.Verbose) + : new TraceSource("dotnet-test", SourceLevels.Warning); + + Source.Listeners.Add(new TextWriterTraceListener(Console.Error)); + } + } +} diff --git a/src/Microsoft.DotNet.Tools.Test/project.json b/src/Microsoft.DotNet.Tools.Test/project.json new file mode 100644 index 000000000..e1e584fa2 --- /dev/null +++ b/src/Microsoft.DotNet.Tools.Test/project.json @@ -0,0 +1,63 @@ +{ + "name": "dotnet-test", + "description": "Test host for discovering and running unit tests at design time, such as in Visual Studio.", + "version": "1.0.0-*", + "repository": { + "type": "git", + "url": "git://github.com/dotnet/cli" + }, + "compilationOptions": { + "warningsAsErrors": true, + "emitEntryPoint": true + }, + "dependencies": { + "Microsoft.NETCore.ConsoleHost": "1.0.0-beta-23409", + "Microsoft.NETCore.TestHost": "1.0.0-beta-23409", + "Microsoft.Extensions.Compilation.Abstractions": "1.0.0-*", + "Microsoft.DotNet.Cli.Utils": { + "type": "build", + "version": "1.0.0-*" + }, + "Microsoft.Dnx.Runtime.CommandParsing.Sources": { + "version": "1.0.0-*", + "type": "build" + }, + "Microsoft.Dnx.Runtime.Sources": { + "version": "1.0.0-*", + "type": "build" + }, + "Microsoft.Extensions.Testing.Abstractions": { + "version": "1.0.0-*", + "type": "build" + }, + "Microsoft.Extensions.CommandLineUtils.Sources": { + "version": "1.0.0-*", + "type": "build" + }, + "Microsoft.Extensions.Logging": "1.0.0-*", + "Newtonsoft.Json": "7.0.1" + }, + "frameworks": { + "dnxcore50": { + "dependencies": { + "System.Console": "4.0.0-beta-*", + "System.Diagnostics.Process": "4.1.0-beta-*", + "System.Diagnostics.TextWriterTraceListener": "4.0.0-beta-*", + "System.Diagnostics.TraceSource": "4.0.0-beta-*", + "System.Dynamic.Runtime": "4.0.11-beta-*", + "System.Net.Primitives": "4.0.11-beta-*", + "System.Net.Sockets": "4.1.0-beta-*", + "System.Runtime": "4.0.21-rc2-*", + "System.Reflection.Extensions": "4.0.1-beta-*", + "System.Reflection.TypeExtensions": "4.0.1-beta-*", + "System.Threading.Thread": "4.0.0-beta-*" + } + } + }, + "scripts": { + "postcompile": [ + "../../scripts/build/place-binary \"%compile:OutputDir%/%project:Name%.dll\"", + "../../scripts/build/place-binary \"%compile:OutputDir%/%project:Name%.pdb\"" + ] + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.Testing.Abstractions/DIA/DiaDataSource.cs b/src/Microsoft.Extensions.Testing.Abstractions/DIA/DiaDataSource.cs new file mode 100644 index 000000000..942d605ea --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/DIA/DiaDataSource.cs @@ -0,0 +1,13 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Runtime.InteropServices; + +namespace dia2 +{ + [ComImport] + [Guid("E6756135-1E65-4D17-8576-610761398C3C")] + public class DiaDataSource + { + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaDataSource.cs b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaDataSource.cs new file mode 100644 index 000000000..99669b8c1 --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaDataSource.cs @@ -0,0 +1,35 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Runtime.InteropServices; + +namespace dia2 +{ + [Guid("79F1BB5F-B66E-48E5-B6A9-1545C323CA3D"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IDiaDataSource + { + [DispId(1)] + string lastError + { + + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + void loadDataFromPdb([MarshalAs(UnmanagedType.LPWStr)] [In] string pdbPath); + + void loadAndValidateDataFromPdb([MarshalAs(UnmanagedType.LPWStr)] [In] string pdbPath, [In] ref Guid pcsig70, [In] uint sig, [In] uint age); + + void loadDataForExe([MarshalAs(UnmanagedType.LPWStr)] [In] string executable, [MarshalAs(UnmanagedType.LPWStr)] [In] string searchPath, [MarshalAs(UnmanagedType.IUnknown)] [In] object pCallback); + + void loadDataFromIStream([MarshalAs(UnmanagedType.Interface)] [In] IStream pIStream); + + void openSession([MarshalAs(UnmanagedType.Interface)] out IDiaSession ppSession); + + void loadDataFromCodeViewInfo([MarshalAs(UnmanagedType.LPWStr)] [In] string executable, [MarshalAs(UnmanagedType.LPWStr)] [In] string searchPath, [In] uint cbCvInfo, [In] ref byte pbCvInfo, [MarshalAs(UnmanagedType.IUnknown)] [In] object pCallback); + + void loadDataFromMiscInfo([MarshalAs(UnmanagedType.LPWStr)] [In] string executable, [MarshalAs(UnmanagedType.LPWStr)] [In] string searchPath, [In] uint timeStampExe, [In] uint timeStampDbg, [In] uint sizeOfExe, [In] uint cbMiscInfo, [In] ref byte pbMiscInfo, [MarshalAs(UnmanagedType.IUnknown)] [In] object pCallback); + } +} diff --git a/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumDebugStreamData.cs b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumDebugStreamData.cs new file mode 100644 index 000000000..70e7c59c2 --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumDebugStreamData.cs @@ -0,0 +1,40 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Collections; +using System.Reflection; +using System.Runtime.InteropServices; + +namespace dia2 +{ + [DefaultMember("Item"), Guid("486943E8-D187-4A6B-A3C4-291259FFF60D"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IDiaEnumDebugStreamData + { + [DispId(1)] + int count + { + + get; + } + [DispId(2)] + string name + { + + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + IEnumerator GetEnumerator(); + + void Item([In] uint index, [In] uint cbData, out uint pcbData, out byte pbData); + + void Next([In] uint celt, [In] uint cbData, out uint pcbData, out byte pbData, out uint pceltFetched); + + void Skip([In] uint celt); + + void Reset(); + + void Clone([MarshalAs(UnmanagedType.Interface)] out IDiaEnumDebugStreamData ppenum); + } +} diff --git a/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumDebugStreams.cs b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumDebugStreams.cs new file mode 100644 index 000000000..2b415c2d7 --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumDebugStreams.cs @@ -0,0 +1,35 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Collections; +using System.Reflection; +using System.Runtime.InteropServices; + +namespace dia2 +{ + [DefaultMember("Item"), Guid("08CBB41E-47A6-4F87-92F1-1C9C87CED044"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IDiaEnumDebugStreams + { + [DispId(1)] + int count + { + + get; + } + + [return: MarshalAs(UnmanagedType.Interface)] + IEnumerator GetEnumerator(); + + [return: MarshalAs(UnmanagedType.Interface)] + IDiaEnumDebugStreamData Item([In] object index); + + void Next([In] uint celt, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumDebugStreamData rgelt, out uint pceltFetched); + + void Skip([In] uint celt); + + void Reset(); + + void Clone([MarshalAs(UnmanagedType.Interface)] out IDiaEnumDebugStreams ppenum); + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumInjectedSources.cs b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumInjectedSources.cs new file mode 100644 index 000000000..3d1b2214f --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumInjectedSources.cs @@ -0,0 +1,34 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Collections; +using System.Reflection; +using System.Runtime.InteropServices; + +namespace dia2 +{ + [DefaultMember("Item"), Guid("D5612573-6925-4468-8883-98CDEC8C384A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IDiaEnumInjectedSources + { + [DispId(1)] + int count + { + + get; + } + + IEnumerator GetEnumerator(); + + [return: MarshalAs(UnmanagedType.Interface)] + IDiaInjectedSource Item([In] uint index); + + void Next([In] uint celt, [MarshalAs(UnmanagedType.Interface)] out IDiaInjectedSource rgelt, out uint pceltFetched); + + void Skip([In] uint celt); + + void Reset(); + + void Clone([MarshalAs(UnmanagedType.Interface)] out IDiaEnumInjectedSources ppenum); + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumInputAssemblyFiles.cs b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumInputAssemblyFiles.cs new file mode 100644 index 000000000..bf5fc842c --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumInputAssemblyFiles.cs @@ -0,0 +1,34 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Collections; +using System.Reflection; +using System.Runtime.InteropServices; + +namespace dia2 +{ + [DefaultMember("Item"), Guid("1C7FF653-51F7-457E-8419-B20F57EF7E4D"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IDiaEnumInputAssemblyFiles + { + [DispId(1)] + int count + { + + get; + } + + IEnumerator GetEnumerator(); + + [return: MarshalAs(UnmanagedType.Interface)] + IDiaInputAssemblyFile Item([In] uint index); + + void Next([In] uint celt, [MarshalAs(UnmanagedType.Interface)] out IDiaInputAssemblyFile rgelt, out uint pceltFetched); + + void Skip([In] uint celt); + + void Reset(); + + void Clone([MarshalAs(UnmanagedType.Interface)] out IDiaEnumInputAssemblyFiles ppenum); + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumLineNumbers.cs b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumLineNumbers.cs new file mode 100644 index 000000000..ebcc07838 --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumLineNumbers.cs @@ -0,0 +1,34 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Collections; +using System.Reflection; +using System.Runtime.InteropServices; + +namespace dia2 +{ + [DefaultMember("Item"), Guid("FE30E878-54AC-44F1-81BA-39DE940F6052"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IDiaEnumLineNumbers + { + [DispId(1)] + int count + { + + get; + } + + IEnumerator GetEnumerator(); + + [return: MarshalAs(UnmanagedType.Interface)] + IDiaLineNumber Item([In] uint index); + + void Next([In] uint celt, [MarshalAs(UnmanagedType.Interface)] out IDiaLineNumber rgelt, out uint pceltFetched); + + void Skip([In] uint celt); + + void Reset(); + + void Clone([MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppenum); + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumSourceFiles.cs b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumSourceFiles.cs new file mode 100644 index 000000000..139d13f19 --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumSourceFiles.cs @@ -0,0 +1,34 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Collections; +using System.Reflection; +using System.Runtime.InteropServices; + +namespace dia2 +{ + [DefaultMember("Item"), Guid("10F3DBD9-664F-4469-B808-9471C7A50538"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IDiaEnumSourceFiles + { + [DispId(1)] + int count + { + + get; + } + + IEnumerator GetEnumerator(); + + [return: MarshalAs(UnmanagedType.Interface)] + IDiaSourceFile Item([In] uint index); + + void Next([In] uint celt, [MarshalAs(UnmanagedType.Interface)] out IDiaSourceFile rgelt, out uint pceltFetched); + + void Skip([In] uint celt); + + void Reset(); + + void Clone([MarshalAs(UnmanagedType.Interface)] out IDiaEnumSourceFiles ppenum); + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumSymbols.cs b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumSymbols.cs new file mode 100644 index 000000000..189188426 --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumSymbols.cs @@ -0,0 +1,34 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Collections; +using System.Reflection; +using System.Runtime.InteropServices; + +namespace dia2 +{ + [DefaultMember("Item"), Guid("CAB72C48-443B-48F5-9B0B-42F0820AB29A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IDiaEnumSymbols + { + [DispId(1)] + int count + { + + get; + } + + IEnumerator GetEnumerator(); + + [return: MarshalAs(UnmanagedType.Interface)] + IDiaSymbol Item([In] uint index); + + void Next([In] uint celt, [MarshalAs(UnmanagedType.Interface)] out IDiaSymbol rgelt, out uint pceltFetched); + + void Skip([In] uint celt); + + void Reset(); + + void Clone([MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppenum); + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumSymbolsByAddr.cs b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumSymbolsByAddr.cs new file mode 100644 index 000000000..dc588e938 --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumSymbolsByAddr.cs @@ -0,0 +1,28 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Runtime.InteropServices; + +namespace dia2 +{ + [Guid("624B7D9C-24EA-4421-9D06-3B577471C1FA"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IDiaEnumSymbolsByAddr + { + + [return: MarshalAs(UnmanagedType.Interface)] + IDiaSymbol symbolByAddr([In] uint isect, [In] uint offset); + + [return: MarshalAs(UnmanagedType.Interface)] + IDiaSymbol symbolByRVA([In] uint relativeVirtualAddress); + + [return: MarshalAs(UnmanagedType.Interface)] + IDiaSymbol symbolByVA([In] ulong virtualAddress); + + void Next([In] uint celt, [MarshalAs(UnmanagedType.Interface)] out IDiaSymbol rgelt, out uint pceltFetched); + + void Prev([In] uint celt, [MarshalAs(UnmanagedType.Interface)] out IDiaSymbol rgelt, out uint pceltFetched); + + void Clone([MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbolsByAddr ppenum); + } +} diff --git a/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumTables.cs b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumTables.cs new file mode 100644 index 000000000..0293437bd --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaEnumTables.cs @@ -0,0 +1,34 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Collections; +using System.Reflection; +using System.Runtime.InteropServices; + +namespace dia2 +{ + [DefaultMember("Item"), Guid("C65C2B0A-1150-4D7A-AFCC-E05BF3DEE81E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IDiaEnumTables + { + [DispId(1)] + int count + { + + get; + } + + IEnumerator GetEnumerator(); + + [return: MarshalAs(UnmanagedType.Interface)] + IDiaTable Item([In] object index); + + void Next(uint celt, [MarshalAs(UnmanagedType.Interface)] out IDiaTable rgelt, ref uint pceltFetched); + + void Skip([In] uint celt); + + void Reset(); + + void Clone([MarshalAs(UnmanagedType.Interface)] out IDiaEnumTables ppenum); + } +} diff --git a/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaInjectedSource.cs b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaInjectedSource.cs new file mode 100644 index 000000000..cc97f3b55 --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaInjectedSource.cs @@ -0,0 +1,54 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Runtime.InteropServices; + +namespace dia2 +{ + [Guid("AE605CDC-8105-4A23-B710-3259F1E26112"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IDiaInjectedSource + { + [DispId(1)] + uint crc + { + + get; + } + [DispId(2)] + ulong length + { + + get; + } + [DispId(3)] + string fileName + { + + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + [DispId(4)] + string objectFileName + { + + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + [DispId(5)] + string virtualFilename + { + + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + [DispId(6)] + uint sourceCompression + { + + get; + } + + void get_source([In] uint cbData, out uint pcbData, out byte pbData); + } +} diff --git a/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaInputAssemblyFile.cs b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaInputAssemblyFile.cs new file mode 100644 index 000000000..dc2022151 --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaInputAssemblyFile.cs @@ -0,0 +1,46 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Runtime.InteropServices; + +namespace dia2 +{ + [Guid("3BFE56B0-390C-4863-9430-1F3D083B7684"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IDiaInputAssemblyFile + { + [DispId(1)] + uint uniqueId + { + + get; + } + [DispId(2)] + uint index + { + + get; + } + [DispId(3)] + uint timeStamp + { + + get; + } + [DispId(4)] + int pdbAvailableAtILMerge + { + + get; + } + [DispId(5)] + string fileName + { + + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + + void get_version([In] uint cbData, out uint pcbData, out byte pbData); + } +} diff --git a/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaLineNumber.cs b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaLineNumber.cs new file mode 100644 index 000000000..447e0411e --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaLineNumber.cs @@ -0,0 +1,99 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Runtime.InteropServices; + +namespace dia2 +{ + [Guid("B388EB14-BE4D-421D-A8A1-6CF7AB057086"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IDiaLineNumber + { + [DispId(1)] + IDiaSymbol compiland + { + + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + [DispId(2)] + IDiaSourceFile sourceFile + { + + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + [DispId(3)] + uint lineNumber + { + + get; + } + [DispId(4)] + uint lineNumberEnd + { + + get; + } + [DispId(5)] + uint columnNumber + { + + get; + } + [DispId(6)] + uint columnNumberEnd + { + + get; + } + [DispId(7)] + uint addressSection + { + + get; + } + [DispId(8)] + uint addressOffset + { + + get; + } + [DispId(9)] + uint relativeVirtualAddress + { + + get; + } + [DispId(10)] + ulong virtualAddress + { + + get; + } + [DispId(11)] + uint length + { + + get; + } + [DispId(12)] + uint sourceFileId + { + + get; + } + [DispId(13)] + int statement + { + + get; + } + [DispId(14)] + uint compilandId + { + + get; + } + } +} diff --git a/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaSession.cs b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaSession.cs new file mode 100644 index 000000000..34d3175ff --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaSession.cs @@ -0,0 +1,130 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Runtime.InteropServices; + +namespace dia2 +{ + [Guid("2F609EE1-D1C8-4E24-8288-3326BADCD211"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IDiaSession + { + [DispId(1)] + ulong loadAddress + { + + get; + + set; + } + [DispId(2)] + IDiaSymbol globalScope + { + + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + + void getEnumTables([MarshalAs(UnmanagedType.Interface)] out IDiaEnumTables ppEnumTables); + + void getSymbolsByAddr([MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbolsByAddr ppEnumbyAddr); + + void findChildren([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol parent, [In] SymTagEnum symTag, [MarshalAs(UnmanagedType.LPWStr)] [In] string name, [In] uint compareFlags, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult); + + void findChildrenEx([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol parent, [In] SymTagEnum symTag, [MarshalAs(UnmanagedType.LPWStr)] [In] string name, [In] uint compareFlags, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult); + + void findChildrenExByAddr([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol parent, [In] SymTagEnum symTag, [MarshalAs(UnmanagedType.LPWStr)] [In] string name, [In] uint compareFlags, [In] uint isect, [In] uint offset, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult); + + void findChildrenExByVA([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol parent, [In] SymTagEnum symTag, [MarshalAs(UnmanagedType.LPWStr)] [In] string name, [In] uint compareFlags, [In] ulong va, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult); + + void findChildrenExByRVA([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol parent, [In] SymTagEnum symTag, [MarshalAs(UnmanagedType.LPWStr)] [In] string name, [In] uint compareFlags, [In] uint rva, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult); + + void findSymbolByAddr([In] uint isect, [In] uint offset, [In] SymTagEnum symTag, [MarshalAs(UnmanagedType.Interface)] out IDiaSymbol ppSymbol); + + void findSymbolByRVA([In] uint rva, [In] SymTagEnum symTag, [MarshalAs(UnmanagedType.Interface)] out IDiaSymbol ppSymbol); + + void findSymbolByVA([In] ulong va, [In] SymTagEnum symTag, [MarshalAs(UnmanagedType.Interface)] out IDiaSymbol ppSymbol); + + void findSymbolByToken([In] uint token, [In] SymTagEnum symTag, [MarshalAs(UnmanagedType.Interface)] out IDiaSymbol ppSymbol); + + void symsAreEquiv([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol symbolA, [MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol symbolB); + + void symbolById([In] uint id, [MarshalAs(UnmanagedType.Interface)] out IDiaSymbol ppSymbol); + + void findSymbolByRVAEx([In] uint rva, [In] SymTagEnum symTag, [MarshalAs(UnmanagedType.Interface)] out IDiaSymbol ppSymbol, out int displacement); + + void findSymbolByVAEx([In] ulong va, [In] SymTagEnum symTag, [MarshalAs(UnmanagedType.Interface)] out IDiaSymbol ppSymbol, out int displacement); + + void findFile([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol pCompiland, [MarshalAs(UnmanagedType.LPWStr)] [In] string name, [In] uint compareFlags, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSourceFiles ppResult); + + void findFileById([In] uint uniqueId, [MarshalAs(UnmanagedType.Interface)] out IDiaSourceFile ppResult); + + void findLines([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol compiland, [MarshalAs(UnmanagedType.Interface)] [In] IDiaSourceFile file, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult); + + void findLinesByAddr([In] uint seg, [In] uint offset, [In] uint length, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult); + + void findLinesByRVA([In] uint rva, [In] uint length, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult); + + void findLinesByVA([In] ulong va, [In] uint length, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult); + + void findLinesByLinenum([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol compiland, [MarshalAs(UnmanagedType.Interface)] [In] IDiaSourceFile file, [In] uint linenum, [In] uint column, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult); + + void findInjectedSource([MarshalAs(UnmanagedType.LPWStr)] [In] string srcFile, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumInjectedSources ppResult); + + void getEnumDebugStreams([MarshalAs(UnmanagedType.Interface)] out IDiaEnumDebugStreams ppEnumDebugStreams); + + void findInlineFramesByAddr([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol parent, [In] uint isect, [In] uint offset, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult); + + void findInlineFramesByRVA([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol parent, [In] uint rva, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult); + + void findInlineFramesByVA([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol parent, [In] ulong va, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult); + + void findInlineeLines([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol parent, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult); + + void findInlineeLinesByAddr([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol parent, [In] uint isect, [In] uint offset, [In] uint length, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult); + + void findInlineeLinesByRVA([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol parent, [In] uint rva, [In] uint length, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult); + + void findInlineeLinesByVA([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol parent, [In] ulong va, [In] uint length, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult); + + void findInlineeLinesByLinenum([MarshalAs(UnmanagedType.Interface)] [In] IDiaSymbol compiland, [MarshalAs(UnmanagedType.Interface)] [In] IDiaSourceFile file, [In] uint linenum, [In] uint column, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult); + + void findInlineesByName([MarshalAs(UnmanagedType.LPWStr)] [In] string name, [In] uint option, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult); + + void addressForVA([In] ulong va, out uint pISect, out uint pOffset); + + void addressForRVA([In] uint rva, out uint pISect, out uint pOffset); + + void findILOffsetsByAddr([In] uint isect, [In] uint offset, [In] uint length, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult); + + void findILOffsetsByRVA([In] uint rva, [In] uint length, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult); + + void findILOffsetsByVA([In] ulong va, [In] uint length, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult); + + void findInputAssemblyFiles([MarshalAs(UnmanagedType.Interface)] out IDiaEnumInputAssemblyFiles ppResult); + + void findInputAssembly([In] uint index, [MarshalAs(UnmanagedType.Interface)] out IDiaInputAssemblyFile ppResult); + + void findInputAssemblyById([In] uint uniqueId, [MarshalAs(UnmanagedType.Interface)] out IDiaInputAssemblyFile ppResult); + + void getFuncMDTokenMapSize(out uint pcb); + + void getFuncMDTokenMap([In] uint cb, out uint pcb, out byte pb); + + void getTypeMDTokenMapSize(out uint pcb); + + void getTypeMDTokenMap([In] uint cb, out uint pcb, out byte pb); + + void getNumberOfFunctionFragments_VA([In] ulong vaFunc, [In] uint cbFunc, out uint pNumFragments); + + void getNumberOfFunctionFragments_RVA([In] uint rvaFunc, [In] uint cbFunc, out uint pNumFragments); + + void getFunctionFragments_VA([In] ulong vaFunc, [In] uint cbFunc, [In] uint cFragments, out ulong pVaFragment, out uint pLenFragment); + + void getFunctionFragments_RVA([In] uint rvaFunc, [In] uint cbFunc, [In] uint cFragments, out uint pRvaFragment, out uint pLenFragment); + + void getExports([MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult); + + void getHeapAllocationSites([MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult); + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaSourceFile.cs b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaSourceFile.cs new file mode 100644 index 000000000..c03d7d869 --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaSourceFile.cs @@ -0,0 +1,42 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Runtime.InteropServices; + +namespace dia2 +{ + [Guid("A2EF5353-F5A8-4EB3-90D2-CB526ACB3CDD"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IDiaSourceFile + { + [DispId(2)] + uint uniqueId + { + + get; + } + [DispId(3)] + string fileName + { + + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + [DispId(4)] + uint checksumType + { + + get; + } + [DispId(5)] + IDiaEnumSymbols compilands + { + + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + + + void get_checksum([In] uint cbData, out uint pcbData, out byte pbData); + } +} diff --git a/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaSymbol.cs b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaSymbol.cs new file mode 100644 index 000000000..b8a3c3e6b --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaSymbol.cs @@ -0,0 +1,1269 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Reflection; +using System.Runtime.InteropServices; + +namespace dia2 +{ + [DefaultMember("symIndexId"), Guid("CB787B2F-BD6C-4635-BA52-933126BD2DCD"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IDiaSymbol + { + [DispId(0)] + uint symIndexId + { + + get; + } + [DispId(1)] + uint symTag + { + + get; + } + [DispId(2)] + string name + { + + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + [DispId(3)] + IDiaSymbol lexicalParent + { + + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + [DispId(4)] + IDiaSymbol classParent + { + + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + [DispId(5)] + IDiaSymbol type + { + + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + [DispId(6)] + uint dataKind + { + + get; + } + [DispId(7)] + uint locationType + { + + get; + } + [DispId(8)] + uint addressSection + { + + get; + } + [DispId(9)] + uint addressOffset + { + + get; + } + [DispId(10)] + uint relativeVirtualAddress + { + + get; + } + [DispId(11)] + ulong virtualAddress + { + + get; + } + [DispId(12)] + uint registerId + { + + get; + } + [DispId(13)] + int offset + { + + get; + } + [DispId(14)] + ulong length + { + + get; + } + [DispId(15)] + uint slot + { + + get; + } + [DispId(16)] + int volatileType + { + + get; + } + [DispId(17)] + int constType + { + + get; + } + [DispId(18)] + int unalignedType + { + + get; + } + [DispId(19)] + uint access + { + + get; + } + [DispId(20)] + string libraryName + { + + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + [DispId(21)] + uint platform + { + + get; + } + [DispId(22)] + uint language + { + + get; + } + [DispId(23)] + int editAndContinueEnabled + { + + get; + } + [DispId(24)] + uint frontEndMajor + { + + get; + } + [DispId(25)] + uint frontEndMinor + { + + get; + } + [DispId(26)] + uint frontEndBuild + { + + get; + } + [DispId(27)] + uint backEndMajor + { + + get; + } + [DispId(28)] + uint backEndMinor + { + + get; + } + [DispId(29)] + uint backEndBuild + { + + get; + } + [DispId(30)] + string sourceFileName + { + + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + [DispId(31)] + string unused + { + + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + [DispId(32)] + uint thunkOrdinal + { + + get; + } + [DispId(33)] + int thisAdjust + { + + get; + } + [DispId(34)] + uint virtualBaseOffset + { + + get; + } + [DispId(35)] + int @virtual + { + + get; + } + [DispId(36)] + int intro + { + + get; + } + [DispId(37)] + int pure + { + + get; + } + [DispId(38)] + uint callingConvention + { + + get; + } + [DispId(39)] + object value + { + + get; + } + [DispId(40)] + uint baseType + { + + get; + } + [DispId(41)] + uint token + { + + get; + } + [DispId(42)] + uint timeStamp + { + + get; + } + [DispId(43)] + Guid guid + { + + get; + } + [DispId(44)] + string symbolsFileName + { + + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + [DispId(46)] + int reference + { + + get; + } + [DispId(47)] + uint count + { + + get; + } + [DispId(49)] + uint bitPosition + { + + get; + } + [DispId(50)] + IDiaSymbol arrayIndexType + { + + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + [DispId(51)] + int packed + { + + get; + } + [DispId(52)] + int constructor + { + + get; + } + [DispId(53)] + int overloadedOperator + { + + get; + } + [DispId(54)] + int nested + { + + get; + } + [DispId(55)] + int hasNestedTypes + { + + get; + } + [DispId(56)] + int hasAssignmentOperator + { + + get; + } + [DispId(57)] + int hasCastOperator + { + + get; + } + [DispId(58)] + int scoped + { + + get; + } + [DispId(59)] + int virtualBaseClass + { + + get; + } + [DispId(60)] + int indirectVirtualBaseClass + { + + get; + } + [DispId(61)] + int virtualBasePointerOffset + { + + get; + } + [DispId(62)] + IDiaSymbol virtualTableShape + { + + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + [DispId(64)] + uint lexicalParentId + { + + get; + } + [DispId(65)] + uint classParentId + { + + get; + } + [DispId(66)] + uint typeId + { + + get; + } + [DispId(67)] + uint arrayIndexTypeId + { + + get; + } + [DispId(68)] + uint virtualTableShapeId + { + + get; + } + [DispId(69)] + int code + { + + get; + } + [DispId(70)] + int function + { + + get; + } + [DispId(71)] + int managed + { + + get; + } + [DispId(72)] + int msil + { + + get; + } + [DispId(73)] + uint virtualBaseDispIndex + { + + get; + } + [DispId(74)] + string undecoratedName + { + + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + [DispId(75)] + uint age + { + + get; + } + [DispId(76)] + uint signature + { + + get; + } + [DispId(77)] + int compilerGenerated + { + + get; + } + [DispId(78)] + int addressTaken + { + + get; + } + [DispId(79)] + uint rank + { + + get; + } + [DispId(80)] + IDiaSymbol lowerBound + { + + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + [DispId(81)] + IDiaSymbol upperBound + { + + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + [DispId(82)] + uint lowerBoundId + { + + get; + } + [DispId(83)] + uint upperBoundId + { + + get; + } + [DispId(84)] + uint targetSection + { + + get; + } + [DispId(85)] + uint targetOffset + { + + get; + } + [DispId(86)] + uint targetRelativeVirtualAddress + { + + get; + } + [DispId(87)] + ulong targetVirtualAddress + { + + get; + } + [DispId(88)] + uint machineType + { + + get; + } + [DispId(89)] + uint oemId + { + + get; + } + [DispId(90)] + uint oemSymbolId + { + + get; + } + [DispId(91)] + IDiaSymbol objectPointerType + { + + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + [DispId(92)] + uint udtKind + { + + get; + } + [DispId(93)] + int noReturn + { + + get; + } + [DispId(94)] + int customCallingConvention + { + + get; + } + [DispId(95)] + int noInline + { + + get; + } + [DispId(96)] + int optimizedCodeDebugInfo + { + + get; + } + [DispId(97)] + int notReached + { + + get; + } + [DispId(98)] + int interruptReturn + { + + get; + } + [DispId(99)] + int farReturn + { + + get; + } + [DispId(100)] + int isStatic + { + + get; + } + [DispId(101)] + int hasDebugInfo + { + + get; + } + [DispId(102)] + int isLTCG + { + + get; + } + [DispId(103)] + int isDataAligned + { + + get; + } + [DispId(104)] + int hasSecurityChecks + { + + get; + } + [DispId(105)] + string compilerName + { + + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + [DispId(106)] + int hasAlloca + { + + get; + } + [DispId(107)] + int hasSetJump + { + + get; + } + [DispId(108)] + int hasLongJump + { + + get; + } + [DispId(109)] + int hasInlAsm + { + + get; + } + [DispId(110)] + int hasEH + { + + get; + } + [DispId(111)] + int hasSEH + { + + get; + } + [DispId(112)] + int hasEHa + { + + get; + } + [DispId(113)] + int isNaked + { + + get; + } + [DispId(114)] + int isAggregated + { + + get; + } + [DispId(115)] + int isSplitted + { + + get; + } + [DispId(116)] + IDiaSymbol container + { + + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + [DispId(117)] + int inlSpec + { + + get; + } + [DispId(118)] + int noStackOrdering + { + + get; + } + [DispId(119)] + IDiaSymbol virtualBaseTableType + { + + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + [DispId(120)] + int hasManagedCode + { + + get; + } + [DispId(121)] + int isHotpatchable + { + + get; + } + [DispId(122)] + int isCVTCIL + { + + get; + } + [DispId(123)] + int isMSILNetmodule + { + + get; + } + [DispId(124)] + int isCTypes + { + + get; + } + [DispId(125)] + int isStripped + { + + get; + } + [DispId(126)] + uint frontEndQFE + { + + get; + } + [DispId(127)] + uint backEndQFE + { + + get; + } + [DispId(128)] + int wasInlined + { + + get; + } + [DispId(129)] + int strictGSCheck + { + + get; + } + [DispId(130)] + int isCxxReturnUdt + { + + get; + } + [DispId(131)] + int isConstructorVirtualBase + { + + get; + } + [DispId(132)] + int RValueReference + { + + get; + } + [DispId(133)] + IDiaSymbol unmodifiedType + { + + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + [DispId(134)] + int framePointerPresent + { + + get; + } + [DispId(135)] + int isSafeBuffers + { + + get; + } + [DispId(136)] + int intrinsic + { + + get; + } + [DispId(137)] + int @sealed + { + + get; + } + [DispId(138)] + int hfaFloat + { + + get; + } + [DispId(139)] + int hfaDouble + { + + get; + } + [DispId(140)] + uint liveRangeStartAddressSection + { + + get; + } + [DispId(141)] + uint liveRangeStartAddressOffset + { + + get; + } + [DispId(142)] + uint liveRangeStartRelativeVirtualAddress + { + + get; + } + [DispId(143)] + uint countLiveRanges + { + + get; + } + [DispId(144)] + ulong liveRangeLength + { + + get; + } + [DispId(145)] + uint offsetInUdt + { + + get; + } + [DispId(146)] + uint paramBasePointerRegisterId + { + + get; + } + [DispId(147)] + uint localBasePointerRegisterId + { + + get; + } + [DispId(148)] + int isLocationControlFlowDependent + { + + get; + } + [DispId(149)] + uint stride + { + + get; + } + [DispId(150)] + uint numberOfRows + { + + get; + } + [DispId(151)] + uint numberOfColumns + { + + get; + } + [DispId(152)] + int isMatrixRowMajor + { + + get; + } + [DispId(153)] + int isReturnValue + { + + get; + } + [DispId(154)] + int isOptimizedAway + { + + get; + } + [DispId(155)] + uint builtInKind + { + + get; + } + [DispId(156)] + uint registerType + { + + get; + } + [DispId(157)] + uint baseDataSlot + { + + get; + } + [DispId(158)] + uint baseDataOffset + { + + get; + } + [DispId(159)] + uint textureSlot + { + + get; + } + [DispId(160)] + uint samplerSlot + { + + get; + } + [DispId(161)] + uint uavSlot + { + + get; + } + [DispId(162)] + uint sizeInUdt + { + + get; + } + [DispId(163)] + uint memorySpaceKind + { + + get; + } + [DispId(164)] + uint unmodifiedTypeId + { + + get; + } + [DispId(165)] + uint subTypeId + { + + get; + } + [DispId(166)] + IDiaSymbol subType + { + + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + [DispId(167)] + uint numberOfModifiers + { + + get; + } + [DispId(168)] + uint numberOfRegisterIndices + { + + get; + } + [DispId(169)] + int isHLSLData + { + + get; + } + [DispId(170)] + int isPointerToDataMember + { + + get; + } + [DispId(171)] + int isPointerToMemberFunction + { + + get; + } + [DispId(172)] + int isSingleInheritance + { + + get; + } + [DispId(173)] + int isMultipleInheritance + { + + get; + } + [DispId(174)] + int isVirtualInheritance + { + + get; + } + [DispId(175)] + int restrictedType + { + + get; + } + [DispId(176)] + int isPointerBasedOnSymbolValue + { + + get; + } + [DispId(177)] + IDiaSymbol baseSymbol + { + + [return: MarshalAs(UnmanagedType.Interface)] + get; + } + [DispId(178)] + uint baseSymbolId + { + + get; + } + [DispId(179)] + string objectFileName + { + + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + [DispId(184)] + int isSdl + { + + get; + } + [DispId(185)] + int isWinRTPointer + { + + get; + } + [DispId(186)] + int isRefUdt + { + + get; + } + [DispId(187)] + int isValueUdt + { + + get; + } + [DispId(188)] + int isInterfaceUdt + { + + get; + } + [DispId(189)] + int isPGO + { + + get; + } + [DispId(190)] + int hasValidPGOCounts + { + + get; + } + [DispId(191)] + int isOptimizedForSpeed + { + + get; + } + [DispId(192)] + uint PGOEntryCount + { + + get; + } + [DispId(193)] + uint PGOEdgeCount + { + + get; + } + [DispId(194)] + ulong PGODynamicInstructionCount + { + + get; + } + [DispId(195)] + uint staticSize + { + + get; + } + [DispId(196)] + uint finalLiveStaticSize + { + + get; + } + [DispId(197)] + string phaseName + { + + [return: MarshalAs(UnmanagedType.BStr)] + get; + } + [DispId(198)] + int hasControlFlowCheck + { + + get; + } + [DispId(199)] + int constantExport + { + + get; + } + [DispId(200)] + int dataExport + { + + get; + } + [DispId(201)] + int privateExport + { + + get; + } + [DispId(202)] + int noNameExport + { + + get; + } + [DispId(203)] + int exportHasExplicitlyAssignedOrdinal + { + + get; + } + [DispId(204)] + int exportIsForwarder + { + + get; + } + [DispId(205)] + uint ordinal + { + + get; + } + + void get_dataBytes([In] uint cbData, out uint pcbData, out byte pbData); + + void findChildren([In] SymTagEnum symTag, [MarshalAs(UnmanagedType.LPWStr)] [In] string name, [In] uint compareFlags, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult); + + void findChildrenEx([In] SymTagEnum symTag, [MarshalAs(UnmanagedType.LPWStr)] [In] string name, [In] uint compareFlags, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult); + + void findChildrenExByAddr([In] SymTagEnum symTag, [MarshalAs(UnmanagedType.LPWStr)] [In] string name, [In] uint compareFlags, [In] uint isect, [In] uint offset, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult); + + void findChildrenExByVA([In] SymTagEnum symTag, [MarshalAs(UnmanagedType.LPWStr)] [In] string name, [In] uint compareFlags, [In] ulong va, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult); + + void findChildrenExByRVA([In] SymTagEnum symTag, [MarshalAs(UnmanagedType.LPWStr)] [In] string name, [In] uint compareFlags, [In] uint rva, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult); + + void get_types([In] uint cTypes, out uint pcTypes, [MarshalAs(UnmanagedType.Interface)] out IDiaSymbol pTypes); + + void get_typeIds([In] uint cTypeIds, out uint pcTypeIds, out uint pdwTypeIds); + + void get_undecoratedNameEx([In] uint undecorateOptions, [MarshalAs(UnmanagedType.BStr)] out string name); + + void get_numericProperties([In] uint cnt, out uint pcnt, out uint pProperties); + + void get_modifierValues([In] uint cnt, out uint pcnt, out ushort pModifiers); + + void findInlineFramesByAddr([In] uint isect, [In] uint offset, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult); + + void findInlineFramesByRVA([In] uint rva, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult); + + void findInlineFramesByVA([In] ulong va, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumSymbols ppResult); + + void findInlineeLines([MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult); + + void findInlineeLinesByAddr([In] uint isect, [In] uint offset, [In] uint length, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult); + + void findInlineeLinesByRVA([In] uint rva, [In] uint length, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult); + + void findInlineeLinesByVA([In] ulong va, [In] uint length, [MarshalAs(UnmanagedType.Interface)] out IDiaEnumLineNumbers ppResult); + + void getSrcLineOnTypeDefn([MarshalAs(UnmanagedType.Interface)] out IDiaLineNumber ppResult); + } +} diff --git a/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaTable.cs b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaTable.cs new file mode 100644 index 000000000..e42d52760 --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaTable.cs @@ -0,0 +1,40 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Collections; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace dia2 +{ + [TypeIdentifier] + [CompilerGenerated] + [DefaultMember("Item"), Guid("4A59FB77-ABAC-469B-A30B-9ECC85BFEF14"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IDiaTable : IEnumUnknown + { + string name { get; } + + [DispId(2)] + int count + { + get; + } + + new void RemoteNext([In] uint celt, [MarshalAs(UnmanagedType.IUnknown)] out object rgelt, out uint pceltFetched); + + new void Skip([In] uint celt); + + new void Reset(); + + new void Clone([MarshalAs(UnmanagedType.Interface)] out IEnumUnknown ppenum); + + [return: MarshalAs(UnmanagedType.IUnknown, MarshalType = "System.Runtime.InteropServices.CustomMarshalers.EnumeratorToEnumVariantMarshaler")] + IEnumerator GetEnumerator(); + + + [return: MarshalAs(UnmanagedType.IUnknown)] + object Item([In] uint index); + } +} diff --git a/src/Microsoft.Extensions.Testing.Abstractions/DIA/IEnumUnknown.cs b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IEnumUnknown.cs new file mode 100644 index 000000000..f4976e5d5 --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IEnumUnknown.cs @@ -0,0 +1,20 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Runtime.InteropServices; + +namespace dia2 +{ + [Guid("00000100-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IEnumUnknown + { + void RemoteNext([In] uint celt, [MarshalAs(UnmanagedType.IUnknown)] out object rgelt, out uint pceltFetched); + + void Skip([In] uint celt); + + void Reset(); + + void Clone([MarshalAs(UnmanagedType.Interface)] out IEnumUnknown ppenum); + } +} diff --git a/src/Microsoft.Extensions.Testing.Abstractions/DIA/ISequentialStream.cs b/src/Microsoft.Extensions.Testing.Abstractions/DIA/ISequentialStream.cs new file mode 100644 index 000000000..f5baae399 --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/DIA/ISequentialStream.cs @@ -0,0 +1,17 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Runtime.InteropServices; + +namespace dia2 +{ + [Guid("0C733A30-2A1C-11CE-ADE5-00AA0044773D"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface ISequentialStream + { + + void RemoteRead([Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, int cb, out uint pcbRead); + + void RemoteWrite([In] ref byte pv, [In] uint cb, out uint pcbWritten); + } +} diff --git a/src/Microsoft.Extensions.Testing.Abstractions/DIA/IStream.cs b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IStream.cs new file mode 100644 index 000000000..dc9e41920 --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/DIA/IStream.cs @@ -0,0 +1,34 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Runtime.InteropServices; + +namespace dia2 +{ + [Guid("0000000C-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IStream : ISequentialStream + { + new void RemoteRead([Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, int cb, out uint pcbRead); + + new void RemoteWrite([In] ref byte pv, [In] uint cb, out uint pcbWritten); + + void RemoteSeek([In] _LARGE_INTEGER dlibMove, [In] uint dwOrigin, out _ULARGE_INTEGER plibNewPosition); + + void SetSize([In] _ULARGE_INTEGER libNewSize); + + void RemoteCopyTo([MarshalAs(UnmanagedType.Interface)] [In] IStream pstm, [In] _ULARGE_INTEGER cb, out _ULARGE_INTEGER pcbRead, out _ULARGE_INTEGER pcbWritten); + + void Commit([In] uint grfCommitFlags); + + void Revert(); + + void LockRegion([In] _ULARGE_INTEGER libOffset, [In] _ULARGE_INTEGER cb, [In] uint dwLockType); + + void UnlockRegion([In] _ULARGE_INTEGER libOffset, [In] _ULARGE_INTEGER cb, [In] uint dwLockType); + + void Stat(out tagSTATSTG pstatstg, [In] uint grfStatFlag); + + void Clone([MarshalAs(UnmanagedType.Interface)] out IStream ppstm); + } +} diff --git a/src/Microsoft.Extensions.Testing.Abstractions/DIA/StreamWrapper.cs b/src/Microsoft.Extensions.Testing.Abstractions/DIA/StreamWrapper.cs new file mode 100644 index 000000000..6fcf6a3ba --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/DIA/StreamWrapper.cs @@ -0,0 +1,80 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.IO; +using System.Runtime.InteropServices; + +namespace dia2 +{ + public class StreamWrapper : IStream + { + private Stream _stream; + + public StreamWrapper(Stream stream) + { + _stream = stream; + } + + public void RemoteRead(byte[] pv, int cb, out uint pcbRead) + { + pcbRead = (uint)_stream.Read(pv, 0, cb); + } + + public void Stat(out tagSTATSTG pstatstg, [In]uint grfStatFlag) + { + pstatstg = new tagSTATSTG(); + pstatstg.cbSize.QuadPart = (ulong)_stream.Length; + } + + public void RemoteSeek([In]_LARGE_INTEGER dlibMove, [In]uint dwOrigin, out _ULARGE_INTEGER plibNewPosition) + { + plibNewPosition.QuadPart = (ulong)_stream.Seek(dlibMove.QuadPart, (SeekOrigin)dwOrigin); + } + + public void RemoteRead(byte[] pv, [In]uint cb, out uint pcbRead) + { + pcbRead = (uint)_stream.Read(pv, offset: 0, count: (int)cb); + } + + public void SetSize([In]_ULARGE_INTEGER libNewSize) + { + throw new NotImplementedException(); + } + + public void RemoteCopyTo([In, MarshalAs(UnmanagedType.Interface)]IStream pstm, [In]_ULARGE_INTEGER cb, out _ULARGE_INTEGER pcbRead, out _ULARGE_INTEGER pcbWritten) + { + throw new NotImplementedException(); + } + + public void Commit([In]uint grfCommitFlags) + { + throw new NotImplementedException(); + } + + public void Revert() + { + throw new NotImplementedException(); + } + + public void LockRegion([In]_ULARGE_INTEGER libOffset, [In]_ULARGE_INTEGER cb, [In]uint dwLockType) + { + throw new NotImplementedException(); + } + + public void UnlockRegion([In]_ULARGE_INTEGER libOffset, [In]_ULARGE_INTEGER cb, [In]uint dwLockType) + { + throw new NotImplementedException(); + } + + public void Clone([MarshalAs(UnmanagedType.Interface)]out IStream ppstm) + { + throw new NotImplementedException(); + } + + public void RemoteWrite([In]ref byte pv, [In]uint cb, out uint pcbWritten) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.Testing.Abstractions/DIA/Structs.cs b/src/Microsoft.Extensions.Testing.Abstractions/DIA/Structs.cs new file mode 100644 index 000000000..a53012f36 --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/DIA/Structs.cs @@ -0,0 +1,44 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Runtime.InteropServices; + +namespace dia2 +{ + [StructLayout(LayoutKind.Sequential, Pack = 8)] + public struct _LARGE_INTEGER + { + public long QuadPart; + } + + [StructLayout(LayoutKind.Sequential, Pack = 8)] + public struct _ULARGE_INTEGER + { + public ulong QuadPart; + } + + [StructLayout(LayoutKind.Sequential, Pack = 8)] + public struct tagSTATSTG + { + [MarshalAs(UnmanagedType.LPWStr)] + public string pwcsName; + public uint type; + public _ULARGE_INTEGER cbSize; + public _FILETIME mtime; + public _FILETIME ctime; + public _FILETIME atime; + public uint grfMode; + public uint grfLocksSupported; + public Guid clsid; + public uint grfStateBits; + public uint reserved; + } + + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct _FILETIME + { + public uint dwLowDateTime; + public uint dwHighDateTime; + } +} diff --git a/src/Microsoft.Extensions.Testing.Abstractions/DIA/SymTagEnum.cs b/src/Microsoft.Extensions.Testing.Abstractions/DIA/SymTagEnum.cs new file mode 100644 index 000000000..b1103077b --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/DIA/SymTagEnum.cs @@ -0,0 +1,51 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace dia2 +{ + public enum SymTagEnum + { + SymTagNull, + SymTagExe, + SymTagCompiland, + SymTagCompilandDetails, + SymTagCompilandEnv, + SymTagFunction, + SymTagBlock, + SymTagData, + SymTagAnnotation, + SymTagLabel, + SymTagPublicSymbol, + SymTagUDT, + SymTagEnum, + SymTagFunctionType, + SymTagPointerType, + SymTagArrayType, + SymTagBaseType, + SymTagTypedef, + SymTagBaseClass, + SymTagFriend, + SymTagFunctionArgType, + SymTagFuncDebugStart, + SymTagFuncDebugEnd, + SymTagUsingNamespace, + SymTagVTableShape, + SymTagVTable, + SymTagCustom, + SymTagThunk, + SymTagCustomType, + SymTagManagedType, + SymTagDimension, + SymTagCallSite, + SymTagInlineSite, + SymTagBaseInterface, + SymTagVectorType, + SymTagMatrixType, + SymTagHLSLType, + SymTagCaller, + SymTagCallee, + SymTagExport, + SymTagHeapAllocationSite, + SymTagMax + } +} diff --git a/src/Microsoft.Extensions.Testing.Abstractions/ISourceInformationProvider.cs b/src/Microsoft.Extensions.Testing.Abstractions/ISourceInformationProvider.cs new file mode 100644 index 000000000..08c38fca8 --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/ISourceInformationProvider.cs @@ -0,0 +1,12 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Reflection; + +namespace Microsoft.Extensions.Testing.Abstractions +{ + public interface ISourceInformationProvider + { + SourceInformation GetSourceInformation(MethodInfo method); + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.Testing.Abstractions/ITestDiscoverySink.cs b/src/Microsoft.Extensions.Testing.Abstractions/ITestDiscoverySink.cs new file mode 100644 index 000000000..0529c1a3b --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/ITestDiscoverySink.cs @@ -0,0 +1,10 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Microsoft.Extensions.Testing.Abstractions +{ + public interface ITestDiscoverySink + { + void SendTestFound(Test test); + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.Testing.Abstractions/Messages/ErrorMessage.cs b/src/Microsoft.Extensions.Testing.Abstractions/Messages/ErrorMessage.cs new file mode 100644 index 000000000..254889ef8 --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/Messages/ErrorMessage.cs @@ -0,0 +1,10 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Microsoft.DotNet.Tools.Test +{ + public class ErrorMessage + { + public string Message { get; set; } + } +} diff --git a/src/Microsoft.Extensions.Testing.Abstractions/Messages/Message.cs b/src/Microsoft.Extensions.Testing.Abstractions/Messages/Message.cs new file mode 100644 index 000000000..5a40f7470 --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/Messages/Message.cs @@ -0,0 +1,20 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Microsoft.Extensions.Testing.Abstractions +{ + public class Message + { + public string MessageType { get; set; } + + public JToken Payload { get; set; } + + public override string ToString() + { + return "(" + MessageType + ") -> " + (Payload == null ? "null" : Payload.ToString(Formatting.Indented)); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.Testing.Abstractions/Messages/ProtocolVersionMessage.cs b/src/Microsoft.Extensions.Testing.Abstractions/Messages/ProtocolVersionMessage.cs new file mode 100644 index 000000000..3aa6e78fc --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/Messages/ProtocolVersionMessage.cs @@ -0,0 +1,10 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Microsoft.DotNet.Tools.Test +{ + public class ProtocolVersionMessage + { + public int Version { get; set; } + } +} diff --git a/src/Microsoft.Extensions.Testing.Abstractions/Messages/RunTestsMessage.cs b/src/Microsoft.Extensions.Testing.Abstractions/Messages/RunTestsMessage.cs new file mode 100644 index 000000000..403cb033c --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/Messages/RunTestsMessage.cs @@ -0,0 +1,12 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Collections.Generic; + +namespace Microsoft.Extensions.Testing.Abstractions +{ + public class RunTestsMessage + { + public List Tests { get; set; } + } +} diff --git a/src/Microsoft.Extensions.Testing.Abstractions/Properties/AssemblyInfo.cs b/src/Microsoft.Extensions.Testing.Abstractions/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..cdbb8074c --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/Properties/AssemblyInfo.cs @@ -0,0 +1,8 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Reflection; +using System.Resources; + +[assembly: AssemblyMetadata("Serviceable", "True")] +[assembly: NeutralResourcesLanguage("en-us")] \ No newline at end of file diff --git a/src/Microsoft.Extensions.Testing.Abstractions/SourceInformation.cs b/src/Microsoft.Extensions.Testing.Abstractions/SourceInformation.cs new file mode 100644 index 000000000..3245b291e --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/SourceInformation.cs @@ -0,0 +1,18 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Microsoft.Extensions.Testing.Abstractions +{ + public class SourceInformation + { + public SourceInformation(string filename, int lineNumber) + { + Filename = filename; + LineNumber = lineNumber; + } + + public string Filename { get; } + + public int LineNumber { get; } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.Testing.Abstractions/SourceInformationProvider.cs b/src/Microsoft.Extensions.Testing.Abstractions/SourceInformationProvider.cs new file mode 100644 index 000000000..a2a5e31a7 --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/SourceInformationProvider.cs @@ -0,0 +1,315 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Runtime.CompilerServices; +using dia2; +using Microsoft.Extensions.Logging; + +namespace Microsoft.Extensions.Testing.Abstractions +{ + public class SourceInformationProvider : ISourceInformationProvider + { + //private readonly IMetadataProjectReference _project; + private readonly string _pdbPath; + private readonly ILogger _logger; + + private bool? _isInitialized; + private IDiaDataSource _diaDataSource; + private IDiaSession _diaSession; + private AssemblyData _assemblyData; + + public SourceInformationProvider( + string pdbPath, + ILogger logger) + { + if (String.IsNullOrWhiteSpace(pdbPath) || + !File.Exists(pdbPath)) + { + throw new ArgumentException($"The file '{pdbPath}' does not exist.", nameof(pdbPath)); + } + _pdbPath = pdbPath; + _logger = logger; + } + + public SourceInformation GetSourceInformation(MethodInfo method) + { + if (method == null) + { + throw new ArgumentNullException(nameof(method)); + } + + if (!EnsureInitialized()) + { + // Unable to load DIA or we had a failure reading the symbols. + return null; + } + + Debug.Assert(_isInitialized == true); + Debug.Assert(_diaSession != null); + Debug.Assert(_assemblyData != null); + + // We need a MethodInfo so we can deal with cases where no user code shows up for provided + // method and class name. In particular: + // + // 1) inherited test methods (method.DeclaringType) + // 2) async test methods (see StateMachineAttribute). + // + // Note that this doesn't deal gracefully with overloaded methods. Symbol APIs don't provide + // a way to match overloads. We'd really need MetadataTokens to do this correctly (missing in + // CoreCLR). + method = ResolveBestMethodInfo(method); + + var className = method.DeclaringType.FullName; + var methodName = method.Name; + + // The DIA code doesn't include a + for nested classes, just a dot. + var symbolId = FindMethodSymbolId(className.Replace('+', '.'), methodName); + if (symbolId == null) + { + // No matching method in the symbol. + return null; + } + + try + { + return GetSourceInformation(symbolId.Value); + } + catch (Exception ex) + { + _logger.LogWarning("Failed to access source information in symbol.", ex); + return null; + } + } + + private MethodInfo ResolveBestMethodInfo(MethodInfo method) + { + Debug.Assert(_isInitialized == true); + + // If a method has a StateMachineAttribute, then all of the user code will show up + // in the symbols associated with the compiler-generated code. So, we need to look + // for the 'MoveNext' on the generated type and resolve symbols for that. + var attribute = method.GetCustomAttribute(); + if (attribute?.StateMachineType == null) + { + return method; + } + + return attribute.StateMachineType.GetMethod( + "MoveNext", + BindingFlags.Instance | BindingFlags.NonPublic); + } + + private uint? FindMethodSymbolId(string className, string methodName) + { + Debug.Assert(_isInitialized == true); + + ClassData classData; + if (_assemblyData.Classes.TryGetValue(className, out classData)) + { + MethodData methodData; + if (classData.Methods.TryGetValue(methodName, out methodData)) + { + return methodData.SymbolId; + } + } + + return null; + } + + private SourceInformation GetSourceInformation(uint symbolId) + { + Debug.Assert(_isInitialized == true); + + string filename = null; + int? lineNumber = null; + + IDiaSymbol diaSymbol; + _diaSession.symbolById(symbolId, out diaSymbol); + if (diaSymbol == null) + { + // Doesn't seem like this should happen, since DIA gave us the id. + return null; + } + + IDiaEnumLineNumbers diaLineNumbers; + _diaSession.findLinesByAddr( + diaSymbol.addressSection, + diaSymbol.addressOffset, + (uint)diaSymbol.length, + out diaLineNumbers); + + // Resist the user to use foreach here. It doesn't work well with these APIs. + IDiaLineNumber diaLineNumber; + var lineNumbersFetched = 0u; + + diaLineNumbers.Next(1u, out diaLineNumber, out lineNumbersFetched); + while (lineNumbersFetched == 1 && diaLineNumber != null) + { + if (filename == null) + { + var diaFile = diaLineNumber.sourceFile; + if (diaFile != null) + { + filename = diaFile.fileName; + } + } + + if (diaLineNumber.lineNumber != 16707566u) + { + // We'll see multiple line numbers for the same method, but we just want the first one. + lineNumber = Math.Min(lineNumber ?? Int32.MaxValue, (int)diaLineNumber.lineNumber); + } + + diaLineNumbers.Next(1u, out diaLineNumber, out lineNumbersFetched); + } + + if (filename == null || lineNumber == null) + { + return null; + } + else + { + return new SourceInformation(filename, lineNumber.Value); + } + } + + private bool EnsureInitialized() + { + if (_isInitialized.HasValue) + { + return _isInitialized.Value; + } + + try + { + _diaDataSource = (IDiaDataSource)new DiaDataSource(); + _isInitialized = true; + } + catch (Exception ex) + { + _logger.LogWarning("Failed to create DIA DataSource. No source information will be available.", ex); + _isInitialized = false; + return _isInitialized.Value; + } + + // We have a project, and we successfully loaded DIA, so let's capture the symbols + // and create a session. + try + { + _diaDataSource.loadDataFromPdb(_pdbPath); + _diaDataSource.openSession(out _diaSession); + } + catch (Exception ex) + { + _logger.LogWarning("Failed to load symbols. No source information will be available.", ex); + _isInitialized = false; + return _isInitialized.Value; + } + + try + { + _assemblyData = FetchSymbolData(_diaSession); + } + catch (Exception ex) + { + _logger.LogWarning("Failed to read symbols. No source information will be available.", ex); + _isInitialized = false; + return _isInitialized.Value; + } + + _isInitialized = true; + return _isInitialized.Value; + } + + // Builds a lookup table of class+method name. + // + // It's easier to build it at once by enumerating, once we have the table, we + // can use the symbolIds to look up the sources when we need them. + private static AssemblyData FetchSymbolData(IDiaSession session) + { + // This will be a *flat* enumerator of all classes. + // + // A nested class will not contain a '+' in it's name, just a '.' separating the parent class name from + // the child class name. + IDiaEnumSymbols diaClasses; + + session.findChildren( + session.globalScope, // Search at the top-level. + SymTagEnum.SymTagCompiland, // Just find classes. + name: null, // Don't filter by name. + compareFlags: 0u, // doesn't matter because name is null. + ppResult: out diaClasses); + + var assemblyData = new AssemblyData(); + + // Resist the urge to use foreach here. It doesn't work well with these APIs. + var classesFetched = 0u; + IDiaSymbol diaClass; + + diaClasses.Next(1u, out diaClass, out classesFetched); + while (classesFetched == 1 && diaClass != null) + { + var classData = new ClassData() + { + Name = diaClass.name, + SymbolId = diaClass.symIndexId, + }; + assemblyData.Classes.Add(diaClass.name, classData); + + IDiaEnumSymbols diaMethods; + session.findChildren( + diaClass, + SymTagEnum.SymTagFunction, + name: null, // Don't filter by name. + compareFlags: 0u, // doesn't matter because name is null. + ppResult: out diaMethods); + + // Resist the urge to use foreach here. It doesn't work well with these APIs. + var methodsFetched = 0u; + IDiaSymbol diaMethod; + + diaMethods.Next(1u, out diaMethod, out methodsFetched); + while (methodsFetched == 1 && diaMethod != null) + { + classData.Methods[diaMethod.name] = new MethodData() + { + Name = diaMethod.name, + SymbolId = diaMethod.symIndexId, + }; + + diaMethods.Next(1u, out diaMethod, out methodsFetched); + } + + diaClasses.Next(1u, out diaClass, out classesFetched); + } + + return assemblyData; + } + + private class AssemblyData + { + public IDictionary Classes { get; } = new Dictionary(); + } + + private class ClassData + { + public string Name { get; set; } + + public uint SymbolId { get; set; } + + public IDictionary Methods { get; } = new Dictionary(); + } + + private class MethodData + { + public string Name { get; set; } + + public uint SymbolId { get; set; } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.Testing.Abstractions/Test.cs b/src/Microsoft.Extensions.Testing.Abstractions/Test.cs new file mode 100644 index 000000000..06622eda5 --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/Test.cs @@ -0,0 +1,28 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; + +namespace Microsoft.Extensions.Testing.Abstractions +{ + public class Test + { + public Test() + { + Properties = new Dictionary(StringComparer.Ordinal); + } + + public string CodeFilePath { get; set; } + + public string DisplayName { get; set; } + + public string FullyQualifiedName { get; set; } + + public Guid? Id { get; set; } + + public int? LineNumber { get; set; } + + public IDictionary Properties { get; private set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.Testing.Abstractions/TestHostServices.cs b/src/Microsoft.Extensions.Testing.Abstractions/TestHostServices.cs new file mode 100644 index 000000000..73c6d134a --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/TestHostServices.cs @@ -0,0 +1,18 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Microsoft.Extensions.Logging; + +namespace Microsoft.Extensions.Testing.Abstractions +{ + public abstract class TestHostServices + { + public abstract ITestDiscoverySink TestDiscoverySink { get; } + + public abstract ITestExecutionSink TestExecutionSink { get; } + + public abstract ISourceInformationProvider SourceInformationProvider { get; } + + public abstract ILoggerFactory LoggerFactory { get; } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.Testing.Abstractions/TestOutcome.cs b/src/Microsoft.Extensions.Testing.Abstractions/TestOutcome.cs new file mode 100644 index 000000000..a3124a1d6 --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/TestOutcome.cs @@ -0,0 +1,14 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Microsoft.Extensions.Testing.Abstractions +{ + public enum TestOutcome + { + None, + Passed, + Failed, + Skipped, + NotFound + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.Testing.Abstractions/TestResult.cs b/src/Microsoft.Extensions.Testing.Abstractions/TestResult.cs new file mode 100644 index 000000000..c91cdeeb0 --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/TestResult.cs @@ -0,0 +1,42 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.ObjectModel; + +namespace Microsoft.Extensions.Testing.Abstractions +{ + public sealed class TestResult + { + public TestResult(Test test) + { + if (test == null) + { + throw new ArgumentNullException(nameof(test)); + } + + Test = test; + Messages = new Collection(); + } + + public Test Test { get; private set; } + + public TestOutcome Outcome { get; set; } + + public string ErrorMessage { get; set; } + + public string ErrorStackTrace { get; set; } + + public string DisplayName { get; set; } + + public Collection Messages { get; private set; } + + public string ComputerName { get; set; } + + public TimeSpan Duration { get; set; } + + public DateTimeOffset StartTime { get; set; } + + public DateTimeOffset EndTime { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.Testing.Abstractions/project.json b/src/Microsoft.Extensions.Testing.Abstractions/project.json new file mode 100644 index 000000000..232e683e7 --- /dev/null +++ b/src/Microsoft.Extensions.Testing.Abstractions/project.json @@ -0,0 +1,38 @@ +{ + "description": "Abstractions for test runners to communicate to a tool, such as Visual Studio.", + "version": "1.0.0-*", + "repository": { + "type": "git", + "url": "git://github.com/dotnet/cli" + }, + "compilationOptions": { + "warningsAsErrors": true + }, + "dependencies": { + "Newtonsoft.Json": "7.0.1", + "Microsoft.DotNet.ProjectModel": { + "version": "1.0.0", + "type": "build" + }, + "Microsoft.Extensions.Compilation.Abstractions": "1.0.0-*", + "Microsoft.Extensions.Logging.Abstractions": "1.0.0-*", + "System.Runtime.Serialization.Primitives": "4.0.11-beta-*" + }, + "frameworks": { + "dnxcore50": { + "dependencies": { + "System.Collections": "4.0.11-rc2-*", + "System.Reflection": "4.1.0-beta-*", + "System.Resources.ResourceManager": "4.0.1-beta-*", + "System.Runtime": "4.0.21-rc2-*", + "System.Runtime.Extensions": "4.0.11-rc2-*" + } + } + }, + "scripts": { + "postcompile": [ + "../../scripts/build/place-binary \"%compile:OutputDir%/%project:Name%.dll\"", + "../../scripts/build/place-binary \"%compile:OutputDir%/%project:Name%.pdb\"" + ] + } +} \ No newline at end of file