Merge pull request #344 from piotrpMSFT/piotrpMSFT/issue342/dotnet-test
dotnet-test command fixes issue #344 and #359 @brthor, note issue #359. Powershell was interpreting particular Env Var names as patterns due to use of -Path. Changing this to -LiteralPath was required since use of patterns was unintended.
This commit is contained in:
commit
d63bd8e50d
71 changed files with 3690 additions and 45 deletions
|
@ -51,6 +51,10 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.ProjectMod
|
|||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Runtime", "src\Microsoft.DotNet.Runtime\Microsoft.DotNet.Runtime.xproj", "{DB29F219-DC92-4AF7-A2EE-E89FFBB3F5F0}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.Testing.Abstractions", "src\Microsoft.Extensions.Testing.Abstractions\Microsoft.Extensions.Testing.Abstractions.xproj", "{DCDFE282-03DE-4DBC-B90C-CC3CE3EC8162}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Tools.Test", "src\Microsoft.DotNet.Tools.Test\Microsoft.DotNet.Tools.Test.xproj", "{F003F228-2AE2-4E9D-877B-93EB773B5061}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -355,6 +359,38 @@ Global
|
|||
{DB29F219-DC92-4AF7-A2EE-E89FFBB3F5F0}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
|
||||
{DB29F219-DC92-4AF7-A2EE-E89FFBB3F5F0}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
|
||||
{DB29F219-DC92-4AF7-A2EE-E89FFBB3F5F0}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
|
||||
{DCDFE282-03DE-4DBC-B90C-CC3CE3EC8162}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DCDFE282-03DE-4DBC-B90C-CC3CE3EC8162}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DCDFE282-03DE-4DBC-B90C-CC3CE3EC8162}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{DCDFE282-03DE-4DBC-B90C-CC3CE3EC8162}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{DCDFE282-03DE-4DBC-B90C-CC3CE3EC8162}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DCDFE282-03DE-4DBC-B90C-CC3CE3EC8162}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DCDFE282-03DE-4DBC-B90C-CC3CE3EC8162}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{DCDFE282-03DE-4DBC-B90C-CC3CE3EC8162}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{DCDFE282-03DE-4DBC-B90C-CC3CE3EC8162}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DCDFE282-03DE-4DBC-B90C-CC3CE3EC8162}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DCDFE282-03DE-4DBC-B90C-CC3CE3EC8162}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{DCDFE282-03DE-4DBC-B90C-CC3CE3EC8162}.Release|x64.Build.0 = Release|Any CPU
|
||||
{DCDFE282-03DE-4DBC-B90C-CC3CE3EC8162}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DCDFE282-03DE-4DBC-B90C-CC3CE3EC8162}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
|
||||
{DCDFE282-03DE-4DBC-B90C-CC3CE3EC8162}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
|
||||
{DCDFE282-03DE-4DBC-B90C-CC3CE3EC8162}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
|
||||
{F003F228-2AE2-4E9D-877B-93EB773B5061}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F003F228-2AE2-4E9D-877B-93EB773B5061}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F003F228-2AE2-4E9D-877B-93EB773B5061}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{F003F228-2AE2-4E9D-877B-93EB773B5061}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{F003F228-2AE2-4E9D-877B-93EB773B5061}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F003F228-2AE2-4E9D-877B-93EB773B5061}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F003F228-2AE2-4E9D-877B-93EB773B5061}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{F003F228-2AE2-4E9D-877B-93EB773B5061}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{F003F228-2AE2-4E9D-877B-93EB773B5061}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F003F228-2AE2-4E9D-877B-93EB773B5061}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F003F228-2AE2-4E9D-877B-93EB773B5061}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{F003F228-2AE2-4E9D-877B-93EB773B5061}.Release|x64.Build.0 = Release|Any CPU
|
||||
{F003F228-2AE2-4E9D-877B-93EB773B5061}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F003F228-2AE2-4E9D-877B-93EB773B5061}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
|
||||
{F003F228-2AE2-4E9D-877B-93EB773B5061}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
|
||||
{F003F228-2AE2-4E9D-877B-93EB773B5061}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -380,5 +416,7 @@ Global
|
|||
{0F480791-4BA0-44E3-8CC4-C71656664175} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
|
||||
{BD7833F8-3209-4682-BF75-B4BCA883E279} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
|
||||
{DB29F219-DC92-4AF7-A2EE-E89FFBB3F5F0} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
|
||||
{DCDFE282-03DE-4DBC-B90C-CC3CE3EC8162} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
|
||||
{F003F228-2AE2-4E9D-877B-93EB773B5061} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -40,12 +40,13 @@ compilers, package managers and other utilities that developers need.",
|
|||
"bin/dotnet" : "usr/bin/dotnet",
|
||||
"bin/dotnet-compile" : "usr/bin/dotnet-compile",
|
||||
"bin/dotnet-compile-csc" : "usr/bin/dotnet-compile-csc",
|
||||
"bin/dotnet-compile-native" : "/usr/bin/dotnet-compile-native",
|
||||
"bin/dotnet-init":"usr/bin/dotnet-init",
|
||||
"bin/dotnet-publish" : "usr/bin/dotnet-publish",
|
||||
"bin/dotnet-repl" : "usr/bin/dotnet-repl",
|
||||
"bin/dotnet-repl-csi" : "usr/bin/dotnet-repl-csi",
|
||||
"bin/dotnet-restore" : "usr/bin/dotnet-restore",
|
||||
"bin/dotnet-compile-native" : "/usr/bin/dotnet-compile-native",
|
||||
"bin/resgen" : "usr/bin/resgen",
|
||||
"bin/dotnet-init":"usr/bin/dotnet-init"
|
||||
"bin/dotnet-test" : "usr/bin/dotnet-test",
|
||||
"bin/resgen" : "usr/bin/resgen"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,14 +15,15 @@ $Projects = @(
|
|||
"Microsoft.DotNet.Cli",
|
||||
"Microsoft.DotNet.Tools.Compiler",
|
||||
"Microsoft.DotNet.Tools.Compiler.Csc",
|
||||
"Microsoft.DotNet.Tools.Compiler.Native",
|
||||
"Microsoft.DotNet.Tools.Init",
|
||||
"Microsoft.DotNet.Tools.Pack",
|
||||
"Microsoft.DotNet.Tools.Publish",
|
||||
"Microsoft.DotNet.Tools.Repl",
|
||||
"Microsoft.DotNet.Tools.Repl.Csi",
|
||||
"Microsoft.DotNet.Tools.Resgen",
|
||||
"Microsoft.DotNet.Tools.Run",
|
||||
"Microsoft.DotNet.Tools.Init",
|
||||
"Microsoft.DotNet.Tools.Compiler.Native"
|
||||
"Microsoft.DotNet.Tools.Test"
|
||||
)
|
||||
|
||||
$BinariesForCoreHost = @(
|
||||
|
|
|
@ -27,14 +27,15 @@ PROJECTS=( \
|
|||
Microsoft.DotNet.Cli \
|
||||
Microsoft.DotNet.Tools.Compiler \
|
||||
Microsoft.DotNet.Tools.Compiler.Csc \
|
||||
Microsoft.DotNet.Tools.Publish \
|
||||
Microsoft.DotNet.Tools.Compiler.Native \
|
||||
Microsoft.DotNet.Tools.Init \
|
||||
Microsoft.DotNet.Tools.Pack \
|
||||
Microsoft.DotNet.Tools.Publish \
|
||||
Microsoft.DotNet.Tools.Repl \
|
||||
Microsoft.DotNet.Tools.Repl.Csi \
|
||||
Microsoft.DotNet.Tools.Resgen \
|
||||
Microsoft.DotNet.Tools.Run \
|
||||
Microsoft.DotNet.Tools.Init \
|
||||
Microsoft.DotNet.Tools.Compiler.Native \
|
||||
Microsoft.DotNet.Tools.Test \
|
||||
)
|
||||
|
||||
BINARIES_FOR_COREHOST=( \
|
||||
|
|
|
@ -25,7 +25,7 @@ pushd "$env:VS140COMNTOOLS\..\..\VC"
|
|||
cmd /c "vcvarsall.bat x64&set" |
|
||||
foreach {
|
||||
if ($_ -match "=") {
|
||||
$v = $_.split("="); set-item -force -path "ENV:\$($v[0])" -value "$($v[1])"
|
||||
$v = $_.split("="); set-item -force -literalpath "ENV:\$($v[0])" -value "$($v[1])"
|
||||
}
|
||||
}
|
||||
popd
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// 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;
|
||||
|
|
|
@ -201,6 +201,9 @@ namespace Microsoft.DotNet.Cli.Utils
|
|||
Reporter.Verbose.WriteLine($"> {FormatProcessInfo(_process.StartInfo)}".White());
|
||||
#endif
|
||||
_process.Start();
|
||||
|
||||
Reporter.Verbose.WriteLine($"Process ID: {_process.Id}");
|
||||
|
||||
_process.BeginOutputReadLine();
|
||||
_process.BeginErrorReadLine();
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// 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.Cli.Utils.CommandParsing
|
||||
{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// 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;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// 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.Cli.Utils.CommandParsing
|
||||
{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// 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;
|
||||
using System.Linq;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// 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.Cli.Utils.CommandParsing
|
||||
{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// 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;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// 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.Cli.Utils.CommandParsing
|
||||
{
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
using System.Linq;
|
||||
|
||||
namespace System.Collections.Generic
|
||||
{
|
||||
internal static class DictionaryExtensions
|
||||
{
|
||||
public static IEnumerable<V> GetOrEmpty<K, V>(this IDictionary<K, IEnumerable<V>> self, K key)
|
||||
{
|
||||
IEnumerable<V> val;
|
||||
if (!self.TryGetValue(key, out val))
|
||||
{
|
||||
return Enumerable.Empty<V>();
|
||||
}
|
||||
return val;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -76,6 +76,8 @@ namespace Microsoft.DotNet.ProjectModel
|
|||
|
||||
public string CompilerName { get; set; }
|
||||
|
||||
public string TestRunner { get; set; }
|
||||
|
||||
public ProjectFilesCollection Files { get; set; }
|
||||
|
||||
public IDictionary<string, string> Commands { get; } = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
|
|
@ -99,5 +99,28 @@ namespace Microsoft.DotNet.ProjectModel
|
|||
.Build();
|
||||
}
|
||||
}
|
||||
public string GetAssemblyPath(string buildConfiguration)
|
||||
{
|
||||
return Path.Combine(
|
||||
GetOutputDirectoryPath(buildConfiguration),
|
||||
ProjectFile.Name + FileNameSuffixes.DotNet.DynamicLib);
|
||||
}
|
||||
|
||||
public string GetPdbPath(string buildConfiguration)
|
||||
{
|
||||
return Path.Combine(
|
||||
GetOutputDirectoryPath(buildConfiguration),
|
||||
ProjectFile.Name + FileNameSuffixes.DotNet.ProgramDatabase);
|
||||
}
|
||||
|
||||
private string GetOutputDirectoryPath(string buildConfiguration)
|
||||
{
|
||||
return Path.Combine(
|
||||
ProjectDirectory,
|
||||
DirectoryNames.Bin,
|
||||
buildConfiguration,
|
||||
TargetFramework.GetShortFolderName(),
|
||||
ProjectModel.RuntimeIdentifier.Current);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -140,6 +140,7 @@ namespace Microsoft.DotNet.ProjectModel
|
|||
project.LicenseUrl = rawProject.ValueAsString("licenseUrl");
|
||||
project.IconUrl = rawProject.ValueAsString("iconUrl");
|
||||
project.CompilerName = rawProject.ValueAsString("compilerName");
|
||||
project.TestRunner = rawProject.ValueAsString("testRunner");
|
||||
|
||||
project.Authors = rawProject.ValueAsStringArray("authors") ?? Array.Empty<string>();
|
||||
project.Owners = rawProject.ValueAsStringArray("owners") ?? Array.Empty<string>();
|
||||
|
|
|
@ -1,10 +1,22 @@
|
|||
// 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 System.Collections.Generic
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel.Utilities
|
||||
{
|
||||
internal static class DictionaryExtensions
|
||||
public static class DictionaryExtensions
|
||||
{
|
||||
public static IEnumerable<V> GetOrEmpty<K, V>(this IDictionary<K, IEnumerable<V>> self, K key)
|
||||
{
|
||||
IEnumerable<V> val;
|
||||
return !self.TryGetValue(key, out val)
|
||||
? Enumerable.Empty<V>()
|
||||
: val;
|
||||
}
|
||||
|
||||
public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TKey, TValue> factory)
|
||||
{
|
||||
lock (dictionary)
|
||||
|
|
|
@ -14,6 +14,7 @@ using Microsoft.DotNet.Tools.Common;
|
|||
using Microsoft.DotNet.ProjectModel;
|
||||
using Microsoft.DotNet.ProjectModel.Compilation;
|
||||
using NuGet.Frameworks;
|
||||
using Microsoft.DotNet.ProjectModel.Utilities;
|
||||
|
||||
namespace Microsoft.DotNet.Tools.Compiler
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>f003f228-2ae2-4e9d-877b-93eb773b5061</ProjectGuid>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
305
src/Microsoft.DotNet.Tools.Test/Program.cs
Normal file
305
src/Microsoft.DotNet.Tools.Test/Program.cs
Normal file
|
@ -0,0 +1,305 @@
|
|||
// 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.Linq;
|
||||
using Microsoft.DotNet.Cli.Utils;
|
||||
using Microsoft.Dnx.Runtime.Common.CommandLine;
|
||||
using Microsoft.DotNet.ProjectModel;
|
||||
using Microsoft.Extensions.Testing.Abstractions;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NuGet.Frameworks;
|
||||
|
||||
namespace Microsoft.DotNet.Tools.Test
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
DebugHelper.HandleDebugSwitch(ref args);
|
||||
|
||||
var app = new CommandLineApplication(false)
|
||||
{
|
||||
Name = "dotnet test",
|
||||
FullName = ".NET Test Driver",
|
||||
Description = "Test Driver for the .NET Platform"
|
||||
};
|
||||
|
||||
app.HelpOption("-?|-h|--help");
|
||||
|
||||
var parentProcessIdOption = app.Option("--parentProcessId", "Used by IDEs to specify their process ID. Test will exit if the parent process does.", CommandOptionType.SingleValue);
|
||||
var portOption = app.Option("--port", "Used by IDEs to specify a port number to listen for a connection.", CommandOptionType.SingleValue);
|
||||
var projectPath = app.Argument("<PROJECT>", "The project to test, defaults to the current directory. Can be a path to a project.json or a project directory.");
|
||||
|
||||
app.OnExecute(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
// Register for parent process's exit event
|
||||
if (parentProcessIdOption.HasValue())
|
||||
{
|
||||
int processId;
|
||||
|
||||
if (!Int32.TryParse(parentProcessIdOption.Value(), out processId))
|
||||
{
|
||||
throw new InvalidOperationException($"Invalid process id '{parentProcessIdOption.Value()}'. Process id must be an integer.");
|
||||
}
|
||||
|
||||
RegisterForParentProcessExit(processId);
|
||||
}
|
||||
|
||||
var projectContexts = CreateProjectContexts(projectPath.Value);
|
||||
|
||||
var projectContext = projectContexts.First();
|
||||
|
||||
var testRunner = projectContext.ProjectFile.TestRunner;
|
||||
|
||||
if (portOption.HasValue())
|
||||
{
|
||||
int port;
|
||||
|
||||
if (!Int32.TryParse(portOption.Value(), out port))
|
||||
{
|
||||
throw new InvalidOperationException($"{portOption.Value()} is not a valid port number.");
|
||||
}
|
||||
|
||||
return RunDesignTime(port, projectContext, testRunner);
|
||||
}
|
||||
else
|
||||
{
|
||||
return RunConsole(projectContext, app, testRunner);
|
||||
}
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
TestHostTracing.Source.TraceEvent(TraceEventType.Error, 0, ex.ToString());
|
||||
return -1;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
TestHostTracing.Source.TraceEvent(TraceEventType.Error, 0, ex.ToString());
|
||||
return -2;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return app.Execute(args);
|
||||
}
|
||||
|
||||
private static int RunConsole(ProjectContext projectContext, CommandLineApplication app, string testRunner)
|
||||
{
|
||||
var commandArgs = new List<string> {projectContext.GetAssemblyPath(Constants.DefaultConfiguration)};
|
||||
commandArgs.AddRange(app.RemainingArguments);
|
||||
|
||||
return Command.Create($"{GetCommandName(testRunner)}", commandArgs, projectContext.TargetFramework)
|
||||
.ForwardStdErr()
|
||||
.ForwardStdOut()
|
||||
.Execute()
|
||||
.ExitCode;
|
||||
}
|
||||
|
||||
private static int RunDesignTime(int port, ProjectContext projectContext, string testRunner)
|
||||
{
|
||||
Console.WriteLine("Listening on port {0}", port);
|
||||
using (var channel = ReportingChannel.ListenOn(port))
|
||||
{
|
||||
Console.WriteLine("Client accepted {0}", channel.Socket.LocalEndPoint);
|
||||
|
||||
HandleDesignTimeMessages(projectContext, testRunner, channel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static void HandleDesignTimeMessages(ProjectContext projectContext, string testRunner, ReportingChannel channel)
|
||||
{
|
||||
try
|
||||
{
|
||||
var message = channel.ReadQueue.Take();
|
||||
|
||||
if (message.MessageType == "ProtocolVersion")
|
||||
{
|
||||
HandleProtocolVersionMessage(message, channel);
|
||||
|
||||
// Take the next message, which should be the command to execute.
|
||||
message = channel.ReadQueue.Take();
|
||||
}
|
||||
|
||||
if (message.MessageType == "TestDiscovery.Start")
|
||||
{
|
||||
HandleTestDiscoveryStartMessage(testRunner, channel, projectContext);
|
||||
}
|
||||
else if (message.MessageType == "TestExecution.Start")
|
||||
{
|
||||
HandleTestExecutionStartMessage(testRunner, message, channel, projectContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
HandleUnknownMessage(message, channel);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
channel.SendError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void HandleProtocolVersionMessage(Message message, ReportingChannel channel)
|
||||
{
|
||||
var version = message.Payload?.ToObject<ProtocolVersionMessage>().Version;
|
||||
var supportedVersion = 1;
|
||||
TestHostTracing.Source.TraceInformation(
|
||||
"[ReportingChannel]: Requested Version: {0} - Using Version: {1}",
|
||||
version,
|
||||
supportedVersion);
|
||||
|
||||
channel.Send(new Message()
|
||||
{
|
||||
MessageType = "ProtocolVersion",
|
||||
Payload = JToken.FromObject(new ProtocolVersionMessage()
|
||||
{
|
||||
Version = supportedVersion,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
private static void HandleTestDiscoveryStartMessage(string testRunner, ReportingChannel channel, ProjectContext projectContext)
|
||||
{
|
||||
TestHostTracing.Source.TraceInformation("Starting Discovery");
|
||||
|
||||
var commandArgs = new List<string> { projectContext.GetAssemblyPath(Constants.DefaultConfiguration) };
|
||||
|
||||
commandArgs.AddRange(new[]
|
||||
{
|
||||
"--list",
|
||||
"--designtime"
|
||||
});
|
||||
|
||||
ExecuteRunnerCommand(testRunner, channel, commandArgs);
|
||||
|
||||
channel.Send(new Message()
|
||||
{
|
||||
MessageType = "TestDiscovery.Response",
|
||||
});
|
||||
|
||||
TestHostTracing.Source.TraceInformation("Completed Discovery");
|
||||
}
|
||||
|
||||
private static void HandleTestExecutionStartMessage(string testRunner, Message message, ReportingChannel channel, ProjectContext projectContext)
|
||||
{
|
||||
TestHostTracing.Source.TraceInformation("Starting Execution");
|
||||
|
||||
var commandArgs = new List<string> { projectContext.GetAssemblyPath(Constants.DefaultConfiguration) };
|
||||
|
||||
commandArgs.AddRange(new[]
|
||||
{
|
||||
"--designtime"
|
||||
});
|
||||
|
||||
var tests = message.Payload?.ToObject<RunTestsMessage>().Tests;
|
||||
if (tests != null)
|
||||
{
|
||||
foreach (var test in tests)
|
||||
{
|
||||
commandArgs.Add("--test");
|
||||
commandArgs.Add(test);
|
||||
}
|
||||
}
|
||||
|
||||
ExecuteRunnerCommand(testRunner, channel, commandArgs);
|
||||
|
||||
channel.Send(new Message()
|
||||
{
|
||||
MessageType = "TestExecution.Response",
|
||||
});
|
||||
|
||||
TestHostTracing.Source.TraceInformation("Completed Execution");
|
||||
}
|
||||
|
||||
private static void HandleUnknownMessage(Message message, ReportingChannel channel)
|
||||
{
|
||||
var error = string.Format("Unexpected message type: '{0}'.", message.MessageType);
|
||||
|
||||
TestHostTracing.Source.TraceEvent(TraceEventType.Error, 0, error);
|
||||
|
||||
channel.SendError(error);
|
||||
|
||||
throw new InvalidOperationException(error);
|
||||
}
|
||||
|
||||
private static void ExecuteRunnerCommand(string testRunner, ReportingChannel channel, List<string> commandArgs)
|
||||
{
|
||||
var result = Command.Create(GetCommandName(testRunner), commandArgs, new NuGetFramework("DNXCore", Version.Parse("5.0")))
|
||||
.OnOutputLine(line =>
|
||||
{
|
||||
try
|
||||
{
|
||||
channel.Send(JsonConvert.DeserializeObject<Message>(line));
|
||||
}
|
||||
catch
|
||||
{
|
||||
TestHostTracing.Source.TraceInformation(line);
|
||||
}
|
||||
})
|
||||
.Execute();
|
||||
|
||||
if (result.ExitCode != 0)
|
||||
{
|
||||
channel.SendError($"{GetCommandName(testRunner)} returned '{result.ExitCode}'.");
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetCommandName(string testRunner)
|
||||
{
|
||||
return $"dotnet-test-{testRunner}";
|
||||
}
|
||||
|
||||
private static void RegisterForParentProcessExit(int id)
|
||||
{
|
||||
var parentProcess = Process.GetProcesses().FirstOrDefault(p => p.Id == id);
|
||||
|
||||
if (parentProcess != null)
|
||||
{
|
||||
parentProcess.EnableRaisingEvents = true;
|
||||
parentProcess.Exited += (sender, eventArgs) =>
|
||||
{
|
||||
TestHostTracing.Source.TraceEvent(
|
||||
TraceEventType.Information,
|
||||
0,
|
||||
"Killing the current process as parent process has exited.");
|
||||
|
||||
Process.GetCurrentProcess().Kill();
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
TestHostTracing.Source.TraceEvent(
|
||||
TraceEventType.Information,
|
||||
0,
|
||||
"Failed to register for parent process's exit event. " +
|
||||
$"Parent process with id '{id}' was not found.");
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<ProjectContext> CreateProjectContexts(string projectPath)
|
||||
{
|
||||
projectPath = projectPath ?? Directory.GetCurrentDirectory();
|
||||
|
||||
if (!projectPath.EndsWith(Project.FileName))
|
||||
{
|
||||
projectPath = Path.Combine(projectPath, Project.FileName);
|
||||
}
|
||||
|
||||
if (!File.Exists(projectPath))
|
||||
{
|
||||
throw new InvalidOperationException($"{projectPath} does not exist.");
|
||||
}
|
||||
|
||||
return ProjectContext.CreateContextForEachFramework(projectPath);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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")]
|
150
src/Microsoft.DotNet.Tools.Test/ReportingChannel.cs
Normal file
150
src/Microsoft.DotNet.Tools.Test/ReportingChannel.cs
Normal file
|
@ -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<Message>(boundedCapacity: 1);
|
||||
|
||||
// Read incoming messages on the background thread
|
||||
new Thread(ReadMessages) { IsBackground = true }.Start();
|
||||
}
|
||||
|
||||
public BlockingCollection<Message> 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<Message>(_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();
|
||||
}
|
||||
}
|
||||
}
|
24
src/Microsoft.DotNet.Tools.Test/TestHostTracing.cs
Normal file
24
src/Microsoft.DotNet.Tools.Test/TestHostTracing.cs
Normal file
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
63
src/Microsoft.DotNet.Tools.Test/project.json
Normal file
63
src/Microsoft.DotNet.Tools.Test/project.json
Normal file
|
@ -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\""
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
// 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 DataKind
|
||||
{
|
||||
DataIsUnknown,
|
||||
DataIsLocal,
|
||||
DataIsStaticLocal,
|
||||
DataIsParam,
|
||||
DataIsObjectPtr,
|
||||
DataIsFileStatic,
|
||||
DataIsGlobal,
|
||||
DataIsMember,
|
||||
DataIsStaticMember,
|
||||
DataIsConstant
|
||||
}
|
||||
}
|
|
@ -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
|
||||
{
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
130
src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaSession.cs
Normal file
130
src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaSession.cs
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
1269
src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaSymbol.cs
Normal file
1269
src/Microsoft.Extensions.Testing.Abstractions/DIA/IDiaSymbol.cs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
34
src/Microsoft.Extensions.Testing.Abstractions/DIA/IStream.cs
Normal file
34
src/Microsoft.Extensions.Testing.Abstractions/DIA/IStream.cs
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
44
src/Microsoft.Extensions.Testing.Abstractions/DIA/Structs.cs
Normal file
44
src/Microsoft.Extensions.Testing.Abstractions/DIA/Structs.cs
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
|
||||
namespace Microsoft.Extensions.Testing.Abstractions
|
||||
{
|
||||
public interface ITestExecutionSink
|
||||
{
|
||||
void SendTestStarted(Test test);
|
||||
|
||||
void SendTestResult(TestResult testResult);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
// 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.IO;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.Extensions.Testing.Abstractions
|
||||
{
|
||||
class LineDelimitedJsonStream
|
||||
{
|
||||
private readonly StreamWriter _stream;
|
||||
|
||||
public LineDelimitedJsonStream(Stream stream)
|
||||
{
|
||||
_stream = new StreamWriter(stream);
|
||||
}
|
||||
|
||||
public void Send(object @object)
|
||||
{
|
||||
_stream.WriteLine(JsonConvert.SerializeObject(@object));
|
||||
|
||||
_stream.Flush();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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<string> Tests { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>dcdfe282-03de-4dbc-b90c-cc3ce3ec8162</ProjectGuid>
|
||||
<RootNamespace>Microsoft.Extensions.Testing.Abstractions</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
|
@ -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")]
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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<StateMachineAttribute>();
|
||||
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<string, ClassData> Classes { get; } = new Dictionary<string, ClassData>();
|
||||
}
|
||||
|
||||
private class ClassData
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public uint SymbolId { get; set; }
|
||||
|
||||
public IDictionary<string, MethodData> Methods { get; } = new Dictionary<string, MethodData>();
|
||||
}
|
||||
|
||||
private class MethodData
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public uint SymbolId { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.Extensions.Testing.Abstractions
|
||||
{
|
||||
public class StreamingTestDiscoverySink : ITestDiscoverySink
|
||||
{
|
||||
private readonly LineDelimitedJsonStream _stream;
|
||||
|
||||
public StreamingTestDiscoverySink(Stream stream)
|
||||
{
|
||||
_stream = new LineDelimitedJsonStream(stream);
|
||||
}
|
||||
|
||||
public void SendTestFound(Test test)
|
||||
{
|
||||
if (test == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(test));
|
||||
}
|
||||
|
||||
_stream.Send(new Message
|
||||
{
|
||||
MessageType = "TestDiscovery.TestFound",
|
||||
Payload = JToken.FromObject(test),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.Extensions.Testing.Abstractions
|
||||
{
|
||||
public class StreamingTestExecutionSink : ITestExecutionSink
|
||||
{
|
||||
private readonly LineDelimitedJsonStream _stream;
|
||||
private readonly ConcurrentDictionary<string, TestState> _runningTests;
|
||||
|
||||
|
||||
public StreamingTestExecutionSink(Stream stream)
|
||||
{
|
||||
_stream = new LineDelimitedJsonStream(stream);
|
||||
_runningTests = new ConcurrentDictionary<string, TestState>();
|
||||
}
|
||||
|
||||
public void SendTestStarted(Test test)
|
||||
{
|
||||
if (test == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(test));
|
||||
}
|
||||
|
||||
if (test.FullyQualifiedName != null)
|
||||
{
|
||||
var state = new TestState() { StartTime = DateTimeOffset.Now, };
|
||||
_runningTests.TryAdd(test.FullyQualifiedName, state);
|
||||
}
|
||||
|
||||
_stream.Send(new Message
|
||||
{
|
||||
MessageType = "TestExecution.TestStarted",
|
||||
Payload = JToken.FromObject(test),
|
||||
});
|
||||
}
|
||||
|
||||
public void SendTestResult(TestResult testResult)
|
||||
{
|
||||
if (testResult == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(testResult));
|
||||
}
|
||||
|
||||
if (testResult.StartTime == default(DateTimeOffset) && testResult.Test.FullyQualifiedName != null)
|
||||
{
|
||||
TestState state;
|
||||
_runningTests.TryRemove(testResult.Test.FullyQualifiedName, out state);
|
||||
|
||||
testResult.StartTime = state.StartTime;
|
||||
}
|
||||
|
||||
if (testResult.EndTime == default(DateTimeOffset))
|
||||
{
|
||||
testResult.EndTime = DateTimeOffset.Now;
|
||||
}
|
||||
|
||||
_stream.Send(new Message
|
||||
{
|
||||
MessageType = "TestExecution.TestResult",
|
||||
Payload = JToken.FromObject(testResult),
|
||||
});
|
||||
}
|
||||
|
||||
private class TestState
|
||||
{
|
||||
public DateTimeOffset StartTime { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
28
src/Microsoft.Extensions.Testing.Abstractions/Test.cs
Normal file
28
src/Microsoft.Extensions.Testing.Abstractions/Test.cs
Normal file
|
@ -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<string, object>(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<string, object> Properties { get; private set; }
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
14
src/Microsoft.Extensions.Testing.Abstractions/TestOutcome.cs
Normal file
14
src/Microsoft.Extensions.Testing.Abstractions/TestOutcome.cs
Normal file
|
@ -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
|
||||
}
|
||||
}
|
42
src/Microsoft.Extensions.Testing.Abstractions/TestResult.cs
Normal file
42
src/Microsoft.Extensions.Testing.Abstractions/TestResult.cs
Normal file
|
@ -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<string>();
|
||||
}
|
||||
|
||||
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<string> Messages { get; private set; }
|
||||
|
||||
public string ComputerName { get; set; }
|
||||
|
||||
public TimeSpan Duration { get; set; }
|
||||
|
||||
public DateTimeOffset StartTime { get; set; }
|
||||
|
||||
public DateTimeOffset EndTime { get; set; }
|
||||
}
|
||||
}
|
38
src/Microsoft.Extensions.Testing.Abstractions/project.json
Normal file
38
src/Microsoft.Extensions.Testing.Abstractions/project.json
Normal file
|
@ -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\""
|
||||
]
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue