Skip to content

Commit

Permalink
Fixed CC for in-process console scenarios (#4084)
Browse files Browse the repository at this point in the history
  • Loading branch information
cvpoienaru authored Oct 25, 2022
1 parent c8a97d9 commit f229b1a
Show file tree
Hide file tree
Showing 2 changed files with 241 additions and 3 deletions.
52 changes: 50 additions & 2 deletions src/vstest.console/InProcessVsTestConsoleWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -830,7 +830,7 @@ await ProcessTestRunAttachmentsAsync(
}

/// <inheritdoc/>
public Task ProcessTestRunAttachmentsAsync(
public async Task ProcessTestRunAttachmentsAsync(
IEnumerable<AttachmentSet> attachments,
IEnumerable<InvokedDataCollector>? invokedDataCollectors,
string? processingSettings,
Expand All @@ -839,7 +839,55 @@ public Task ProcessTestRunAttachmentsAsync(
ITestRunAttachmentsProcessingEventsHandler eventsHandler,
CancellationToken cancellationToken)
{
throw new NotImplementedException();
_testPlatformEventSource.TranslationLayerTestRunAttachmentsProcessingStart();

try
{
var attachmentProcessingPayload = new TestRunAttachmentsProcessingPayload
{
Attachments = attachments,
InvokedDataCollectors = invokedDataCollectors,
RunSettings = processingSettings,
CollectMetrics = collectMetrics
};

using (cancellationToken.Register(() =>
TestRequestManager?.CancelTestRunAttachmentsProcessing()))
{
// Awaiting the attachment processing task here. The implementation of the
// underlying operation guarantees the event handler is called when processing
// is complete, so when awaiting ends, the results have already been passed to
// the caller via the event handler. No need for further synchronization.
//
// NOTE: We're passing in CancellationToken.None and that is by design, *DO NOT*
// attempt to optimize this code by passing in the cancellation token registered
// above. Passing in the said token would result in potentially leaving the caller
// hanging when the token is signaled before even starting the test run attachment
// processing. In this scenario, the Task.Run should not even run in the first
// place, and as such the event handler that signals processing is complete will
// not be triggered anymore.
await Task.Run(() =>
TestRequestManager?.ProcessTestRunAttachments(
attachmentProcessingPayload,
eventsHandler,
new ProtocolConfig { Version = _highestSupportedVersion }),
CancellationToken.None)
.ConfigureAwait(false);
}
}
catch (Exception ex)
{
EqtTrace.Error("InProcessVsTestConsoleWrapper.ProcessTestRunAttachmentsAsync: Exception occurred: " + ex);

var attachmentsProcessingArgs = new TestRunAttachmentsProcessingCompleteEventArgs(
isCanceled: cancellationToken.IsCancellationRequested,
ex);

eventsHandler.HandleLogMessage(TestMessageLevel.Error, ex.ToString());
eventsHandler.HandleTestRunAttachmentsProcessingComplete(attachmentsProcessingArgs, lastChunk: null);
}

_testPlatformEventSource.TranslationLayerTestRunAttachmentsProcessingStop();
}

/// <inheritdoc/>
Expand Down
192 changes: 191 additions & 1 deletion test/vstest.console.UnitTests/InProcessVsTestConsoleWrapperTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

using Microsoft.TestPlatform.VsTestConsole.TranslationLayer;
using Microsoft.TestPlatform.VsTestConsole.TranslationLayer.Interfaces;
Expand All @@ -15,13 +17,14 @@
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.Interfaces;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.Payloads;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;
using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions;
using Microsoft.VisualStudio.TestPlatform.Utilities;
using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using FluentAssertions;
using Moq;
using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces;

namespace Microsoft.VisualStudio.TestPlatform.CommandLine.UnitTests;

Expand All @@ -38,6 +41,17 @@ public class InProcessVsTestConsoleWrapperTests

private readonly IList<string> _testSources = new List<String>() { "test1", "test2" };
private readonly IList<TestCase> _testCases = new List<TestCase>() { new TestCase(), new TestCase() };
private readonly IList<AttachmentSet> _attachmentSets = new List<AttachmentSet>()
{
new AttachmentSet(new Uri("datacollector://AttachmentSetDataCollector1"), "AttachmentSet1"),
new AttachmentSet(new Uri("datacollector://AttachmentSetDataCollector2"), "AttachmentSet2"),
};
private readonly IList<InvokedDataCollector> _invokedDataCollectors = new List<InvokedDataCollector>()
{
new InvokedDataCollector(new Uri("datacollector://InvokedDataCollector1"), "InvokedDataCollector1", "DummyAssemblyName1", "DummyFilePath1", true),
new InvokedDataCollector(new Uri("datacollector://InvokedDataCollector2"), "InvokedDataCollector2", "DummyAssemblyName2", "DummyFilePath2", false),
};

private readonly string _runSettings = "dummy runsettings";

public InProcessVsTestConsoleWrapperTests()
Expand Down Expand Up @@ -849,4 +863,180 @@ public void InProcessWrapperStartTestSessionSucceedsWhenNoExceptionIsThrown()
mockTestSessionEventsHandler.Verify(eh => eh.HandleStartTestSessionComplete(startTestSessionCompleteArgs), Times.Once);
mockTestSessionEventsHandler.Verify(eh => eh.HandleStopTestSessionComplete(stopTestSessionCompleteArgs), Times.Once);
}

[TestMethod]
public async Task InProcessWrapperProcessTestRunAttachmentsAsyncWithSevenParamsIsSuccessfullyInvoked()
{
var attachmentsEventHandler = new Mock<ITestRunAttachmentsProcessingEventsHandler>();

TestRunAttachmentsProcessingPayload? payload = null;
_mockTestRequestManager
.Setup(trm => trm.ProcessTestRunAttachments(
It.IsAny<TestRunAttachmentsProcessingPayload>(),
It.IsAny<ITestRunAttachmentsProcessingEventsHandler>(),
It.IsAny<ProtocolConfig>()))
.Callback((
TestRunAttachmentsProcessingPayload p,
ITestRunAttachmentsProcessingEventsHandler _,
ProtocolConfig _) => payload = p);

await _consoleWrapper.ProcessTestRunAttachmentsAsync(
_attachmentSets,
_invokedDataCollectors,
_runSettings,
true,
false,
attachmentsEventHandler.Object,
CancellationToken.None).ConfigureAwait(false);

Assert.IsNotNull(payload);
Assert.IsTrue(_attachmentSets.SequenceEqual(payload.Attachments!));
Assert.IsTrue(_invokedDataCollectors.SequenceEqual(payload.InvokedDataCollectors!));
Assert.AreEqual(_runSettings, payload.RunSettings);
Assert.IsFalse(payload.CollectMetrics);

_mockEventSource.Verify(es => es.TranslationLayerTestRunAttachmentsProcessingStart(), Times.Once);
_mockEventSource.Verify(es => es.TranslationLayerTestRunAttachmentsProcessingStop(), Times.Once);
_mockTestRequestManager.Verify(trm => trm.ResetOptions(), Times.Never);
_mockTestRequestManager.Verify(trm => trm.ProcessTestRunAttachments(
It.IsAny<TestRunAttachmentsProcessingPayload>(),
It.IsAny<ITestRunAttachmentsProcessingEventsHandler>(),
It.IsAny<ProtocolConfig>()), Times.Once);
}

[TestMethod]
public async Task InProcessWrapperProcessTestRunAttachmentsAsyncWithSevenParamsSuccessfullyHandlesCancellation()
{
var attachmentsEventHandler = new Mock<ITestRunAttachmentsProcessingEventsHandler>();

TestRunAttachmentsProcessingPayload? payload = null;
_mockTestRequestManager
.Setup(trm => trm.ProcessTestRunAttachments(
It.IsAny<TestRunAttachmentsProcessingPayload>(),
It.IsAny<ITestRunAttachmentsProcessingEventsHandler>(),
It.IsAny<ProtocolConfig>()))
.Callback((
TestRunAttachmentsProcessingPayload p,
ITestRunAttachmentsProcessingEventsHandler _,
ProtocolConfig _) => payload = p);
_mockTestRequestManager.Setup(trm => trm.CancelTestRunAttachmentsProcessing())
.Callback(() => { });

var cancellationTokenSource = new CancellationTokenSource();

cancellationTokenSource.Cancel();
await _consoleWrapper.ProcessTestRunAttachmentsAsync(
_attachmentSets,
_invokedDataCollectors,
_runSettings,
true,
false,
attachmentsEventHandler.Object,
cancellationTokenSource.Token).ConfigureAwait(false);

Assert.IsNotNull(payload);
Assert.IsTrue(_attachmentSets.SequenceEqual(payload.Attachments!));
Assert.IsTrue(_invokedDataCollectors.SequenceEqual(payload.InvokedDataCollectors!));
Assert.AreEqual(_runSettings, payload.RunSettings);
Assert.IsFalse(payload.CollectMetrics);

_mockEventSource.Verify(es => es.TranslationLayerTestRunAttachmentsProcessingStart(), Times.Once);
_mockEventSource.Verify(es => es.TranslationLayerTestRunAttachmentsProcessingStop(), Times.Once);
_mockTestRequestManager.Verify(trm => trm.ResetOptions(), Times.Never);
_mockTestRequestManager.Verify(trm => trm.ProcessTestRunAttachments(
It.IsAny<TestRunAttachmentsProcessingPayload>(),
It.IsAny<ITestRunAttachmentsProcessingEventsHandler>(),
It.IsAny<ProtocolConfig>()), Times.Once);
_mockTestRequestManager.Verify(trm => trm.CancelTestRunAttachmentsProcessing(), Times.Once);
}

[TestMethod]
public async Task InProcessWrapperProcessTestRunAttachmentsAsyncWithSevenParamsSuccessfullyHandlesExceptions()
{
var attachmentsEventHandler = new Mock<ITestRunAttachmentsProcessingEventsHandler>();

_mockTestRequestManager
.Setup(trm => trm.ProcessTestRunAttachments(
It.IsAny<TestRunAttachmentsProcessingPayload>(),
It.IsAny<ITestRunAttachmentsProcessingEventsHandler>(),
It.IsAny<ProtocolConfig>()))
.Throws(new Exception("Dummy exception"));

await _consoleWrapper.ProcessTestRunAttachmentsAsync(
_attachmentSets,
_invokedDataCollectors,
_runSettings,
true,
false,
attachmentsEventHandler.Object,
CancellationToken.None).ConfigureAwait(false);

_mockEventSource.Verify(es => es.TranslationLayerTestRunAttachmentsProcessingStart(), Times.Once);
_mockEventSource.Verify(es => es.TranslationLayerTestRunAttachmentsProcessingStop(), Times.Once);
_mockTestRequestManager.Verify(trm => trm.ResetOptions(), Times.Never);
_mockTestRequestManager.Verify(trm => trm.ProcessTestRunAttachments(
It.IsAny<TestRunAttachmentsProcessingPayload>(),
It.IsAny<ITestRunAttachmentsProcessingEventsHandler>(),
It.IsAny<ProtocolConfig>()), Times.Once);
attachmentsEventHandler.Verify(eh => eh.HandleLogMessage(TestMessageLevel.Error, It.IsAny<string>()));
}

[TestMethod]
public async Task InProcessWrapperProcessTestRunAttachmentsAsyncWithSevenParamsSuccessfullyHandlesNullTestRequestManager()
{
var attachmentsEventHandler = new Mock<ITestRunAttachmentsProcessingEventsHandler>();

_consoleWrapper.TestRequestManager = null;

await _consoleWrapper.ProcessTestRunAttachmentsAsync(
_attachmentSets,
_invokedDataCollectors,
_runSettings,
true,
false,
attachmentsEventHandler.Object,
CancellationToken.None).ConfigureAwait(false);

_mockEventSource.Verify(es => es.TranslationLayerTestRunAttachmentsProcessingStart(), Times.Once);
_mockEventSource.Verify(es => es.TranslationLayerTestRunAttachmentsProcessingStop(), Times.Once);
}

[TestMethod]
public async Task InProcessWrapperProcessTestRunAttachmentsAsyncWithSixParamsIsSuccessfullyInvoked()
{
var attachmentsEventHandler = new Mock<ITestRunAttachmentsProcessingEventsHandler>();

TestRunAttachmentsProcessingPayload? payload = null;
_mockTestRequestManager
.Setup(trm => trm.ProcessTestRunAttachments(
It.IsAny<TestRunAttachmentsProcessingPayload>(),
It.IsAny<ITestRunAttachmentsProcessingEventsHandler>(),
It.IsAny<ProtocolConfig>()))
.Callback((
TestRunAttachmentsProcessingPayload p,
ITestRunAttachmentsProcessingEventsHandler _,
ProtocolConfig _) => payload = p);

await _consoleWrapper.ProcessTestRunAttachmentsAsync(
_attachmentSets,
_runSettings,
true,
false,
attachmentsEventHandler.Object,
CancellationToken.None);

Assert.IsNotNull(payload);
Assert.IsTrue(_attachmentSets.SequenceEqual(payload.Attachments!));
Assert.IsNull(payload.InvokedDataCollectors);
Assert.AreEqual(_runSettings, payload.RunSettings);
Assert.IsFalse(payload.CollectMetrics);

_mockEventSource.Verify(es => es.TranslationLayerTestRunAttachmentsProcessingStart(), Times.Once);
_mockEventSource.Verify(es => es.TranslationLayerTestRunAttachmentsProcessingStop(), Times.Once);
_mockTestRequestManager.Verify(trm => trm.ResetOptions(), Times.Never);
_mockTestRequestManager.Verify(trm => trm.ProcessTestRunAttachments(
It.IsAny<TestRunAttachmentsProcessingPayload>(),
It.IsAny<ITestRunAttachmentsProcessingEventsHandler>(),
It.IsAny<ProtocolConfig>()), Times.Once);
}
}

0 comments on commit f229b1a

Please sign in to comment.