diff --git a/.gitignore b/.gitignore index 3f156e9b9..7a5b1af63 100644 --- a/.gitignore +++ b/.gitignore @@ -277,3 +277,6 @@ test/PackagedCommands/Consumers/*/project.json # Vim swp files *.swp *.*~ + +# VS generated files +launchSettings.json \ No newline at end of file diff --git a/src/Microsoft.DotNet.Cli.Utils/CollectionsExtensions.cs b/src/Microsoft.DotNet.Cli.Utils/CollectionsExtensions.cs new file mode 100644 index 000000000..575ee62ba --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/CollectionsExtensions.cs @@ -0,0 +1,18 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.DotNet.Cli.Utils +{ + public static class CollectionsExtensions + { + public static IEnumerable OrEmptyIfNull(this IEnumerable enumerable) + { + return enumerable == null + ? Enumerable.Empty() + : enumerable; + } + } +} diff --git a/src/dotnet/commands/dotnet-test/DotnetTest.cs b/src/dotnet/commands/dotnet-test/DotnetTest.cs index ab895d248..b684fce1b 100644 --- a/src/dotnet/commands/dotnet-test/DotnetTest.cs +++ b/src/dotnet/commands/dotnet-test/DotnetTest.cs @@ -20,6 +20,8 @@ namespace Microsoft.DotNet.Tools.Test public string PathToAssemblyUnderTest { get; } + public IEnumerable TestsToRun { get; set; } + public DotnetTest(ITestMessagesCollection messages, string pathToAssemblyUnderTest) { PathToAssemblyUnderTest = pathToAssemblyUnderTest; diff --git a/src/dotnet/commands/dotnet-test/DotnetTestExtensions.cs b/src/dotnet/commands/dotnet-test/DotnetTestExtensions.cs index 9a173cb0a..0e4c17b74 100644 --- a/src/dotnet/commands/dotnet-test/DotnetTestExtensions.cs +++ b/src/dotnet/commands/dotnet-test/DotnetTestExtensions.cs @@ -48,12 +48,14 @@ namespace Microsoft.DotNet.Tools.Test public static IDotnetTest AddTestRunnnersMessageHandlers( this IDotnetTest dotnetTest, - IReportingChannel adapterChannel) + IReportingChannel adapterChannel, + IReportingChannelFactory reportingChannelFactory) { dotnetTest.AddMessageHandler(new TestRunnerTestStartedMessageHandler(adapterChannel)); dotnetTest.AddMessageHandler(new TestRunnerTestResultMessageHandler(adapterChannel)); dotnetTest.AddMessageHandler(new TestRunnerTestFoundMessageHandler(adapterChannel)); dotnetTest.AddMessageHandler(new TestRunnerTestCompletedMessageHandler(adapterChannel)); + dotnetTest.AddMessageHandler(new TestRunnerWaitingCommandMessageHandler(reportingChannelFactory)); return dotnetTest; } diff --git a/src/dotnet/commands/dotnet-test/IDotnetTest.cs b/src/dotnet/commands/dotnet-test/IDotnetTest.cs index 3d0386b8a..1cf7350f4 100644 --- a/src/dotnet/commands/dotnet-test/IDotnetTest.cs +++ b/src/dotnet/commands/dotnet-test/IDotnetTest.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; +using System.Collections.Generic; namespace Microsoft.DotNet.Tools.Test { @@ -17,6 +18,8 @@ namespace Microsoft.DotNet.Tools.Test IDotnetTestMessageHandler UnknownMessageHandler { set; } + IEnumerable TestsToRun { get; set; } + void StartHandlingMessages(); void StartListeningTo(IReportingChannel reportingChannel); diff --git a/src/dotnet/commands/dotnet-test/IReportingChannelFactory.cs b/src/dotnet/commands/dotnet-test/IReportingChannelFactory.cs index a1e7274e1..2f35fffd2 100644 --- a/src/dotnet/commands/dotnet-test/IReportingChannelFactory.cs +++ b/src/dotnet/commands/dotnet-test/IReportingChannelFactory.cs @@ -1,12 +1,16 @@ // 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; + namespace Microsoft.DotNet.Tools.Test { public interface IReportingChannelFactory { - IReportingChannel CreateChannelWithAnyAvailablePort(); + event EventHandler TestRunnerChannelCreated; - IReportingChannel CreateChannelWithPort(int port); + IReportingChannel CreateTestRunnerChannel(); + + IReportingChannel CreateAdapterChannel(int port); } } diff --git a/src/dotnet/commands/dotnet-test/MessageHandlers/GetTestRunnerProcessStartInfoMessageHandler.cs b/src/dotnet/commands/dotnet-test/MessageHandlers/GetTestRunnerProcessStartInfoMessageHandler.cs index 17ed2092f..08898a8f4 100644 --- a/src/dotnet/commands/dotnet-test/MessageHandlers/GetTestRunnerProcessStartInfoMessageHandler.cs +++ b/src/dotnet/commands/dotnet-test/MessageHandlers/GetTestRunnerProcessStartInfoMessageHandler.cs @@ -37,7 +37,7 @@ namespace Microsoft.DotNet.Tools.Test private void DoHandleMessage(IDotnetTest dotnetTest, Message message) { - var testRunnerChannel = _reportingChannelFactory.CreateChannelWithAnyAvailablePort(); + var testRunnerChannel = _reportingChannelFactory.CreateTestRunnerChannel(); dotnetTest.StartListeningTo(testRunnerChannel); @@ -46,6 +46,8 @@ namespace Microsoft.DotNet.Tools.Test var testRunner = _testRunnerFactory.CreateTestRunner( new RunTestsArgumentsBuilder(dotnetTest.PathToAssemblyUnderTest, testRunnerChannel.Port, message)); + dotnetTest.TestsToRun = message.Payload?.ToObject().Tests; + var processStartInfo = testRunner.GetProcessStartInfo(); _adapterChannel.Send(new Message diff --git a/src/dotnet/commands/dotnet-test/MessageHandlers/TestDiscoveryStartMessageHandler.cs b/src/dotnet/commands/dotnet-test/MessageHandlers/TestDiscoveryStartMessageHandler.cs index c6dcef258..941c48c13 100644 --- a/src/dotnet/commands/dotnet-test/MessageHandlers/TestDiscoveryStartMessageHandler.cs +++ b/src/dotnet/commands/dotnet-test/MessageHandlers/TestDiscoveryStartMessageHandler.cs @@ -51,7 +51,7 @@ namespace Microsoft.DotNet.Cli.Tools.Test try { - var testRunnerChannel = _reportingChannelFactory.CreateChannelWithAnyAvailablePort(); + var testRunnerChannel = _reportingChannelFactory.CreateTestRunnerChannel(); dotnetTest.StartListeningTo(testRunnerChannel); diff --git a/src/dotnet/commands/dotnet-test/MessageHandlers/TestMessageTypes.cs b/src/dotnet/commands/dotnet-test/MessageHandlers/TestMessageTypes.cs index 1cf24c941..a12a62e4f 100644 --- a/src/dotnet/commands/dotnet-test/MessageHandlers/TestMessageTypes.cs +++ b/src/dotnet/commands/dotnet-test/MessageHandlers/TestMessageTypes.cs @@ -5,6 +5,8 @@ namespace Microsoft.DotNet.Tools.Test { public static class TestMessageTypes { + public const string TestRunnerExecute = "TestRunner.Execute"; + public const string TestRunnerWaitingCommand = "TestRunner.WaitingCommand"; public const string TestRunnerTestResult = "TestExecution.TestResult"; public const string TestRunnerTestStarted = "TestExecution.TestStarted"; public const string TestRunnerTestCompleted = "TestRunner.TestCompleted"; diff --git a/src/dotnet/commands/dotnet-test/MessageHandlers/TestRunnerWaitingCommandMessageHandler.cs b/src/dotnet/commands/dotnet-test/MessageHandlers/TestRunnerWaitingCommandMessageHandler.cs new file mode 100644 index 000000000..8f05566be --- /dev/null +++ b/src/dotnet/commands/dotnet-test/MessageHandlers/TestRunnerWaitingCommandMessageHandler.cs @@ -0,0 +1,73 @@ +// 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 Microsoft.Extensions.Testing.Abstractions; +using Newtonsoft.Json.Linq; +using Microsoft.DotNet.Cli.Utils; + +namespace Microsoft.DotNet.Tools.Test +{ + public class TestRunnerWaitingCommandMessageHandler : IDotnetTestMessageHandler + { + private readonly IReportingChannelFactory _reportingChannelFactory; + private IReportingChannel _testRunnerChannel; + + public TestRunnerWaitingCommandMessageHandler(IReportingChannelFactory reportingChannelFactory) + { + _reportingChannelFactory = reportingChannelFactory; + + _reportingChannelFactory.TestRunnerChannelCreated += OnTestRunnerChannelCreated; + } + + public DotnetTestState HandleMessage(IDotnetTest dotnetTest, Message message) + { + var nextState = DotnetTestState.NoOp; + + if (CanHandleMessage(dotnetTest, message)) + { + HandleMessage(dotnetTest); + nextState = DotnetTestState.TestExecutionSentTestRunnerProcessStartInfo; + } + + return nextState; + } + + private void HandleMessage(IDotnetTest dotnetTest) + { + if (_testRunnerChannel == null) + { + const string errorMessage = + "A test runner channel hasn't been created for TestRunnerWaitingCommandMessageHandler"; + throw new InvalidOperationException(errorMessage); + } + + _testRunnerChannel.Send(new Message + { + MessageType = TestMessageTypes.TestRunnerExecute, + Payload = JToken.FromObject(new RunTestsMessage + { + Tests = new List(dotnetTest.TestsToRun.OrEmptyIfNull()) + }) + }); + } + + private void OnTestRunnerChannelCreated(object sender, IReportingChannel testRunnerChannel) + { + if (_testRunnerChannel != null) + { + const string errorMessage = "TestRunnerWaitingCommandMessageHandler already has a test runner channel"; + throw new InvalidOperationException(errorMessage); + } + + _testRunnerChannel = testRunnerChannel; + } + + private static bool CanHandleMessage(IDotnetTest dotnetTest, Message message) + { + return dotnetTest.State == DotnetTestState.TestExecutionSentTestRunnerProcessStartInfo && + message.MessageType == TestMessageTypes.TestRunnerWaitingCommand; + } + } +} diff --git a/src/dotnet/commands/dotnet-test/Program.cs b/src/dotnet/commands/dotnet-test/Program.cs index bafe2e85b..7d9eed583 100644 --- a/src/dotnet/commands/dotnet-test/Program.cs +++ b/src/dotnet/commands/dotnet-test/Program.cs @@ -151,7 +151,7 @@ namespace Microsoft.DotNet.Tools.Test string outputPath) { var reportingChannelFactory = new ReportingChannelFactory(); - var adapterChannel = reportingChannelFactory.CreateChannelWithPort(port); + var adapterChannel = reportingChannelFactory.CreateAdapterChannel(port); try { @@ -159,7 +159,7 @@ namespace Microsoft.DotNet.Tools.Test var messages = new TestMessagesCollection(); using (var dotnetTest = new DotnetTest(messages, assemblyUnderTest)) { - var commandFactory = + var commandFactory = new FixedPathCommandFactory(projectContext.TargetFramework, configuration, outputPath); var testRunnerFactory = new TestRunnerFactory(GetCommandName(testRunner), commandFactory); @@ -167,7 +167,7 @@ namespace Microsoft.DotNet.Tools.Test .AddNonSpecificMessageHandlers(messages, adapterChannel) .AddTestDiscoveryMessageHandlers(adapterChannel, reportingChannelFactory, testRunnerFactory) .AddTestRunMessageHandlers(adapterChannel, reportingChannelFactory, testRunnerFactory) - .AddTestRunnnersMessageHandlers(adapterChannel); + .AddTestRunnnersMessageHandlers(adapterChannel, reportingChannelFactory); dotnetTest.StartListeningTo(adapterChannel); diff --git a/src/dotnet/commands/dotnet-test/ReportingChannelFactory.cs b/src/dotnet/commands/dotnet-test/ReportingChannelFactory.cs index 0dac24eba..f8a5940ea 100644 --- a/src/dotnet/commands/dotnet-test/ReportingChannelFactory.cs +++ b/src/dotnet/commands/dotnet-test/ReportingChannelFactory.cs @@ -1,16 +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; + namespace Microsoft.DotNet.Tools.Test { public class ReportingChannelFactory : IReportingChannelFactory { - public IReportingChannel CreateChannelWithAnyAvailablePort() + public event EventHandler TestRunnerChannelCreated; + + public IReportingChannel CreateTestRunnerChannel() { - return ReportingChannel.ListenOn(0); + var testRunnerChannel = ReportingChannel.ListenOn(0); + + TestRunnerChannelCreated?.Invoke(this, testRunnerChannel); + + return testRunnerChannel; } - public IReportingChannel CreateChannelWithPort(int port) + public IReportingChannel CreateAdapterChannel(int port) { return ReportingChannel.ListenOn(port); } diff --git a/src/dotnet/commands/dotnet-test/TestRunners/RunTestsArgumentsBuilder.cs b/src/dotnet/commands/dotnet-test/TestRunners/RunTestsArgumentsBuilder.cs index 4397731f4..7a2c86f4f 100644 --- a/src/dotnet/commands/dotnet-test/TestRunners/RunTestsArgumentsBuilder.cs +++ b/src/dotnet/commands/dotnet-test/TestRunners/RunTestsArgumentsBuilder.cs @@ -26,19 +26,10 @@ namespace Microsoft.DotNet.Tools.Test _assemblyUnderTest, "--designtime", "--port", - $"{_port}" + $"{_port}", + "--wait-command" }; - var tests = _message.Payload?.ToObject().Tests; - if (tests != null) - { - foreach (var test in tests) - { - commandArgs.Add("--test"); - commandArgs.Add(test); - } - } - return commandArgs; } } diff --git a/test/dotnet-test.UnitTests/DotnetTestMessageScenario.cs b/test/dotnet-test.UnitTests/DotnetTestMessageScenario.cs index 975ccdf38..775d45884 100644 --- a/test/dotnet-test.UnitTests/DotnetTestMessageScenario.cs +++ b/test/dotnet-test.UnitTests/DotnetTestMessageScenario.cs @@ -31,8 +31,11 @@ namespace Microsoft.Dotnet.Tools.Test.Tests { var reportingChannelFactoryMock = new Mock(); reportingChannelFactoryMock - .Setup(r => r.CreateChannelWithAnyAvailablePort()) - .Returns(TestRunnerChannelMock.Object); + .Setup(r => r.CreateTestRunnerChannel()) + .Returns(TestRunnerChannelMock.Object) + .Raises( + r => r.TestRunnerChannelCreated += null, + reportingChannelFactoryMock.Object, TestRunnerChannelMock.Object); var commandFactoryMock = new Mock(); @@ -56,7 +59,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests .AddNonSpecificMessageHandlers(_messages, adapterChannel) .AddTestDiscoveryMessageHandlers(adapterChannel, reportingChannelFactory, testRunnerFactory) .AddTestRunMessageHandlers(adapterChannel, reportingChannelFactory, testRunnerFactory) - .AddTestRunnnersMessageHandlers(adapterChannel); + .AddTestRunnnersMessageHandlers(adapterChannel, reportingChannelFactory); DotnetTestUnderTest.StartListeningTo(adapterChannel); diff --git a/test/dotnet-test.UnitTests/GivenARunTestsArgumentsBuilder.cs b/test/dotnet-test.UnitTests/GivenARunTestsArgumentsBuilder.cs index 31d2f8de8..396ca0a06 100644 --- a/test/dotnet-test.UnitTests/GivenARunTestsArgumentsBuilder.cs +++ b/test/dotnet-test.UnitTests/GivenARunTestsArgumentsBuilder.cs @@ -32,10 +32,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests "--designtime", "--port", $"{port}", - "--test", - "test1", - "--test", - "test2"); + "--wait-command"); } } } diff --git a/test/dotnet-test.UnitTests/GivenATestDiscoveryStartMessageHandler.cs b/test/dotnet-test.UnitTests/GivenATestDiscoveryStartMessageHandler.cs index d70242130..971ceeb3b 100644 --- a/test/dotnet-test.UnitTests/GivenATestDiscoveryStartMessageHandler.cs +++ b/test/dotnet-test.UnitTests/GivenATestDiscoveryStartMessageHandler.cs @@ -47,7 +47,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests _reportingChannelFactoryMock = new Mock(); _reportingChannelFactoryMock.Setup(r => - r.CreateChannelWithAnyAvailablePort()).Returns(_testRunnerChannelMock.Object); + r.CreateTestRunnerChannel()).Returns(_testRunnerChannelMock.Object); _testDiscoveryStartMessageHandler = new TestDiscoveryStartMessageHandler( _testRunnerFactoryMock.Object, @@ -131,7 +131,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests _dotnetTestMock.Object, _validMessage); - _reportingChannelFactoryMock.Verify(r => r.CreateChannelWithAnyAvailablePort(), Times.Once); + _reportingChannelFactoryMock.Verify(r => r.CreateTestRunnerChannel(), Times.Once); } [Fact] diff --git a/test/dotnet-test.UnitTests/GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler.cs b/test/dotnet-test.UnitTests/GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler.cs index 58ae38211..24a9942b7 100644 --- a/test/dotnet-test.UnitTests/GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler.cs +++ b/test/dotnet-test.UnitTests/GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler.cs @@ -20,6 +20,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests private GetTestRunnerProcessStartInfoMessageHandler _testGetTestRunnerProcessStartInfoMessageHandler; private Message _validMessage; private TestStartInfo _testStartInfo; + private List _testsToRun; private Mock _testRunnerMock; private Mock _testRunnerFactoryMock; @@ -32,10 +33,11 @@ namespace Microsoft.Dotnet.Tools.Test.Tests public GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler() { + _testsToRun = new List {"test1", "test2"}; _validMessage = new Message { MessageType = TestMessageTypes.TestExecutionGetTestRunnerProcessStartInfo, - Payload = JToken.FromObject(new RunTestsMessage { Tests = new List { "test1", "test2" } }) + Payload = JToken.FromObject(new RunTestsMessage { Tests = _testsToRun }) }; _dotnetTestMock = new Mock(); @@ -63,7 +65,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests _reportingChannelFactoryMock = new Mock(); _reportingChannelFactoryMock.Setup(r => - r.CreateChannelWithAnyAvailablePort()).Returns(_testRunnerChannelMock.Object); + r.CreateTestRunnerChannel()).Returns(_testRunnerChannelMock.Object); _testGetTestRunnerProcessStartInfoMessageHandler = new GetTestRunnerProcessStartInfoMessageHandler( _testRunnerFactoryMock.Object, @@ -149,7 +151,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests _dotnetTestMock.Object, _validMessage); - _reportingChannelFactoryMock.Verify(r => r.CreateChannelWithAnyAvailablePort(), Times.Once); + _reportingChannelFactoryMock.Verify(r => r.CreateTestRunnerChannel(), Times.Once); } [Fact] @@ -172,6 +174,16 @@ namespace Microsoft.Dotnet.Tools.Test.Tests _dotnetTestMock.Verify(d => d.StartListeningTo(_testRunnerChannelMock.Object), Times.Once); } + [Fact] + public void It_sets_the_TestsToRun_of_DotnetTest() + { + _testGetTestRunnerProcessStartInfoMessageHandler.HandleMessage( + _dotnetTestMock.Object, + _validMessage); + + _dotnetTestMock.VerifySet(d => d.TestsToRun = _testsToRun); + } + [Fact] public void It_passes_the_right_arguments_to_the_run_tests_arguments_builder() { @@ -185,8 +197,6 @@ namespace Microsoft.Dotnet.Tools.Test.Tests arguments.Should().Contain("--port", $"{TestRunnerPort}"); arguments.Should().Contain($"{AssemblyUnderTest}"); - arguments.Should().Contain("--test", "test1"); - arguments.Should().Contain("--test", "test2"); } } } diff --git a/test/dotnet-test.UnitTests/GivenATestRunnerWaitingCommandMessageHandler.cs b/test/dotnet-test.UnitTests/GivenATestRunnerWaitingCommandMessageHandler.cs new file mode 100644 index 000000000..e44e4ed8f --- /dev/null +++ b/test/dotnet-test.UnitTests/GivenATestRunnerWaitingCommandMessageHandler.cs @@ -0,0 +1,145 @@ +// 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 FluentAssertions; +using Microsoft.DotNet.Tools.Test; +using Microsoft.Extensions.Testing.Abstractions; +using Moq; +using Xunit; +using System.Linq; + +namespace Microsoft.Dotnet.Tools.Test.Tests +{ + public class GivenATestRunnerWaitingCommandMessageHandler + { + private Mock _dotnetTestMock; + private Mock _testRunnerChannelMock; + private Mock _reportingChannelFactory; + private List _testsToRun; + + private Message _validMessage; + private TestRunnerWaitingCommandMessageHandler _testRunnerWaitingCommandMessageHandler; + + public GivenATestRunnerWaitingCommandMessageHandler() + { + _testsToRun = new List { "test1", "test2" }; + _dotnetTestMock = new Mock(); + _dotnetTestMock.Setup(d => d.State).Returns(DotnetTestState.TestExecutionSentTestRunnerProcessStartInfo); + _dotnetTestMock.Setup(d => d.TestsToRun).Returns(_testsToRun); + + _validMessage = new Message + { + MessageType = TestMessageTypes.TestRunnerWaitingCommand + }; + + _testRunnerChannelMock = new Mock(); + _reportingChannelFactory = new Mock(); + + _testRunnerWaitingCommandMessageHandler = + new TestRunnerWaitingCommandMessageHandler(_reportingChannelFactory.Object); + } + + [Fact] + public void It_returns_NoOp_if_the_dotnet_test_state_is_not_TestExecutionSentTestRunnerProcessStartInfo_or_TestExecutionTestStarted() + { + var dotnetTestMock = new Mock(); + dotnetTestMock.Setup(d => d.State).Returns(DotnetTestState.Terminated); + + var nextState = _testRunnerWaitingCommandMessageHandler.HandleMessage( + dotnetTestMock.Object, + _validMessage); + + nextState.Should().Be(DotnetTestState.NoOp); + } + + [Fact] + public void It_returns_NoOp_if_the_message_is_not_TestRunnerWaitingCommand() + { + var nextState = _testRunnerWaitingCommandMessageHandler.HandleMessage( + _dotnetTestMock.Object, + new Message { MessageType = "Something different from TestRunner.WaitingCommand" }); + + nextState.Should().Be(DotnetTestState.NoOp); + } + + [Fact] + public void It_returns_TestExecutionSentTestRunnerProcessStartInfo_when_it_handles_the_message() + { + _reportingChannelFactory.Raise( + r => r.TestRunnerChannelCreated += null, + _reportingChannelFactory.Object, _testRunnerChannelMock.Object); + + var nextState = _testRunnerWaitingCommandMessageHandler.HandleMessage( + _dotnetTestMock.Object, + _validMessage); + + nextState.Should().Be(DotnetTestState.TestExecutionSentTestRunnerProcessStartInfo); + } + + [Fact] + public void It_sends_a_TestRunnerExecute_when_it_handles_the_message() + { + _reportingChannelFactory.Raise( + r => r.TestRunnerChannelCreated += null, + _reportingChannelFactory.Object, _testRunnerChannelMock.Object); + + _testRunnerChannelMock + .Setup(a => a.Send(It.Is(m => m.MessageType == TestMessageTypes.TestRunnerExecute))) + .Verifiable(); + + _testRunnerWaitingCommandMessageHandler.HandleMessage( + _dotnetTestMock.Object, + _validMessage); + + _testRunnerChannelMock.Verify(); + } + + [Fact] + public void It_sends_a_the_list_of_tests_to_run_when_it_handles_the_message() + { + _testRunnerChannelMock.Setup(a => a.Send(It.Is(m => + m.MessageType == TestMessageTypes.TestRunnerExecute && + m.Payload.ToObject().Tests.All(t => _testsToRun.Contains(t)) && + m.Payload.ToObject().Tests.Count == _testsToRun.Count))).Verifiable(); + + _reportingChannelFactory.Raise( + r => r.TestRunnerChannelCreated += null, + _reportingChannelFactory.Object, _testRunnerChannelMock.Object); + + _testRunnerWaitingCommandMessageHandler.HandleMessage( + _dotnetTestMock.Object, + _validMessage); + + _testRunnerChannelMock.Verify(); + } + + [Fact] + public void It_throws_InvalidOperationException_when_a_second_test_runner_channel_gets_created() + { + _reportingChannelFactory.Raise( + r => r.TestRunnerChannelCreated += null, + _reportingChannelFactory.Object, _testRunnerChannelMock.Object); + + Action action = () => _reportingChannelFactory.Raise( + r => r.TestRunnerChannelCreated += null, + _reportingChannelFactory.Object, _testRunnerChannelMock.Object); + + const string errorMessage = "TestRunnerWaitingCommandMessageHandler already has a test runner channel"; + action.ShouldThrow().WithMessage(errorMessage); + } + + [Fact] + public void It_throws_InvalidOperationException_when_no_test_runner_channel_has_been_created() + { + Action action = () => _testRunnerWaitingCommandMessageHandler.HandleMessage( + _dotnetTestMock.Object, + _validMessage); + + const string errorMessage = + "A test runner channel hasn't been created for TestRunnerWaitingCommandMessageHandler"; + action.ShouldThrow().WithMessage(errorMessage); + } + } +} diff --git a/test/dotnet-test.UnitTests/GivenThatWeWantToRunTests.cs b/test/dotnet-test.UnitTests/GivenThatWeWantToRunTests.cs index 7059bc128..156851f0b 100644 --- a/test/dotnet-test.UnitTests/GivenThatWeWantToRunTests.cs +++ b/test/dotnet-test.UnitTests/GivenThatWeWantToRunTests.cs @@ -36,6 +36,18 @@ namespace Microsoft.Dotnet.Tools.Test.Tests dotnetTestMessageScenario.AdapterChannelMock .Setup(a => a.Send( It.Is(m => m.MessageType == TestMessageTypes.TestExecutionTestRunnerProcessStartInfo))) + .Callback(() => dotnetTestMessageScenario.TestRunnerChannelMock.Raise( + t => t.MessageReceived += null, + dotnetTestMessageScenario.DotnetTestUnderTest, + new Message + { + MessageType = TestMessageTypes.TestRunnerWaitingCommand + })) + .Verifiable(); + + dotnetTestMessageScenario.TestRunnerChannelMock + .Setup(a => a.Send( + It.Is(m => m.MessageType == TestMessageTypes.TestRunnerExecute))) .Callback(() => dotnetTestMessageScenario.TestRunnerChannelMock.Raise( t => t.MessageReceived += null, dotnetTestMessageScenario.DotnetTestUnderTest,