Merge branch 'rel/1.0.0' of https://github.com/dotnet/cli into build-refactor1

This commit is contained in:
Sridhar Periyasamy 2016-03-07 14:22:02 -08:00
commit 0f679e68bf
19 changed files with 311 additions and 36 deletions

3
.gitignore vendored
View file

@ -277,3 +277,6 @@ test/PackagedCommands/Consumers/*/project.json
# Vim swp files
*.swp
*.*~
# VS generated files
launchSettings.json

View file

@ -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<T> OrEmptyIfNull<T>(this IEnumerable<T> enumerable)
{
return enumerable == null
? Enumerable.Empty<T>()
: enumerable;
}
}
}

View file

@ -20,6 +20,8 @@ namespace Microsoft.DotNet.Tools.Test
public string PathToAssemblyUnderTest { get; }
public IEnumerable<string> TestsToRun { get; set; }
public DotnetTest(ITestMessagesCollection messages, string pathToAssemblyUnderTest)
{
PathToAssemblyUnderTest = pathToAssemblyUnderTest;

View file

@ -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;
}

View file

@ -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<string> TestsToRun { get; set; }
void StartHandlingMessages();
void StartListeningTo(IReportingChannel reportingChannel);

View file

@ -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<IReportingChannel> TestRunnerChannelCreated;
IReportingChannel CreateChannelWithPort(int port);
IReportingChannel CreateTestRunnerChannel();
IReportingChannel CreateAdapterChannel(int port);
}
}

View file

@ -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<RunTestsMessage>().Tests;
var processStartInfo = testRunner.GetProcessStartInfo();
_adapterChannel.Send(new Message

View file

@ -51,7 +51,7 @@ namespace Microsoft.DotNet.Cli.Tools.Test
try
{
var testRunnerChannel = _reportingChannelFactory.CreateChannelWithAnyAvailablePort();
var testRunnerChannel = _reportingChannelFactory.CreateTestRunnerChannel();
dotnetTest.StartListeningTo(testRunnerChannel);

View file

@ -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";

View file

@ -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<string>(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;
}
}
}

View file

@ -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);

View file

@ -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<IReportingChannel> 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);
}

View file

@ -26,19 +26,10 @@ namespace Microsoft.DotNet.Tools.Test
_assemblyUnderTest,
"--designtime",
"--port",
$"{_port}"
$"{_port}",
"--wait-command"
};
var tests = _message.Payload?.ToObject<RunTestsMessage>().Tests;
if (tests != null)
{
foreach (var test in tests)
{
commandArgs.Add("--test");
commandArgs.Add(test);
}
}
return commandArgs;
}
}

View file

@ -31,8 +31,11 @@ namespace Microsoft.Dotnet.Tools.Test.Tests
{
var reportingChannelFactoryMock = new Mock<IReportingChannelFactory>();
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<ICommandFactory>();
@ -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);

View file

@ -32,10 +32,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests
"--designtime",
"--port",
$"{port}",
"--test",
"test1",
"--test",
"test2");
"--wait-command");
}
}
}

View file

@ -47,7 +47,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests
_reportingChannelFactoryMock = new Mock<IReportingChannelFactory>();
_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]

View file

@ -20,6 +20,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests
private GetTestRunnerProcessStartInfoMessageHandler _testGetTestRunnerProcessStartInfoMessageHandler;
private Message _validMessage;
private TestStartInfo _testStartInfo;
private List<string> _testsToRun;
private Mock<ITestRunner> _testRunnerMock;
private Mock<ITestRunnerFactory> _testRunnerFactoryMock;
@ -32,10 +33,11 @@ namespace Microsoft.Dotnet.Tools.Test.Tests
public GivenATestExecutionGetTestRunnerProcessStartInfoMessageHandler()
{
_testsToRun = new List<string> {"test1", "test2"};
_validMessage = new Message
{
MessageType = TestMessageTypes.TestExecutionGetTestRunnerProcessStartInfo,
Payload = JToken.FromObject(new RunTestsMessage { Tests = new List<string> { "test1", "test2" } })
Payload = JToken.FromObject(new RunTestsMessage { Tests = _testsToRun })
};
_dotnetTestMock = new Mock<IDotnetTest>();
@ -63,7 +65,7 @@ namespace Microsoft.Dotnet.Tools.Test.Tests
_reportingChannelFactoryMock = new Mock<IReportingChannelFactory>();
_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");
}
}
}

View file

@ -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<IDotnetTest> _dotnetTestMock;
private Mock<IReportingChannel> _testRunnerChannelMock;
private Mock<IReportingChannelFactory> _reportingChannelFactory;
private List<string> _testsToRun;
private Message _validMessage;
private TestRunnerWaitingCommandMessageHandler _testRunnerWaitingCommandMessageHandler;
public GivenATestRunnerWaitingCommandMessageHandler()
{
_testsToRun = new List<string> { "test1", "test2" };
_dotnetTestMock = new Mock<IDotnetTest>();
_dotnetTestMock.Setup(d => d.State).Returns(DotnetTestState.TestExecutionSentTestRunnerProcessStartInfo);
_dotnetTestMock.Setup(d => d.TestsToRun).Returns(_testsToRun);
_validMessage = new Message
{
MessageType = TestMessageTypes.TestRunnerWaitingCommand
};
_testRunnerChannelMock = new Mock<IReportingChannel>();
_reportingChannelFactory = new Mock<IReportingChannelFactory>();
_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<IDotnetTest>();
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<Message>(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<Message>(m =>
m.MessageType == TestMessageTypes.TestRunnerExecute &&
m.Payload.ToObject<RunTestsMessage>().Tests.All(t => _testsToRun.Contains(t)) &&
m.Payload.ToObject<RunTestsMessage>().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<InvalidOperationException>().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<InvalidOperationException>().WithMessage(errorMessage);
}
}
}

View file

@ -36,6 +36,18 @@ namespace Microsoft.Dotnet.Tools.Test.Tests
dotnetTestMessageScenario.AdapterChannelMock
.Setup(a => a.Send(
It.Is<Message>(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<Message>(m => m.MessageType == TestMessageTypes.TestRunnerExecute)))
.Callback(() => dotnetTestMessageScenario.TestRunnerChannelMock.Raise(
t => t.MessageReceived += null,
dotnetTestMessageScenario.DotnetTestUnderTest,