mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-26 21:42:11 +00:00
Added test adapter for Cosmos test kernels.
This commit is contained in:
parent
4d88868362
commit
c75ec2e126
8 changed files with 397 additions and 0 deletions
|
|
@ -1,5 +1,9 @@
|
||||||
<Project>
|
<Project>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<LangVersion>Latest</LangVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<RepoRoot>$(MSBuildThisFileDirectory)</RepoRoot>
|
<RepoRoot>$(MSBuildThisFileDirectory)</RepoRoot>
|
||||||
<IL2CPURepoRoot>$(RepoRoot)..\IL2CPU\</IL2CPURepoRoot>
|
<IL2CPURepoRoot>$(RepoRoot)..\IL2CPU\</IL2CPURepoRoot>
|
||||||
|
|
|
||||||
11
Test.sln
11
Test.sln
|
|
@ -160,6 +160,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cosmos.Debug.HyperVServer",
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cosmos.TestRunner.Full", "Tests\Cosmos.TestRunner.Full\Cosmos.TestRunner.Full.csproj", "{65EE0B97-D3F0-400D-B432-85FF5553C44E}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cosmos.TestRunner.Full", "Tests\Cosmos.TestRunner.Full\Cosmos.TestRunner.Full.csproj", "{65EE0B97-D3F0-400D-B432-85FF5553C44E}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cosmos.TestRunner.TestAdapter", "Tests\Cosmos.TestRunner.TestAdapter\Cosmos.TestRunner.TestAdapter.csproj", "{8574E797-7C48-4F12-B537-4F927BCBA93B}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -609,6 +611,14 @@ Global
|
||||||
{65EE0B97-D3F0-400D-B432-85FF5553C44E}.Release|Any CPU.Build.0 = Release|Any CPU
|
{65EE0B97-D3F0-400D-B432-85FF5553C44E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{65EE0B97-D3F0-400D-B432-85FF5553C44E}.Release|x86.ActiveCfg = Release|Any CPU
|
{65EE0B97-D3F0-400D-B432-85FF5553C44E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{65EE0B97-D3F0-400D-B432-85FF5553C44E}.Release|x86.Build.0 = Release|Any CPU
|
{65EE0B97-D3F0-400D-B432-85FF5553C44E}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{8574E797-7C48-4F12-B537-4F927BCBA93B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{8574E797-7C48-4F12-B537-4F927BCBA93B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{8574E797-7C48-4F12-B537-4F927BCBA93B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{8574E797-7C48-4F12-B537-4F927BCBA93B}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{8574E797-7C48-4F12-B537-4F927BCBA93B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{8574E797-7C48-4F12-B537-4F927BCBA93B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{8574E797-7C48-4F12-B537-4F927BCBA93B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{8574E797-7C48-4F12-B537-4F927BCBA93B}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
@ -685,6 +695,7 @@ Global
|
||||||
{CCFD198D-4859-462B-9EF7-B305A8B4E6FC} = {0E67EFE8-5944-4F6C-8B47-C5E06D4C79F5}
|
{CCFD198D-4859-462B-9EF7-B305A8B4E6FC} = {0E67EFE8-5944-4F6C-8B47-C5E06D4C79F5}
|
||||||
{3421E19D-16C7-4593-9F6B-291ECB86A3EB} = {F7C6CA93-1D02-443C-9C8B-A1988DE0306B}
|
{3421E19D-16C7-4593-9F6B-291ECB86A3EB} = {F7C6CA93-1D02-443C-9C8B-A1988DE0306B}
|
||||||
{65EE0B97-D3F0-400D-B432-85FF5553C44E} = {0E67EFE8-5944-4F6C-8B47-C5E06D4C79F5}
|
{65EE0B97-D3F0-400D-B432-85FF5553C44E} = {0E67EFE8-5944-4F6C-8B47-C5E06D4C79F5}
|
||||||
|
{8574E797-7C48-4F12-B537-4F927BCBA93B} = {0E67EFE8-5944-4F6C-8B47-C5E06D4C79F5}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {4418C803-277E-448F-A0A0-52788FA215AD}
|
SolutionGuid = {4418C803-277E-448F-A0A0-52788FA215AD}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
|
<PackageDescription>Test adapter for Cosmos kernels.</PackageDescription>
|
||||||
|
<DevelopmentDependency>True</DevelopmentDependency>
|
||||||
|
<NoWarn>NU5111</NoWarn>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.TestPlatform.ObjectModel" Version="15.7.0" PrivateAssets="All" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Cosmos.TestRunner.Core\Cosmos.TestRunner.Core.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<IncludeBuildOutput>False</IncludeBuildOutput>
|
||||||
|
<!-- NuGet 4.8+ -->
|
||||||
|
<SuppressDependenciesWhenPacking>True</SuppressDependenciesWhenPacking>
|
||||||
|
<TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage);PackTestAdapter</TargetsForTfmSpecificContentInPackage>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Target Name="PackTestAdapter" DependsOnTargets="Publish">
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<_GeneratedFiles Include="$(PublishDepsFilePath)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<TfmSpecificPackageFile Include="@(_GeneratedFiles)">
|
||||||
|
<PackagePath>tools\%(_GeneratedFiles.RecursiveDir)%(_GeneratedFiles.Filename)%(_GeneratedFiles.Extension)</PackagePath>
|
||||||
|
</TfmSpecificPackageFile>
|
||||||
|
<TfmSpecificPackageFile Include="@(ResolvedFileToPublish->'$([MSBuild]::NormalizeDirectory($(PublishDir)))%(RelativePath)')">
|
||||||
|
<PackagePath>tools\%(ResolvedFileToPublish.RelativePath)</PackagePath>
|
||||||
|
</TfmSpecificPackageFile>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
</Project>
|
||||||
123
Tests/Cosmos.TestRunner.TestAdapter/CosmosTestDiscoverer.cs
Normal file
123
Tests/Cosmos.TestRunner.TestAdapter/CosmosTestDiscoverer.cs
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Reflection.Metadata;
|
||||||
|
using System.Reflection.PortableExecutable;
|
||||||
|
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
|
||||||
|
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter;
|
||||||
|
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;
|
||||||
|
|
||||||
|
namespace Cosmos.TestRunner.TestAdapter
|
||||||
|
{
|
||||||
|
[FileExtension(".dll")]
|
||||||
|
[DefaultExecutorUri(CosmosTestExecutor.ExecutorUri)]
|
||||||
|
public sealed class CosmosTestDiscoverer : ITestDiscoverer
|
||||||
|
{
|
||||||
|
private static readonly Uri ExecutorUri = new Uri(CosmosTestExecutor.ExecutorUri);
|
||||||
|
|
||||||
|
public void DiscoverTests(
|
||||||
|
IEnumerable<string> sources,
|
||||||
|
IDiscoveryContext discoveryContext,
|
||||||
|
IMessageLogger logger,
|
||||||
|
ITestCaseDiscoverySink discoverySink)
|
||||||
|
{
|
||||||
|
var testCases = DiscoverTests(sources, discoveryContext, logger);
|
||||||
|
|
||||||
|
foreach (var testCase in testCases)
|
||||||
|
{
|
||||||
|
discoverySink.SendTestCase(testCase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal IEnumerable<TestCase> DiscoverTests(
|
||||||
|
IEnumerable<string> sources,
|
||||||
|
IDiscoveryContext discoveryContext,
|
||||||
|
IMessageLogger logger)
|
||||||
|
{
|
||||||
|
var testCases = new List<TestCase>();
|
||||||
|
|
||||||
|
foreach (var source in sources)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var stream = File.OpenRead(source))
|
||||||
|
{
|
||||||
|
using (var peReader = new PEReader(stream))
|
||||||
|
{
|
||||||
|
if (!peReader.HasMetadata)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var metadataReader = peReader.GetMetadataReader();
|
||||||
|
|
||||||
|
if (!metadataReader.IsAssembly)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: check exported types?
|
||||||
|
|
||||||
|
foreach (var typeHandle in metadataReader.TypeDefinitions)
|
||||||
|
{
|
||||||
|
var type = metadataReader.GetTypeDefinition(typeHandle);
|
||||||
|
|
||||||
|
if ((type.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public)
|
||||||
|
{
|
||||||
|
var baseTypeHandle = type.BaseType;
|
||||||
|
|
||||||
|
// has to be type reference, as it's not generic
|
||||||
|
// and it's not declared in the same module
|
||||||
|
if (baseTypeHandle.Kind == HandleKind.TypeReference)
|
||||||
|
{
|
||||||
|
var baseType = metadataReader.GetTypeReference((TypeReferenceHandle)baseTypeHandle);
|
||||||
|
|
||||||
|
var baseTypeNamespace = metadataReader.GetString(baseType.Namespace);
|
||||||
|
var baseTypeName = metadataReader.GetString(baseType.Name);
|
||||||
|
|
||||||
|
if (String.Equals(baseTypeNamespace, "Cosmos.System", StringComparison.Ordinal)
|
||||||
|
&& String.Equals(baseTypeName, "Kernel", StringComparison.Ordinal)
|
||||||
|
&& baseType.ResolutionScope.Kind == HandleKind.AssemblyReference)
|
||||||
|
{
|
||||||
|
var baseTypeAssemblyReference = metadataReader.GetAssemblyReference(
|
||||||
|
(AssemblyReferenceHandle)baseType.ResolutionScope);
|
||||||
|
|
||||||
|
var baseTypeAssemblyName = metadataReader.GetString(baseTypeAssemblyReference.Name);
|
||||||
|
|
||||||
|
if (String.Equals(baseTypeAssemblyName, "Cosmos.System2", StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
var typeNamespace = metadataReader.GetString(type.Namespace);
|
||||||
|
var typeName = metadataReader.GetString(type.Name);
|
||||||
|
|
||||||
|
var assemblyDefinition = metadataReader.GetAssemblyDefinition();
|
||||||
|
var assemblyName = metadataReader.GetString(assemblyDefinition.Name);
|
||||||
|
|
||||||
|
var fullyQualifiedName = $"{typeName}, {assemblyName}";
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(typeNamespace))
|
||||||
|
{
|
||||||
|
fullyQualifiedName = $"{typeNamespace}.{fullyQualifiedName}";
|
||||||
|
}
|
||||||
|
|
||||||
|
var testCase = new TestCase(fullyQualifiedName, ExecutorUri, source);
|
||||||
|
testCases.Add(testCase);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return testCases;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
67
Tests/Cosmos.TestRunner.TestAdapter/CosmosTestExecutor.cs
Normal file
67
Tests/Cosmos.TestRunner.TestAdapter/CosmosTestExecutor.cs
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Threading;
|
||||||
|
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
|
||||||
|
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter;
|
||||||
|
|
||||||
|
using Cosmos.TestRunner.Core;
|
||||||
|
|
||||||
|
namespace Cosmos.TestRunner.TestAdapter
|
||||||
|
{
|
||||||
|
[ExtensionUri(ExecutorUri)]
|
||||||
|
public sealed class CosmosTestExecutor : ITestExecutor
|
||||||
|
{
|
||||||
|
public const string ExecutorUri = "executor://CosmosTestExecutor";
|
||||||
|
|
||||||
|
private CancellationTokenSource _cancellationTokenSource;
|
||||||
|
|
||||||
|
public void RunTests(
|
||||||
|
IEnumerable<TestCase> tests,
|
||||||
|
IRunContext runContext,
|
||||||
|
IFrameworkHandle frameworkHandle)
|
||||||
|
{
|
||||||
|
_cancellationTokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
|
foreach (var test in tests)
|
||||||
|
{
|
||||||
|
var configuration = new EngineConfiguration(new string[] { test.Source }, runContext);
|
||||||
|
var testEngine = new Engine(configuration);
|
||||||
|
|
||||||
|
var outputHandler = new TestAdapterOutputHandler(frameworkHandle);
|
||||||
|
testEngine.SetOutputHandler(outputHandler);
|
||||||
|
|
||||||
|
var testResult = new TestResult(test);
|
||||||
|
|
||||||
|
frameworkHandle.RecordStart(test);
|
||||||
|
|
||||||
|
var kernelTestResult = testEngine.Execute(_cancellationTokenSource.Token).KernelTestResults[0];
|
||||||
|
|
||||||
|
testResult.Outcome = kernelTestResult.Result ? TestOutcome.Passed : TestOutcome.Failed;
|
||||||
|
|
||||||
|
var messages = new Collection<TestResultMessage>();
|
||||||
|
|
||||||
|
foreach (var message in outputHandler.Messages)
|
||||||
|
{
|
||||||
|
messages.Add(new TestResultMessage(String.Empty, message));
|
||||||
|
}
|
||||||
|
|
||||||
|
frameworkHandle.RecordEnd(test, testResult.Outcome);
|
||||||
|
frameworkHandle.RecordResult(testResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RunTests(
|
||||||
|
IEnumerable<string> sources,
|
||||||
|
IRunContext runContext,
|
||||||
|
IFrameworkHandle frameworkHandle)
|
||||||
|
{
|
||||||
|
var discoverer = new CosmosTestDiscoverer();
|
||||||
|
var tests = discoverer.DiscoverTests(sources, runContext, null);
|
||||||
|
|
||||||
|
RunTests(tests, runContext, frameworkHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Cancel() => _cancellationTokenSource.Cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
119
Tests/Cosmos.TestRunner.TestAdapter/EngineConfiguration.cs
Normal file
119
Tests/Cosmos.TestRunner.TestAdapter/EngineConfiguration.cs
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter;
|
||||||
|
|
||||||
|
using Cosmos.Build.Common;
|
||||||
|
using Cosmos.TestRunner.Core;
|
||||||
|
|
||||||
|
namespace Cosmos.TestRunner.TestAdapter
|
||||||
|
{
|
||||||
|
internal sealed class EngineConfiguration : IEngineConfiguration
|
||||||
|
{
|
||||||
|
public int AllowedSecondsInKernel { get; }
|
||||||
|
public IEnumerable<RunTargetEnum> RunTargets { get; }
|
||||||
|
public bool RunWithGDB { get; }
|
||||||
|
public bool StartBochsDebugGUI { get; }
|
||||||
|
|
||||||
|
public bool DebugIL2CPU { get; }
|
||||||
|
public string KernelPkg { get; }
|
||||||
|
public TraceAssemblies TraceAssembliesLevel { get; }
|
||||||
|
public bool EnableStackCorruptionChecks { get; }
|
||||||
|
public StackCorruptionDetectionLevel StackCorruptionDetectionLevel { get; }
|
||||||
|
|
||||||
|
public IEnumerable<string> KernelAssembliesToRun { get; }
|
||||||
|
|
||||||
|
private readonly IRunContext _context;
|
||||||
|
|
||||||
|
public EngineConfiguration(
|
||||||
|
IEnumerable<string> testKernels,
|
||||||
|
IRunContext context)
|
||||||
|
{
|
||||||
|
KernelAssembliesToRun = testKernels;
|
||||||
|
|
||||||
|
_context = context;
|
||||||
|
|
||||||
|
var settingsXml = _context.RunSettings.SettingsXml;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(settingsXml))
|
||||||
|
{
|
||||||
|
settingsXml = "<RunSettings />";
|
||||||
|
}
|
||||||
|
|
||||||
|
var doc = XDocument.Parse(settingsXml);
|
||||||
|
var runConfiguration = doc.Element("RunConfiguration");
|
||||||
|
|
||||||
|
AllowedSecondsInKernel = GetIntValue(runConfiguration, nameof(AllowedSecondsInKernel), 1200);
|
||||||
|
|
||||||
|
var runTargetsString = GetStringValue(runConfiguration, nameof(RunTargets), "Bochs");
|
||||||
|
var runTargets = new List<RunTargetEnum>();
|
||||||
|
|
||||||
|
foreach (var runTargetName in runTargetsString.Split(';'))
|
||||||
|
{
|
||||||
|
if (Enum.TryParse<RunTargetEnum>(runTargetName, out var runTarget))
|
||||||
|
{
|
||||||
|
runTargets.Add(runTarget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RunTargets = runTargets;
|
||||||
|
RunWithGDB = GetBoolValue(runConfiguration, nameof(RunWithGDB), false);
|
||||||
|
StartBochsDebugGUI = GetBoolValue(runConfiguration, nameof(StartBochsDebugGUI), false);
|
||||||
|
|
||||||
|
DebugIL2CPU = GetBoolValue(runConfiguration, nameof(DebugIL2CPU), false);
|
||||||
|
KernelPkg = GetStringValue(runConfiguration, nameof(KernelPkg), String.Empty);
|
||||||
|
TraceAssembliesLevel = GetEnumValue(runConfiguration, nameof(KernelPkg), TraceAssemblies.User);
|
||||||
|
EnableStackCorruptionChecks = GetBoolValue(runConfiguration, nameof(EnableStackCorruptionChecks), true);
|
||||||
|
StackCorruptionDetectionLevel = GetEnumValue(
|
||||||
|
runConfiguration, nameof(KernelPkg), StackCorruptionDetectionLevel.AllInstructions);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool GetBoolValue(XElement element, XName name, bool defaultValue)
|
||||||
|
{
|
||||||
|
var value = GetStringValue(element, name, null);
|
||||||
|
|
||||||
|
if (Boolean.TryParse(value, out var result))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static T GetEnumValue<T>(XElement element, XName name, T defaultValue) where T : struct, Enum
|
||||||
|
{
|
||||||
|
var value = GetStringValue(element, name, null);
|
||||||
|
|
||||||
|
if (Enum.TryParse<T>(value, true, out var result))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetIntValue(XElement element, XName name, int defaultValue)
|
||||||
|
{
|
||||||
|
var value = GetStringValue(element, name, null);
|
||||||
|
|
||||||
|
if (Int32.TryParse(value, out var result))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetStringValue(XElement element, XName name, string defaultValue)
|
||||||
|
{
|
||||||
|
var childElement = element?.Element(name);
|
||||||
|
|
||||||
|
if (childElement != null)
|
||||||
|
{
|
||||||
|
return childElement.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
4
Tests/Cosmos.TestRunner.TestAdapter/Readme.txt
Normal file
4
Tests/Cosmos.TestRunner.TestAdapter/Readme.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
To debug vstest/test adapter:
|
||||||
|
|
||||||
|
set VSTEST_HOST_DEBUG=1
|
||||||
|
dotnet test
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter;
|
||||||
|
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;
|
||||||
|
|
||||||
|
using Cosmos.TestRunner.Core;
|
||||||
|
|
||||||
|
namespace Cosmos.TestRunner.TestAdapter
|
||||||
|
{
|
||||||
|
internal class TestAdapterOutputHandler : OutputHandlerFullTextBase
|
||||||
|
{
|
||||||
|
public IReadOnlyList<string> Messages => _messages;
|
||||||
|
|
||||||
|
private readonly IFrameworkHandle _frameworkHandle;
|
||||||
|
private readonly List<string> _messages = new List<string>();
|
||||||
|
|
||||||
|
public TestAdapterOutputHandler(IFrameworkHandle frameworkHandle)
|
||||||
|
{
|
||||||
|
_frameworkHandle = frameworkHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Log(string message)
|
||||||
|
{
|
||||||
|
_frameworkHandle.SendMessage(TestMessageLevel.Informational, message);
|
||||||
|
_messages.Add(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue