Modifying the reporting channels to make the AdapterChannel a client and leave the TestRunnerChannel a server. This will prevent port conflicts between dotnet test and the Adapter (VS) due to race conditions.
Added E2E tests for dotnet test interactions with an adapter (design time).
This commit is contained in:
parent
ffedcb315f
commit
8d39adbdbf
22 changed files with 536 additions and 84 deletions
|
@ -1,6 +1,7 @@
|
|||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25020.0
|
||||
VisualStudioVersion = 14.0.25029.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{ED2FE3E2-F7E7-4389-8231-B65123F2076F}"
|
||||
EndProject
|
||||
|
@ -76,6 +77,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.TestFramew
|
|||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-test.UnitTests", "test\dotnet-test.UnitTests\dotnet-test.UnitTests.xproj", "{857274AC-E741-4266-A7FD-14DEE0C1CC96}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-test.Tests", "test\dotnet-test.Tests\dotnet-test.Tests.xproj", "{60C33D0A-A5D8-4AB0-9956-1F804654DF05}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -472,22 +475,6 @@ Global
|
|||
{0745410A-6629-47EB-AAB5-08D6288CAD72}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
|
||||
{0745410A-6629-47EB-AAB5-08D6288CAD72}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
|
||||
{0745410A-6629-47EB-AAB5-08D6288CAD72}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
|
||||
{0B31C336-149D-471A-B7B1-27B0F1E80F83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0B31C336-149D-471A-B7B1-27B0F1E80F83}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0B31C336-149D-471A-B7B1-27B0F1E80F83}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
|
@ -504,22 +491,22 @@ Global
|
|||
{0B31C336-149D-471A-B7B1-27B0F1E80F83}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
|
||||
{0B31C336-149D-471A-B7B1-27B0F1E80F83}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
|
||||
{0B31C336-149D-471A-B7B1-27B0F1E80F83}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.Release|x64.Build.0 = Release|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
|
||||
{0724ED7C-56E3-4604-9970-25E600611383}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0724ED7C-56E3-4604-9970-25E600611383}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0724ED7C-56E3-4604-9970-25E600611383}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
|
@ -536,6 +523,38 @@ Global
|
|||
{0724ED7C-56E3-4604-9970-25E600611383}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
|
||||
{0724ED7C-56E3-4604-9970-25E600611383}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
|
||||
{0724ED7C-56E3-4604-9970-25E600611383}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.Release|x64.Build.0 = Release|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
|
||||
{60C33D0A-A5D8-4AB0-9956-1F804654DF05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{60C33D0A-A5D8-4AB0-9956-1F804654DF05}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{60C33D0A-A5D8-4AB0-9956-1F804654DF05}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{60C33D0A-A5D8-4AB0-9956-1F804654DF05}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{60C33D0A-A5D8-4AB0-9956-1F804654DF05}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{60C33D0A-A5D8-4AB0-9956-1F804654DF05}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
|
||||
{60C33D0A-A5D8-4AB0-9956-1F804654DF05}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{60C33D0A-A5D8-4AB0-9956-1F804654DF05}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{60C33D0A-A5D8-4AB0-9956-1F804654DF05}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{60C33D0A-A5D8-4AB0-9956-1F804654DF05}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{60C33D0A-A5D8-4AB0-9956-1F804654DF05}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{60C33D0A-A5D8-4AB0-9956-1F804654DF05}.Release|x64.Build.0 = Release|Any CPU
|
||||
{60C33D0A-A5D8-4AB0-9956-1F804654DF05}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{60C33D0A-A5D8-4AB0-9956-1F804654DF05}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
|
||||
{60C33D0A-A5D8-4AB0-9956-1F804654DF05}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
|
||||
{60C33D0A-A5D8-4AB0-9956-1F804654DF05}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -565,11 +584,12 @@ Global
|
|||
{DA8E0E9E-A6D6-4583-864C-8F40465E3A48} = {713CBFBB-5392-438D-B766-A9A585EF1BB8}
|
||||
{0138CB8F-4AA9-4029-A21E-C07C30F425BA} = {713CBFBB-5392-438D-B766-A9A585EF1BB8}
|
||||
{BD4F0750-4E81-4AD2-90B5-E470881792C3} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
|
||||
{0745410A-6629-47EB-AAB5-08D6288CAD72} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
|
||||
{0E3300A4-DF54-40BF-87D8-E7658330C288} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
|
||||
{0B31C336-149D-471A-B7B1-27B0F1E80F83} = {0E3300A4-DF54-40BF-87D8-E7658330C288}
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
|
||||
{4A4711D8-4312-49FC-87B5-4F183F4C6A51} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
|
||||
{0724ED7C-56E3-4604-9970-25E600611383} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
|
||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
|
||||
{60C33D0A-A5D8-4AB0-9956-1F804654DF05} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -0,0 +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.
|
||||
|
||||
using Xunit;
|
||||
|
||||
namespace FakeTests
|
||||
{
|
||||
public class GivenThatIWantSomeFakeTests
|
||||
{
|
||||
[Fact]
|
||||
public void It_succeeds()
|
||||
{
|
||||
Assert.True(true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void It_fails()
|
||||
{
|
||||
Assert.True(false);
|
||||
}
|
||||
}
|
||||
}
|
21
TestAssets/TestProjects/ProjectWithTests/project.json
Normal file
21
TestAssets/TestProjects/ProjectWithTests/project.json
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"version": "1.0.0-*",
|
||||
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.5.0-rc2-23911",
|
||||
|
||||
"xunit": "2.1.0",
|
||||
"dotnet-test-xunit": "1.0.0-dev-91790-12"
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"netstandardapp1.5": {
|
||||
"imports": [
|
||||
"dnxcore50",
|
||||
"portable-net45+win8"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"testRunner": "xunit"
|
||||
}
|
|
@ -36,7 +36,8 @@ namespace Microsoft.DotNet.Cli.Build
|
|||
"Microsoft.DotNet.ProjectModel.Tests",
|
||||
"Microsoft.Extensions.DependencyModel.Tests",
|
||||
"ArgumentForwardingTests",
|
||||
"dotnet-test.UnitTests"
|
||||
"dotnet-test.UnitTests",
|
||||
"dotnet-test.Tests"
|
||||
};
|
||||
|
||||
[Target(nameof(PrepareTargets.Init), nameof(SetupTests), nameof(RestoreTests), nameof(BuildTests), nameof(RunTests), nameof(ValidateDependencies))]
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace Microsoft.DotNet.Tools.Test
|
|||
|
||||
dotnetTest.StartListeningTo(testRunnerChannel);
|
||||
|
||||
testRunnerChannel.Accept();
|
||||
testRunnerChannel.Connect();
|
||||
|
||||
var testRunner = _testRunnerFactory.CreateTestRunner(
|
||||
new RunTestsArgumentsBuilder(dotnetTest.PathToAssemblyUnderTest, testRunnerChannel.Port, message));
|
||||
|
|
|
@ -55,7 +55,7 @@ namespace Microsoft.DotNet.Cli.Tools.Test
|
|||
|
||||
dotnetTest.StartListeningTo(testRunnerChannel);
|
||||
|
||||
testRunnerChannel.Accept();
|
||||
testRunnerChannel.Connect();
|
||||
|
||||
var testRunner = _testRunnerFactory.CreateTestRunner(
|
||||
new DiscoverTestsArgumentsBuilder(dotnetTest.PathToAssemblyUnderTest, testRunnerChannel.Port));
|
||||
|
|
|
@ -11,6 +11,7 @@ namespace Microsoft.DotNet.Tools.Test
|
|||
public const string TestRunnerTestStarted = "TestExecution.TestStarted";
|
||||
public const string TestRunnerTestCompleted = "TestRunner.TestCompleted";
|
||||
public const string TestRunnerTestFound = "TestDiscovery.TestFound";
|
||||
public const string TestSessionConnected = "TestSession.Connected";
|
||||
public const string TestSessionTerminate = "TestSession.Terminate";
|
||||
public const string VersionCheck = "ProtocolVersion";
|
||||
public const string TestDiscoveryStart = "TestDiscovery.Start";
|
||||
|
|
|
@ -183,7 +183,7 @@ namespace Microsoft.DotNet.Tools.Test
|
|||
|
||||
dotnetTest.StartListeningTo(adapterChannel);
|
||||
|
||||
adapterChannel.Accept();
|
||||
adapterChannel.Connect();
|
||||
|
||||
dotnetTest.StartHandlingMessages();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
// 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.Testing.Abstractions;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Microsoft.DotNet.Tools.Test
|
||||
{
|
||||
public class AdapterReportingChannel : ReportingChannel
|
||||
{
|
||||
private readonly IPEndPoint _ipEndPoint;
|
||||
|
||||
public static AdapterReportingChannel ConnectTo(int port)
|
||||
{
|
||||
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
var ipEndPoint = new IPEndPoint(IPAddress.Loopback, port);
|
||||
|
||||
return new AdapterReportingChannel(socket, ipEndPoint);
|
||||
}
|
||||
|
||||
private AdapterReportingChannel(Socket connectSocket, IPEndPoint ipEndPoint)
|
||||
: base(connectSocket, ipEndPoint.Port)
|
||||
{
|
||||
_ipEndPoint = ipEndPoint;
|
||||
}
|
||||
|
||||
public override void Connect()
|
||||
{
|
||||
Socket = ConnectSocket;
|
||||
|
||||
Socket.Connect(_ipEndPoint);
|
||||
|
||||
StartReadingMessages();
|
||||
|
||||
Send(new Message
|
||||
{
|
||||
MessageType = TestMessageTypes.TestSessionConnected
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@ namespace Microsoft.DotNet.Tools.Test
|
|||
|
||||
int Port { get; }
|
||||
|
||||
void Accept();
|
||||
void Connect();
|
||||
|
||||
void Send(Message message);
|
||||
|
|
@ -14,52 +14,26 @@ using Newtonsoft.Json.Linq;
|
|||
|
||||
namespace Microsoft.DotNet.Tools.Test
|
||||
{
|
||||
public class ReportingChannel : IReportingChannel
|
||||
public abstract class ReportingChannel : IReportingChannel
|
||||
{
|
||||
public static ReportingChannel ListenOn(int port)
|
||||
{
|
||||
// This fixes the mono incompatibility but ties it to ipv4 connections
|
||||
var listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
listenSocket.Bind(new IPEndPoint(IPAddress.Loopback, port));
|
||||
listenSocket.Listen(10);
|
||||
|
||||
return new ReportingChannel(listenSocket);
|
||||
}
|
||||
|
||||
private BinaryWriter _writer;
|
||||
private BinaryReader _reader;
|
||||
private Socket _listenSocket;
|
||||
|
||||
private ReportingChannel(Socket listenSocket)
|
||||
protected ReportingChannel(Socket connectSocket, int port)
|
||||
{
|
||||
_listenSocket = listenSocket;
|
||||
Port = ((IPEndPoint)listenSocket.LocalEndPoint).Port;
|
||||
ConnectSocket = connectSocket;
|
||||
Port = port;
|
||||
}
|
||||
|
||||
protected Socket Socket { get; set; }
|
||||
|
||||
public event EventHandler<Message> MessageReceived;
|
||||
|
||||
public Socket Socket { get; private set; }
|
||||
public Socket ConnectSocket { get; }
|
||||
|
||||
public int Port { get; }
|
||||
|
||||
public void Accept()
|
||||
{
|
||||
new Thread(() =>
|
||||
{
|
||||
using (_listenSocket)
|
||||
{
|
||||
Socket = _listenSocket.Accept();
|
||||
|
||||
var stream = new NetworkStream(Socket);
|
||||
_writer = new BinaryWriter(stream);
|
||||
_reader = new BinaryReader(stream);
|
||||
|
||||
// Read incoming messages on the background thread
|
||||
new Thread(ReadMessages) { IsBackground = true }.Start();
|
||||
}
|
||||
}) { IsBackground = true }.Start();
|
||||
}
|
||||
public abstract void Connect();
|
||||
|
||||
public void Send(Message message)
|
||||
{
|
||||
|
@ -104,6 +78,16 @@ namespace Microsoft.DotNet.Tools.Test
|
|||
SendError(ex.ToString());
|
||||
}
|
||||
|
||||
protected void StartReadingMessages()
|
||||
{
|
||||
var stream = new NetworkStream(Socket);
|
||||
_writer = new BinaryWriter(stream);
|
||||
_reader = new BinaryReader(stream);
|
||||
|
||||
// Read incoming messages on the background thread
|
||||
new Thread(ReadMessages) { IsBackground = true }.Start();
|
||||
}
|
||||
|
||||
private void ReadMessages()
|
||||
{
|
||||
while (true)
|
||||
|
@ -140,10 +124,7 @@ namespace Microsoft.DotNet.Tools.Test
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Socket != null)
|
||||
{
|
||||
Socket.Dispose();
|
||||
}
|
||||
Socket?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@ namespace Microsoft.DotNet.Tools.Test
|
|||
|
||||
public IReportingChannel CreateTestRunnerChannel()
|
||||
{
|
||||
var testRunnerChannel = ReportingChannel.ListenOn(0);
|
||||
var testRunnerChannel = TestRunnerReportingChannel.ListenOn(0);
|
||||
|
||||
TestRunnerChannelCreated?.Invoke(this, testRunnerChannel);
|
||||
|
||||
|
@ -20,7 +20,7 @@ namespace Microsoft.DotNet.Tools.Test
|
|||
|
||||
public IReportingChannel CreateAdapterChannel(int port)
|
||||
{
|
||||
return ReportingChannel.ListenOn(port);
|
||||
return AdapterReportingChannel.ConnectTo(port);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
|
||||
namespace Microsoft.DotNet.Tools.Test
|
||||
{
|
||||
public class TestRunnerReportingChannel : ReportingChannel
|
||||
{
|
||||
public static ReportingChannel ListenOn(int port)
|
||||
{
|
||||
// This fixes the mono incompatibility but ties it to ipv4 connections
|
||||
var listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
listenSocket.Bind(new IPEndPoint(IPAddress.Loopback, port));
|
||||
listenSocket.Listen(10);
|
||||
|
||||
return new TestRunnerReportingChannel(listenSocket, ((IPEndPoint)listenSocket.LocalEndPoint));
|
||||
}
|
||||
|
||||
private TestRunnerReportingChannel(Socket connectSocket, IPEndPoint ipEndPoint)
|
||||
: base(connectSocket, ipEndPoint.Port)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Connect()
|
||||
{
|
||||
new Thread(() =>
|
||||
{
|
||||
using (ConnectSocket)
|
||||
{
|
||||
Socket = ConnectSocket.Accept();
|
||||
|
||||
StartReadingMessages();
|
||||
}
|
||||
})
|
||||
{ IsBackground = true }.Start();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -58,7 +58,8 @@
|
|||
"Microsoft.Win32.Registry": {
|
||||
"version": "4.0.0-rc2-23911",
|
||||
"exclude": "Compile"
|
||||
}
|
||||
},
|
||||
"System.Net.NameResolution": "4.0.0-rc2-23911"
|
||||
},
|
||||
"frameworks": {
|
||||
"netstandardapp1.5": {
|
||||
|
|
|
@ -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 Microsoft.DotNet.Cli.Utils;
|
||||
|
||||
namespace Microsoft.DotNet.Tools.Test.Utilities
|
||||
{
|
||||
public class DotnetTestCommand : TestCommand
|
||||
{
|
||||
public DotnetTestCommand() : base("dotnet")
|
||||
{
|
||||
}
|
||||
|
||||
public override CommandResult Execute(string args = "")
|
||||
{
|
||||
args = $"test {args}";
|
||||
return base.Execute(args);
|
||||
}
|
||||
}
|
||||
}
|
177
test/dotnet-test.Tests/Adapter.cs
Normal file
177
test/dotnet-test.Tests/Adapter.cs
Normal file
|
@ -0,0 +1,177 @@
|
|||
// 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.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using Microsoft.Extensions.Testing.Abstractions;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Microsoft.Dotnet.Tools.Test.Tests
|
||||
{
|
||||
public class Adapter : IDisposable
|
||||
{
|
||||
private readonly string _startMessage;
|
||||
private BinaryWriter _writer;
|
||||
private BinaryReader _reader;
|
||||
private Socket _socket;
|
||||
private Socket _listenSocket;
|
||||
|
||||
public IDictionary<string, List<Message>> Messages { get; }
|
||||
|
||||
public int Port { get; private set; }
|
||||
|
||||
public Adapter(string startMessage)
|
||||
{
|
||||
_startMessage = startMessage;
|
||||
Messages = new Dictionary<string, List<Message>>();
|
||||
|
||||
_listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
var endpoint = new IPEndPoint(IPAddress.Loopback, 0);
|
||||
_listenSocket.Bind(endpoint);
|
||||
|
||||
Port = ((IPEndPoint)_listenSocket.LocalEndPoint).Port;
|
||||
}
|
||||
|
||||
public void Listen()
|
||||
{
|
||||
var listenThread = new Thread(() =>
|
||||
{
|
||||
using (_listenSocket)
|
||||
{
|
||||
_listenSocket.Listen(1);
|
||||
_socket = _listenSocket.Accept();
|
||||
}
|
||||
|
||||
var stream = new NetworkStream(_socket);
|
||||
_writer = new BinaryWriter(stream);
|
||||
_reader = new BinaryReader(stream);
|
||||
|
||||
ReadMessages();
|
||||
})
|
||||
{
|
||||
IsBackground = true
|
||||
};
|
||||
|
||||
listenThread.Start();
|
||||
}
|
||||
|
||||
public void Send(string messageType)
|
||||
{
|
||||
lock (_writer)
|
||||
{
|
||||
_writer.Write(JsonConvert.SerializeObject(new
|
||||
{
|
||||
MessageType = messageType,
|
||||
PayLoad = JToken.FromObject(new
|
||||
{
|
||||
})
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadMessages()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
var message = GetMessage();
|
||||
|
||||
StoreMessage(message);
|
||||
|
||||
if (HandleMessage(message))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void StoreMessage(Message message)
|
||||
{
|
||||
if (!Messages.ContainsKey(message.MessageType))
|
||||
{
|
||||
Messages.Add(message.MessageType, new List<Message>());
|
||||
}
|
||||
|
||||
Messages[message.MessageType].Add(message);
|
||||
}
|
||||
|
||||
private bool HandleMessage(Message message)
|
||||
{
|
||||
if (message.MessageType == "TestSession.Connected")
|
||||
{
|
||||
Send(_startMessage);
|
||||
}
|
||||
|
||||
if (message.MessageType == "TestExecution.TestRunnerProcessStartInfo")
|
||||
{
|
||||
StartTestRunner(message.Payload.ToObject<TestStartInfo>());
|
||||
}
|
||||
|
||||
if (message.MessageType == "TestDiscovery.Completed")
|
||||
{
|
||||
Send("TestSession.Terminate");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (message.MessageType == "TestExecution.Completed")
|
||||
{
|
||||
Send("TestSession.Terminate");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void StartTestRunner(TestStartInfo testPsiInfo)
|
||||
{
|
||||
var testPsi = new ProcessStartInfo(testPsiInfo.FileName, testPsiInfo.Arguments);
|
||||
testPsi.RedirectStandardOutput = true;
|
||||
testPsi.UseShellExecute = false;
|
||||
var testProcess = new Process
|
||||
{
|
||||
StartInfo = testPsi
|
||||
};
|
||||
|
||||
var testProcessThread = new Thread(() => { testProcess.Start(); })
|
||||
{
|
||||
IsBackground = true
|
||||
};
|
||||
testProcessThread.Start();
|
||||
}
|
||||
|
||||
private Message GetMessage()
|
||||
{
|
||||
var rawMessage = _reader.ReadString();
|
||||
Console.WriteLine("\nRECEIVING MESSAGE:");
|
||||
Console.WriteLine($"{rawMessage}");
|
||||
Console.WriteLine($"==============================\n");
|
||||
|
||||
var message = JsonConvert.DeserializeObject<Message>(rawMessage);
|
||||
return message;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_socket?.Dispose();
|
||||
}
|
||||
|
||||
private class TestStartInfo
|
||||
{
|
||||
public string FileName { get; set; }
|
||||
|
||||
public string Arguments { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
// 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.DotNet.ProjectModel;
|
||||
using Microsoft.DotNet.Tools.Test.Utilities;
|
||||
using System.IO;
|
||||
using FluentAssertions;
|
||||
using Xunit;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.Dotnet.Tools.Test.Tests
|
||||
{
|
||||
public class GivenThatWeWantToUseDotnetTestE2EInDesignTime : TestBase
|
||||
{
|
||||
private string _projectFilePath;
|
||||
private string _outputPath;
|
||||
|
||||
public GivenThatWeWantToUseDotnetTestE2EInDesignTime()
|
||||
{
|
||||
var testInstance = TestAssetsManager.CreateTestInstance("ProjectWithTests").WithLockFiles();
|
||||
|
||||
_projectFilePath = Path.Combine(testInstance.TestRoot, "project.json");
|
||||
var contexts = ProjectContext.CreateContextForEachFramework(
|
||||
_projectFilePath,
|
||||
null,
|
||||
PlatformServices.Default.Runtime.GetAllCandidateRuntimeIdentifiers());
|
||||
var runtime = contexts.FirstOrDefault(c => !string.IsNullOrEmpty(c.RuntimeIdentifier))?.RuntimeIdentifier;
|
||||
_outputPath = Path.Combine(testInstance.TestRoot, "bin", "Debug", DefaultFramework, runtime);
|
||||
var buildCommand = new BuildCommand(_projectFilePath);
|
||||
var result = buildCommand.Execute();
|
||||
|
||||
result.Should().Pass();
|
||||
}
|
||||
|
||||
[WindowsOnlyFact]
|
||||
public void It_discovers_two_tests_for_the_ProjectWithTests()
|
||||
{
|
||||
using (var adapter = new Adapter("TestDiscovery.Start"))
|
||||
{
|
||||
adapter.Listen();
|
||||
|
||||
var testCommand = new DotnetTestCommand();
|
||||
var result = testCommand.Execute($"{_projectFilePath} -o {_outputPath} --port {adapter.Port}");
|
||||
result.Should().Pass();
|
||||
|
||||
adapter.Messages["TestSession.Connected"].Count.Should().Be(1);
|
||||
adapter.Messages["TestDiscovery.TestFound"].Count.Should().Be(2);
|
||||
adapter.Messages["TestDiscovery.Completed"].Count.Should().Be(1);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void It_runs_two_tests_for_the_ProjectWithTests()
|
||||
{
|
||||
using (var adapter = new Adapter("TestExecution.GetTestRunnerProcessStartInfo"))
|
||||
{
|
||||
adapter.Listen();
|
||||
|
||||
var testCommand = new DotnetTestCommand();
|
||||
var result = testCommand.Execute($"{_projectFilePath} -o {_outputPath} --port {adapter.Port}");
|
||||
result.Should().Pass();
|
||||
|
||||
adapter.Messages["TestSession.Connected"].Count.Should().Be(1);
|
||||
adapter.Messages["TestExecution.TestRunnerProcessStartInfo"].Count.Should().Be(1);
|
||||
adapter.Messages["TestExecution.TestStarted"].Count.Should().Be(2);
|
||||
adapter.Messages["TestExecution.TestResult"].Count.Should().Be(2);
|
||||
adapter.Messages["TestExecution.Completed"].Count.Should().Be(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
18
test/dotnet-test.Tests/dotnet-test.Tests.xproj
Normal file
18
test/dotnet-test.Tests/dotnet-test.Tests.xproj
Normal file
|
@ -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>60c33d0a-a5d8-4ab0-9956-1f804654df05</ProjectGuid>
|
||||
<RootNamespace>Microsoft.Dotnet.Tools.Test.Tests</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
33
test/dotnet-test.Tests/project.json
Normal file
33
test/dotnet-test.Tests/project.json
Normal file
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"version": "1.0.0-*",
|
||||
|
||||
"dependencies": {
|
||||
"Newtonsoft.Json": "7.0.1",
|
||||
"NETStandard.Library": "1.5.0-rc2-23911",
|
||||
"Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" },
|
||||
"Microsoft.DotNet.TestFramework": { "target": "project" },
|
||||
"Microsoft.DotNet.ProjectModel": { "target": "project" },
|
||||
"Microsoft.Extensions.Testing.Abstractions": { "target": "project" },
|
||||
"System.Net.NameResolution": "4.0.0-rc2-23911",
|
||||
"System.Net.Sockets": "4.1.0-rc2-23911",
|
||||
"System.Runtime.Serialization.Primitives": "4.1.1-rc2-23911",
|
||||
|
||||
"xunit": "2.1.0",
|
||||
"dotnet-test-xunit": "1.0.0-dev-91790-12"
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"netstandardapp1.5": {
|
||||
"imports": [
|
||||
"dnxcore50",
|
||||
"portable-net45+win8"
|
||||
]
|
||||
}
|
||||
},
|
||||
"content": [
|
||||
"../../TestAssets/TestProjects/ProjectWithTests/**/*",
|
||||
"../../TestAssets/TestProjects/global.json"
|
||||
],
|
||||
|
||||
"testRunner": "xunit"
|
||||
}
|
|
@ -141,7 +141,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests
|
|||
_dotnetTestMock.Object,
|
||||
_validMessage);
|
||||
|
||||
_testRunnerChannelMock.Verify(t => t.Accept(), Times.Once);
|
||||
_testRunnerChannelMock.Verify(t => t.Connect(), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
@ -161,7 +161,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests
|
|||
_dotnetTestMock.Object,
|
||||
_validMessage);
|
||||
|
||||
_testRunnerChannelMock.Verify(t => t.Accept(), Times.Once);
|
||||
_testRunnerChannelMock.Verify(t => t.Connect(), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
Loading…
Reference in a new issue