Skip to content

Commit

Permalink
RFC changes merged
Browse files Browse the repository at this point in the history
  • Loading branch information
jakubch1 committed Jun 30, 2020
1 parent 25849e9 commit 571028e
Show file tree
Hide file tree
Showing 18 changed files with 235 additions and 200 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public void HandleMultiTestRunFinalizationProgress(MultiTestRunFinalizationProgr
}

/// <inheritdoc/>
public void HandleFinalisedAttachments(IEnumerable<AttachmentSet> attachments)
public void HandleProcessedAttachmentsChunk(IEnumerable<AttachmentSet> attachments)
{
throw new System.NotImplementedException();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ public class MultiTestRunFinalizationManager : IMultiTestRunFinalizationManager
private static string FinalizationFailed = "Failed";

private readonly ITestPlatformEventSource testPlatformEventSource;
private readonly IDataCollectorAttachments[] dataCollectorAttachmentsHandlers;
private readonly IDataCollectorAttachmentProcessor[] dataCollectorAttachmentsProcessors;

/// <summary>
/// Initializes a new instance of the <see cref="MultiTestRunFinalizationManager"/> class.
/// </summary>
public MultiTestRunFinalizationManager(ITestPlatformEventSource testPlatformEventSource, params IDataCollectorAttachments[] dataCollectorAttachmentsHandlers)
public MultiTestRunFinalizationManager(ITestPlatformEventSource testPlatformEventSource, params IDataCollectorAttachmentProcessor[] dataCollectorAttachmentsProcessors)
{
this.testPlatformEventSource = testPlatformEventSource ?? throw new ArgumentNullException(nameof(testPlatformEventSource));
this.dataCollectorAttachmentsHandlers = dataCollectorAttachmentsHandlers ?? throw new ArgumentNullException(nameof(dataCollectorAttachmentsHandlers));
this.dataCollectorAttachmentsProcessors = dataCollectorAttachmentsProcessors ?? throw new ArgumentNullException(nameof(dataCollectorAttachmentsProcessors));
}

/// <inheritdoc/>
Expand Down Expand Up @@ -64,10 +64,7 @@ private async Task<Collection<AttachmentSet>> InternalFinalizeMultiTestRunAsync(
var taskCompletionSource = new TaskCompletionSource<Collection<AttachmentSet>>();
using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled()))
{
Task<Collection<AttachmentSet>> task = Task.Run(() =>
{
return ProcessAttachments(new Collection<AttachmentSet>(attachments.ToList()), eventHandler, cancellationToken);
});
Task<Collection<AttachmentSet>> task = Task.Run(async () => await ProcessAttachmentsAsync(new Collection<AttachmentSet>(attachments.ToList()), eventHandler, cancellationToken));

var completedTask = await Task.WhenAny(task, taskCompletionSource.Task).ConfigureAwait(false);

Expand All @@ -77,7 +74,7 @@ private async Task<Collection<AttachmentSet>> InternalFinalizeMultiTestRunAsync(
}
else
{
eventHandler?.HandleLogMessage(ObjectModel.Logging.TestMessageLevel.Informational, "Finalization was cancelled.");
eventHandler?.HandleLogMessage(TestMessageLevel.Informational, "Finalization was cancelled.");
return FinalizeOperation(requestData, new MultiTestRunFinalizationCompleteEventArgs(true, null), attachments, stopwatch, eventHandler);
}
}
Expand All @@ -94,26 +91,26 @@ private async Task<Collection<AttachmentSet>> InternalFinalizeMultiTestRunAsync(
{
EqtTrace.Error("MultiTestRunFinalizationManager: Exception in FinalizeMultiTestRunAsync: " + e);

eventHandler?.HandleLogMessage(ObjectModel.Logging.TestMessageLevel.Error, e.Message);
eventHandler?.HandleLogMessage(TestMessageLevel.Error, e.Message);
return FinalizeOperation(requestData, new MultiTestRunFinalizationCompleteEventArgs(false, e), attachments, stopwatch, eventHandler);
}
}

private Collection<AttachmentSet> ProcessAttachments(Collection<AttachmentSet> attachments, IMultiTestRunFinalizationEventsHandler eventsHandler, CancellationToken cancellationToken)
private async Task<Collection<AttachmentSet>> ProcessAttachmentsAsync(Collection<AttachmentSet> attachments, IMultiTestRunFinalizationEventsHandler eventsHandler, CancellationToken cancellationToken)
{
if (attachments == null || !attachments.Any()) return attachments;

var logger = CreateMessageLogger(eventsHandler);

for (int i = 0; i < dataCollectorAttachmentsHandlers.Length; i++)
for (int i = 0; i < dataCollectorAttachmentsProcessors.Length; i++)
{
IDataCollectorAttachments dataCollectorAttachmentsHandler = dataCollectorAttachmentsHandlers[i];
var dataCollectorAttachmentsProcessor = dataCollectorAttachmentsProcessors[i];
int attachmentsHandlerIndex = i + 1;

Uri attachementUri = dataCollectorAttachmentsHandler.GetExtensionUri();
if (attachementUri != null)
ICollection<Uri> attachementProcessorUris = dataCollectorAttachmentsProcessor.GetExtensionUris()?.ToList();
if (attachementProcessorUris != null && attachementProcessorUris.Any())
{
var attachmentsToBeProcessed = attachments.Where(dataCollectionAttachment => attachementUri.Equals(dataCollectionAttachment.Uri)).ToArray();
var attachmentsToBeProcessed = attachments.Where(dataCollectionAttachment => attachementProcessorUris.Any(uri => uri.Equals(dataCollectionAttachment.Uri))).ToArray();
if (attachmentsToBeProcessed.Any())
{
foreach (var attachment in attachmentsToBeProcessed)
Expand All @@ -123,9 +120,9 @@ private Collection<AttachmentSet> ProcessAttachments(Collection<AttachmentSet> a

IProgress<int> progressReporter = new Progress<int>((int progress) =>
eventsHandler?.HandleMultiTestRunFinalizationProgress(
new MultiTestRunFinalizationProgressEventArgs(attachmentsHandlerIndex, dataCollectorAttachmentsHandler.GetExtensionUri(), progress, dataCollectorAttachmentsHandlers.Length)));
new MultiTestRunFinalizationProgressEventArgs(attachmentsHandlerIndex, attachementProcessorUris, progress, dataCollectorAttachmentsProcessors.Length)));

ICollection<AttachmentSet> processedAttachments = dataCollectorAttachmentsHandler.HandleDataCollectionAttachmentSets(new Collection<AttachmentSet>(attachmentsToBeProcessed), progressReporter, logger, cancellationToken);
ICollection<AttachmentSet> processedAttachments = await dataCollectorAttachmentsProcessor.ProcessAttachmentSetsAsync(new Collection<AttachmentSet>(attachmentsToBeProcessed), progressReporter, logger, cancellationToken).ConfigureAwait(false);

foreach (var attachment in processedAttachments)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public MultiTestRunFinalizationCompleteEventArgs(bool isCanceled, Exception erro
public Exception Error { get; private set; }

/// <summary>
/// Get or Sets the Metrics
/// Get or Sets the Metrics (used for telemetry)
/// </summary>
[DataMember]
public IDictionary<string, object> Metrics { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
namespace Microsoft.VisualStudio.TestPlatform.ObjectModel.Client
{
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;

[DataContract]
Expand All @@ -12,40 +13,40 @@ public class MultiTestRunFinalizationProgressEventArgs : EventArgs
/// <summary>
/// Default constructor.
/// </summary>
/// <param name="currentHandlerIndex">Specifies current handler index.</param>
/// <param name="currentHandlerUri">Specifies current handler Uri.</param>
/// <param name="currentHandlerProgress">Specifies current handler progress.</param>
/// <param name="handlersCount">Specifies the overall number of handlers.</param>
public MultiTestRunFinalizationProgressEventArgs(long currentHandlerIndex, Uri currentHandlerUri, long currentHandlerProgress, long handlersCount)
/// <param name="currentAttachmentProcessorIndex">Specifies current attachment processor index.</param>
/// <param name="currentAttachmentProcessorUris">Specifies current processor Uris.</param>
/// <param name="currentAttachmentProcessorProgress">Specifies current processor progress.</param>
/// <param name="attachmentProcessorsCount">Specifies the overall number of processors.</param>
public MultiTestRunFinalizationProgressEventArgs(long currentAttachmentProcessorIndex, ICollection<Uri> currentAttachmentProcessorUris, long currentAttachmentProcessorProgress, long attachmentProcessorsCount)
{
CurrentHandlerIndex = currentHandlerIndex;
CurrentHandlerUri = currentHandlerUri;
CurrentHandlerProgress = currentHandlerProgress;
HandlersCount = handlersCount;
CurrentAttachmentProcessorIndex = currentAttachmentProcessorIndex;
CurrentAttachmentProcessorUris = currentAttachmentProcessorUris;
CurrentAttachmentProcessorProgress = currentAttachmentProcessorProgress;
AttachmentProcessorsCount = attachmentProcessorsCount;
}

/// <summary>
/// Gets a current handler index.
/// Gets a current attachment processor index.
/// </summary>
[DataMember]
public long CurrentHandlerIndex { get; private set; }
public long CurrentAttachmentProcessorIndex { get; private set; }

/// <summary>
/// Gets a current handler URI.
/// Gets a current attachment processor URI.
/// </summary>
[DataMember]
public Uri CurrentHandlerUri { get; private set; }
public ICollection<Uri> CurrentAttachmentProcessorUris { get; private set; }

/// <summary>
/// Gets a current handler progress.
/// Gets a current attachment processor progress.
/// </summary>
[DataMember]
public long CurrentHandlerProgress { get; private set; }
public long CurrentAttachmentProcessorProgress { get; private set; }

/// <summary>
/// Gets the overall number of handlers.
/// Gets the overall number of attachment processors.
/// </summary>
[DataMember]
public long HandlersCount { get; private set; }
public long AttachmentProcessorsCount { get; private set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
namespace Microsoft.VisualStudio.TestPlatform.ObjectModel.Client
{
/// <summary>
/// Interface contract for handling multi test run finalization complete events
/// Interface contract for handling multi test run finalization events
/// </summary>
public interface IMultiTestRunFinalizationEventsHandler : ITestMessageEventHandler
{
Expand All @@ -18,10 +18,10 @@ public interface IMultiTestRunFinalizationEventsHandler : ITestMessageEventHandl
void HandleMultiTestRunFinalizationComplete(MultiTestRunFinalizationCompleteEventArgs finalizationCompleteEventArgs, IEnumerable<AttachmentSet> lastChunk);

/// <summary>
/// Dispatch FinalisedAttachments event to listeners.
/// Dispatch ProcessedAttachmentsChunk event to listeners.
/// </summary>
/// <param name="attachments">Finalised attachment sets.</param>
void HandleFinalisedAttachments(IEnumerable<AttachmentSet> attachments);
/// <param name="attachments">Processed attachment sets.</param>
void HandleProcessedAttachmentsChunk(IEnumerable<AttachmentSet> attachments);

/// <summary>
/// Dispatch MultiTestRunFinalizationProgress event to listeners.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollection
{
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;

/// <summary>
/// Interface for data collectors add-ins that choose to reprocess generated attachments
/// </summary>
public interface IDataCollectorAttachmentProcessor
{
/// <summary>
/// Gets the attachments Uris, which are handled by attachment processor
/// </summary>
IEnumerable<Uri> GetExtensionUris();

/// <summary>
/// Indicates whether attachment processor is supporting incremental processing of attachments
/// </summary>
bool SupportsIncrementalProcessing { get; }

/// <summary>
/// Reprocess attachments generated by independent test executions
/// </summary>
/// <param name="attachments">Attachments to be processed</param>
/// <param name="progressReporter">Progress reporter. Accepts integers from 0 to 100</param>
/// <param name="logger">Message logger</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>Attachments after reprocessing</returns>
Task<ICollection<AttachmentSet>> ProcessAttachmentSetsAsync(ICollection<AttachmentSet> attachments, IProgress<int> progressReporter, IMessageLogger logger, CancellationToken cancellationToken);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@

namespace Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollection
{
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;
using System;
using System.Collections.Generic;
using System.Threading;

/// <summary>
/// Interface for data collectors add-ins that choose to handle attachment(s) generated
/// </summary>
[Obsolete("Interface is deprecated. Please use IDataCollectorAttachmentProcessor instead")]
public interface IDataCollectorAttachments
{
/// <summary>
Expand All @@ -19,15 +18,6 @@ public interface IDataCollectorAttachments
/// <returns>Gets the attachment set after Test Run Session</returns>
ICollection<AttachmentSet> HandleDataCollectionAttachmentSets(ICollection<AttachmentSet> dataCollectionAttachments);

/// <summary>
/// Gets the attachment set after Test Run Session
/// </summary>
/// <param name="dataCollectionAttachments">Attachments to be processed</param>
/// <param name="progressReporter">Progress reporter. Accepts integers from 0 to 100</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>Gets the attachment set after Test Run Session</returns>
ICollection<AttachmentSet> HandleDataCollectionAttachmentSets(ICollection<AttachmentSet> dataCollectionAttachments, IProgress<int> progressReporter, IMessageLogger logger, CancellationToken cancellationToken);

/// <summary>
/// Gets the attachment Uri, which is handled by current Collector
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ namespace Microsoft.VisualStudio.TestPlatform.Utilities
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollection;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;
using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions;

public class CodeCoverageDataAttachmentsHandler : IDataCollectorAttachments
public class CodeCoverageDataAttachmentsHandler : IDataCollectorAttachmentProcessor
{
private const string CoverageUri = "datacollector://microsoft/CodeCoverage/2.0";
private const string CoverageFileExtension = ".coverage";
Expand All @@ -27,35 +28,32 @@ public class CodeCoverageDataAttachmentsHandler : IDataCollectorAttachments

private static readonly Uri CodeCoverageDataCollectorUri = new Uri(CoverageUri);

public Uri GetExtensionUri()
{
return CodeCoverageDataCollectorUri;
}
public bool SupportsIncrementalProcessing => true;

public ICollection<AttachmentSet> HandleDataCollectionAttachmentSets(ICollection<AttachmentSet> dataCollectionAttachments)
public IEnumerable<Uri> GetExtensionUris()
{
return HandleDataCollectionAttachmentSets(dataCollectionAttachments, null, null, CancellationToken.None);
}
yield return CodeCoverageDataCollectorUri;
}

public ICollection<AttachmentSet> HandleDataCollectionAttachmentSets(ICollection<AttachmentSet> dataCollectionAttachments, IProgress<int> progressReporter, IMessageLogger logger, CancellationToken cancellationToken)
public Task<ICollection<AttachmentSet>> ProcessAttachmentSetsAsync(ICollection<AttachmentSet> attachments, IProgress<int> progressReporter, IMessageLogger logger, CancellationToken cancellationToken)
{
if (dataCollectionAttachments != null && dataCollectionAttachments.Any())
if (attachments != null && attachments.Any())
{
var codeCoverageFiles = dataCollectionAttachments.Select(coverageAttachment => coverageAttachment.Attachments[0].Uri.LocalPath).ToArray();
var codeCoverageFiles = attachments.Select(coverageAttachment => coverageAttachment.Attachments[0].Uri.LocalPath).ToArray();
var outputFile = MergeCodeCoverageFiles(codeCoverageFiles, progressReporter, cancellationToken);
var attachmentSet = new AttachmentSet(CodeCoverageDataCollectorUri, CoverageFriendlyName);

if (!string.IsNullOrEmpty(outputFile))
{
attachmentSet.Attachments.Add(new UriDataAttachment(new Uri(outputFile), CoverageFriendlyName));
return new Collection<AttachmentSet> { attachmentSet };
return Task.FromResult((ICollection<AttachmentSet>)new Collection<AttachmentSet> { attachmentSet });
}

// In case merging fails(esp in dotnet core we cannot merge), so return filtered list of Code Coverage Attachments
return dataCollectionAttachments;
return Task.FromResult(attachments);
}

return new Collection<AttachmentSet>();
return Task.FromResult((ICollection<AttachmentSet>)new Collection<AttachmentSet>());
}

private string MergeCodeCoverageFiles(IList<string> files, IProgress<int> progressReporter, CancellationToken cancellationToken)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,10 @@ public interface IVsTestConsoleWrapperAsync
/// Provides back all attachments to TestPlatform for additional processing (for example merging)
/// </summary>
/// <param name="attachments">Collection of attachments</param>
/// <param name="collectMetrics">Enables metrics collection</param>
/// <param name="multiTestRunFinalizationCompleteEventsHandler">EventHandler to receive session complete event</param>
/// <param name="multiTestRunCompleted">Indicates that all test executions are done and all data is provided</param>
/// <param name="collectMetrics">Enables metrics collection (used for telemetry)</param>
/// <param name="eventsHandler">EventHandler to receive session complete event</param>
/// <param name="cancellationToken">Cancellation token</param>
Task FinalizeMultiTestRunAsync(IEnumerable<AttachmentSet> attachments, bool collectMetrics, IMultiTestRunFinalizationEventsHandler multiTestRunFinalizationCompleteEventsHandler, CancellationToken cancellationToken);
Task FinalizeMultiTestRunAsync(IEnumerable<AttachmentSet> attachments, bool multiTestRunCompleted, bool collectMetrics, IMultiTestRunFinalizationEventsHandler eventsHandler, CancellationToken cancellationToken);
}
}
Loading

0 comments on commit 571028e

Please sign in to comment.