diff --git a/Microsoft.DotNet.Cli.sln b/Microsoft.DotNet.Cli.sln index faa3eb2c8..e2ce9023a 100644 --- a/Microsoft.DotNet.Cli.sln +++ b/Microsoft.DotNet.Cli.sln @@ -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 diff --git a/TestAssets/TestProjects/ProjectWithTests/GivenThatIWantSomeFakeTests.cs b/TestAssets/TestProjects/ProjectWithTests/GivenThatIWantSomeFakeTests.cs new file mode 100644 index 000000000..4eca454af --- /dev/null +++ b/TestAssets/TestProjects/ProjectWithTests/GivenThatIWantSomeFakeTests.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/TestAssets/TestProjects/ProjectWithTests/project.json b/TestAssets/TestProjects/ProjectWithTests/project.json new file mode 100644 index 000000000..db7fc17fa --- /dev/null +++ b/TestAssets/TestProjects/ProjectWithTests/project.json @@ -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" +} diff --git a/scripts/dotnet-cli-build/TestTargets.cs b/scripts/dotnet-cli-build/TestTargets.cs index 8526400a3..5d0e3c31f 100644 --- a/scripts/dotnet-cli-build/TestTargets.cs +++ b/scripts/dotnet-cli-build/TestTargets.cs @@ -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))] diff --git a/src/dotnet/commands/dotnet-test/MessageHandlers/GetTestRunnerProcessStartInfoMessageHandler.cs b/src/dotnet/commands/dotnet-test/MessageHandlers/GetTestRunnerProcessStartInfoMessageHandler.cs index 08898a8f4..95931d9cd 100644 --- a/src/dotnet/commands/dotnet-test/MessageHandlers/GetTestRunnerProcessStartInfoMessageHandler.cs +++ b/src/dotnet/commands/dotnet-test/MessageHandlers/GetTestRunnerProcessStartInfoMessageHandler.cs @@ -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)); diff --git a/src/dotnet/commands/dotnet-test/MessageHandlers/TestDiscoveryStartMessageHandler.cs b/src/dotnet/commands/dotnet-test/MessageHandlers/TestDiscoveryStartMessageHandler.cs index 941c48c13..bf3976a27 100644 --- a/src/dotnet/commands/dotnet-test/MessageHandlers/TestDiscoveryStartMessageHandler.cs +++ b/src/dotnet/commands/dotnet-test/MessageHandlers/TestDiscoveryStartMessageHandler.cs @@ -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)); diff --git a/src/dotnet/commands/dotnet-test/MessageHandlers/TestMessageTypes.cs b/src/dotnet/commands/dotnet-test/MessageHandlers/TestMessageTypes.cs index a12a62e4f..ce76ccef4 100644 --- a/src/dotnet/commands/dotnet-test/MessageHandlers/TestMessageTypes.cs +++ b/src/dotnet/commands/dotnet-test/MessageHandlers/TestMessageTypes.cs @@ -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"; diff --git a/src/dotnet/commands/dotnet-test/Program.cs b/src/dotnet/commands/dotnet-test/Program.cs index 24d12c11b..1f327b2c3 100644 --- a/src/dotnet/commands/dotnet-test/Program.cs +++ b/src/dotnet/commands/dotnet-test/Program.cs @@ -183,7 +183,7 @@ namespace Microsoft.DotNet.Tools.Test dotnetTest.StartListeningTo(adapterChannel); - adapterChannel.Accept(); + adapterChannel.Connect(); dotnetTest.StartHandlingMessages(); } diff --git a/src/dotnet/commands/dotnet-test/ReportingChannels/AdapterReportingChannel.cs b/src/dotnet/commands/dotnet-test/ReportingChannels/AdapterReportingChannel.cs new file mode 100644 index 000000000..1bf9ffb21 --- /dev/null +++ b/src/dotnet/commands/dotnet-test/ReportingChannels/AdapterReportingChannel.cs @@ -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 + }); + } + } +} diff --git a/src/dotnet/commands/dotnet-test/IReportingChannel.cs b/src/dotnet/commands/dotnet-test/ReportingChannels/IReportingChannel.cs similarity index 95% rename from src/dotnet/commands/dotnet-test/IReportingChannel.cs rename to src/dotnet/commands/dotnet-test/ReportingChannels/IReportingChannel.cs index f103c61e2..0729b4032 100644 --- a/src/dotnet/commands/dotnet-test/IReportingChannel.cs +++ b/src/dotnet/commands/dotnet-test/ReportingChannels/IReportingChannel.cs @@ -13,7 +13,7 @@ namespace Microsoft.DotNet.Tools.Test int Port { get; } - void Accept(); + void Connect(); void Send(Message message); diff --git a/src/dotnet/commands/dotnet-test/IReportingChannelFactory.cs b/src/dotnet/commands/dotnet-test/ReportingChannels/IReportingChannelFactory.cs similarity index 100% rename from src/dotnet/commands/dotnet-test/IReportingChannelFactory.cs rename to src/dotnet/commands/dotnet-test/ReportingChannels/IReportingChannelFactory.cs diff --git a/src/dotnet/commands/dotnet-test/ReportingChannel.cs b/src/dotnet/commands/dotnet-test/ReportingChannels/ReportingChannel.cs similarity index 68% rename from src/dotnet/commands/dotnet-test/ReportingChannel.cs rename to src/dotnet/commands/dotnet-test/ReportingChannels/ReportingChannel.cs index f6a919ace..624e75c32 100644 --- a/src/dotnet/commands/dotnet-test/ReportingChannel.cs +++ b/src/dotnet/commands/dotnet-test/ReportingChannels/ReportingChannel.cs @@ -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 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(); } } } \ No newline at end of file diff --git a/src/dotnet/commands/dotnet-test/ReportingChannelFactory.cs b/src/dotnet/commands/dotnet-test/ReportingChannels/ReportingChannelFactory.cs similarity index 83% rename from src/dotnet/commands/dotnet-test/ReportingChannelFactory.cs rename to src/dotnet/commands/dotnet-test/ReportingChannels/ReportingChannelFactory.cs index f8a5940ea..0ecec58c6 100644 --- a/src/dotnet/commands/dotnet-test/ReportingChannelFactory.cs +++ b/src/dotnet/commands/dotnet-test/ReportingChannels/ReportingChannelFactory.cs @@ -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); } } } diff --git a/src/dotnet/commands/dotnet-test/ReportingChannels/TestRunnerReportingChannel.cs b/src/dotnet/commands/dotnet-test/ReportingChannels/TestRunnerReportingChannel.cs new file mode 100644 index 000000000..204988441 --- /dev/null +++ b/src/dotnet/commands/dotnet-test/ReportingChannels/TestRunnerReportingChannel.cs @@ -0,0 +1,42 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.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(); + } + } +} diff --git a/src/dotnet/project.json b/src/dotnet/project.json index 7938f0157..ed86374d8 100644 --- a/src/dotnet/project.json +++ b/src/dotnet/project.json @@ -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": { diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/DotnetTestCommand.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/DotnetTestCommand.cs new file mode 100644 index 000000000..181bdd97b --- /dev/null +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/DotnetTestCommand.cs @@ -0,0 +1,20 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using 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); + } + } +} diff --git a/test/dotnet-test.Tests/Adapter.cs b/test/dotnet-test.Tests/Adapter.cs new file mode 100644 index 000000000..f4c66fa60 --- /dev/null +++ b/test/dotnet-test.Tests/Adapter.cs @@ -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> Messages { get; } + + public int Port { get; private set; } + + public Adapter(string startMessage) + { + _startMessage = startMessage; + Messages = new Dictionary>(); + + _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()); + } + + 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()); + } + + 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(rawMessage); + return message; + } + + public void Dispose() + { + _socket?.Dispose(); + } + + private class TestStartInfo + { + public string FileName { get; set; } + + public string Arguments { get; set; } + } + } +} \ No newline at end of file diff --git a/test/dotnet-test.Tests/GivenThatWeWantToUseDotnetTestE2EInDesignTime.cs b/test/dotnet-test.Tests/GivenThatWeWantToUseDotnetTestE2EInDesignTime.cs new file mode 100644 index 000000000..5c874ac30 --- /dev/null +++ b/test/dotnet-test.Tests/GivenThatWeWantToUseDotnetTestE2EInDesignTime.cs @@ -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); + } + } + } +} diff --git a/test/dotnet-test.Tests/dotnet-test.Tests.xproj b/test/dotnet-test.Tests/dotnet-test.Tests.xproj new file mode 100644 index 000000000..19adc5ad5 --- /dev/null +++ b/test/dotnet-test.Tests/dotnet-test.Tests.xproj @@ -0,0 +1,18 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 60c33d0a-a5d8-4ab0-9956-1f804654df05 + Microsoft.Dotnet.Tools.Test.Tests + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin + + + 2.0 + + + \ No newline at end of file diff --git a/test/dotnet-test.Tests/project.json b/test/dotnet-test.Tests/project.json new file mode 100644 index 000000000..07eb34c33 --- /dev/null +++ b/test/dotnet-test.Tests/project.json @@ -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" +} diff --git a/test/dotnet-test.UnitTests/GivenATestDiscoveryStartMessageHandler.cs b/test/dotnet-test.UnitTests/GivenATestDiscoveryStartMessageHandler.cs index 971ceeb3b..1c6ea4bbf 100644 --- a/test/dotnet-test.UnitTests/GivenATestDiscoveryStartMessageHandler.cs +++ b/test/dotnet-test.UnitTests/GivenATestDiscoveryStartMessageHandler.cs @@ -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] diff --git a/test/dotnet-test.UnitTests/GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler.cs b/test/dotnet-test.UnitTests/GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler.cs index 24a9942b7..e99271634 100644 --- a/test/dotnet-test.UnitTests/GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler.cs +++ b/test/dotnet-test.UnitTests/GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler.cs @@ -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]