44using System ;
55using System . Collections . Generic ;
66using System . Collections . ObjectModel ;
7+ using System . Diagnostics ;
78using System . Linq ;
89using System . Threading ;
910using System . Threading . Tasks ;
11+ using Microsoft . VisualStudio . TestPlatform . Common . Telemetry ;
1012using Microsoft . VisualStudio . TestPlatform . CoreUtilities . Tracing . Interfaces ;
1113using Microsoft . VisualStudio . TestPlatform . ObjectModel ;
1214using Microsoft . VisualStudio . TestPlatform . ObjectModel . Client ;
@@ -20,6 +22,10 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.MultiTestRunFinali
2022 /// </summary>
2123 public class MultiTestRunFinalizationManager : IMultiTestRunFinalizationManager
2224 {
25+ private static string FinalizationCompleted = "Completed" ;
26+ private static string FinalizationCanceled = "Canceled" ;
27+ private static string FinalizationFailed = "Failed" ;
28+
2329 private readonly ITestPlatformEventSource testPlatformEventSource ;
2430 private readonly IDataCollectorAttachments [ ] dataCollectorAttachmentsHandlers ;
2531
@@ -33,65 +39,74 @@ public MultiTestRunFinalizationManager(ITestPlatformEventSource testPlatformEven
3339 }
3440
3541 /// <inheritdoc/>
36- public async Task FinalizeMultiTestRunAsync ( ICollection < AttachmentSet > attachments , IMultiTestRunFinalizationEventsHandler eventHandler , CancellationToken cancellationToken )
42+ public async Task FinalizeMultiTestRunAsync ( IRequestData requestData , IEnumerable < AttachmentSet > attachments , IMultiTestRunFinalizationEventsHandler eventHandler , CancellationToken cancellationToken )
3743 {
38- await InternalFinalizeMultiTestRunAsync ( new Collection < AttachmentSet > ( attachments . ToList ( ) ) , eventHandler , cancellationToken ) . ConfigureAwait ( false ) ;
44+ await InternalFinalizeMultiTestRunAsync ( requestData , new Collection < AttachmentSet > ( attachments . ToList ( ) ) , eventHandler , cancellationToken ) . ConfigureAwait ( false ) ;
3945 }
40-
4146 /// <inheritdoc/>
42- public Task < Collection < AttachmentSet > > FinalizeMultiTestRunAsync ( ICollection < AttachmentSet > attachments , CancellationToken cancellationToken )
47+ public Task < Collection < AttachmentSet > > FinalizeMultiTestRunAsync ( IRequestData requestData , IEnumerable < AttachmentSet > attachments , CancellationToken cancellationToken )
4348 {
44- return InternalFinalizeMultiTestRunAsync ( new Collection < AttachmentSet > ( attachments . ToList ( ) ) , null , cancellationToken ) ;
49+ return InternalFinalizeMultiTestRunAsync ( requestData , new Collection < AttachmentSet > ( attachments . ToList ( ) ) , null , cancellationToken ) ;
4550 }
4651
47- private async Task < Collection < AttachmentSet > > InternalFinalizeMultiTestRunAsync ( Collection < AttachmentSet > attachments , IMultiTestRunFinalizationEventsHandler eventHandler , CancellationToken cancellationToken )
52+ private async Task < Collection < AttachmentSet > > InternalFinalizeMultiTestRunAsync ( IRequestData requestData , Collection < AttachmentSet > attachments , IMultiTestRunFinalizationEventsHandler eventHandler , CancellationToken cancellationToken )
4853 {
54+ Stopwatch stopwatch = Stopwatch . StartNew ( ) ;
55+
4956 try
5057 {
5158 testPlatformEventSource . MultiTestRunFinalizationStart ( attachments ? . Count ?? 0 ) ;
52-
59+ requestData . MetricsCollection . Add ( TelemetryDataConstants . NumberOfAttachmentsSentForFinalization , attachments ? . Count ?? 0 ) ;
60+
5361 cancellationToken . ThrowIfCancellationRequested ( ) ;
5462
55- var taskCompletionSource = new TaskCompletionSource < object > ( ) ;
63+ var taskCompletionSource = new TaskCompletionSource < Collection < AttachmentSet > > ( ) ;
5664 using ( cancellationToken . Register ( ( ) => taskCompletionSource . TrySetCanceled ( ) ) )
5765 {
58- Task task = Task . Run ( ( ) =>
66+ Task < Collection < AttachmentSet > > task = Task . Run ( ( ) =>
5967 {
60- HandleAttachments ( attachments , cancellationToken ) ;
68+ return ProcessAttachments ( new Collection < AttachmentSet > ( attachments . ToList ( ) ) , new ProgressReporter ( eventHandler , dataCollectorAttachmentsHandlers . Length ) , cancellationToken ) ;
6169 } ) ;
6270
6371 var completedTask = await Task . WhenAny ( task , taskCompletionSource . Task ) . ConfigureAwait ( false ) ;
6472
6573 if ( completedTask == task )
6674 {
67- await task ;
68- eventHandler ? . HandleMultiTestRunFinalizationComplete ( attachments ) ;
69- testPlatformEventSource . MultiTestRunFinalizationStop ( attachments . Count ) ;
70- return attachments ;
75+ return FinalizeOperation ( requestData , await task , eventHandler , FinalizationCompleted ) ;
7176 }
7277 else
7378 {
7479 eventHandler ? . HandleLogMessage ( ObjectModel . Logging . TestMessageLevel . Informational , "Finalization was cancelled." ) ;
75- eventHandler ? . HandleMultiTestRunFinalizationComplete ( null ) ;
76- testPlatformEventSource . MultiTestRunFinalizationStop ( 0 ) ;
80+ return FinalizeOperation ( requestData , attachments , eventHandler , FinalizationCanceled ) ;
7781 }
7882 }
79-
80- return null ;
83+ }
84+ catch ( OperationCanceledException )
85+ {
86+ if ( EqtTrace . IsWarningEnabled )
87+ {
88+ EqtTrace . Warning ( "MultiTestRunFinalizationManager: operation was cancelled." ) ;
89+ }
90+ return FinalizeOperation ( requestData , attachments , eventHandler , FinalizationCanceled ) ;
8191 }
8292 catch ( Exception e )
8393 {
8494 EqtTrace . Error ( "MultiTestRunFinalizationManager: Exception in FinalizeMultiTestRunAsync: " + e ) ;
8595
8696 eventHandler ? . HandleLogMessage ( ObjectModel . Logging . TestMessageLevel . Error , e . Message ) ;
87- eventHandler ? . HandleMultiTestRunFinalizationComplete ( null ) ;
88- testPlatformEventSource . MultiTestRunFinalizationStop ( 0 ) ;
89- return null ;
97+ return FinalizeOperation ( requestData , attachments , eventHandler , FinalizationFailed ) ;
98+ }
99+ finally
100+ {
101+ stopwatch . Stop ( ) ;
102+ requestData . MetricsCollection . Metrics . Add ( TelemetryDataConstants . TimeTakenInSecForFinalization , stopwatch . Elapsed . TotalSeconds ) ;
90103 }
91104 }
92105
93- private void HandleAttachments ( ICollection < AttachmentSet > attachments , CancellationToken cancellationToken )
106+ private Collection < AttachmentSet > ProcessAttachments ( Collection < AttachmentSet > attachments , ProgressReporter progressReporter , CancellationToken cancellationToken )
94107 {
108+ if ( attachments == null || ! attachments . Any ( ) ) return attachments ;
109+
95110 foreach ( var dataCollectorAttachmentsHandler in dataCollectorAttachmentsHandlers )
96111 {
97112 Uri attachementUri = dataCollectorAttachmentsHandler . GetExtensionUri ( ) ;
@@ -105,14 +120,50 @@ private void HandleAttachments(ICollection<AttachmentSet> attachments, Cancellat
105120 attachments . Remove ( attachment ) ;
106121 }
107122
108- ICollection < AttachmentSet > processedAttachments = dataCollectorAttachmentsHandler . HandleDataCollectionAttachmentSets ( new Collection < AttachmentSet > ( attachmentsToBeProcessed ) , cancellationToken ) ;
123+ ICollection < AttachmentSet > processedAttachments = dataCollectorAttachmentsHandler . HandleDataCollectionAttachmentSets ( new Collection < AttachmentSet > ( attachmentsToBeProcessed ) , progressReporter , cancellationToken ) ;
109124 foreach ( var attachment in processedAttachments )
110125 {
111126 attachments . Add ( attachment ) ;
112127 }
113128 }
114129 }
115130 }
131+
132+ return attachments ;
133+ }
134+
135+ private Collection < AttachmentSet > FinalizeOperation ( IRequestData requestData , Collection < AttachmentSet > attachments , IMultiTestRunFinalizationEventsHandler eventHandler , string finalizationState )
136+ {
137+ eventHandler ? . HandleMultiTestRunFinalizationComplete ( attachments ) ;
138+ testPlatformEventSource . MultiTestRunFinalizationStop ( attachments . Count ) ;
139+ requestData . MetricsCollection . Add ( TelemetryDataConstants . NumberOfAttachmentsAfterFinalization , attachments . Count ) ;
140+ requestData . MetricsCollection . Add ( TelemetryDataConstants . FinalizationState , attachments . Count ) ;
141+
142+ return attachments ;
143+ }
144+
145+ private class ProgressReporter : IProgress < int >
146+ {
147+ private readonly IMultiTestRunFinalizationEventsHandler eventsHandler ;
148+ private readonly int totalNumberOfHandlers ;
149+ private int currentHandlerIndex ;
150+
151+ public ProgressReporter ( IMultiTestRunFinalizationEventsHandler eventsHandler , int totalNumberOfHandlers )
152+ {
153+ this . eventsHandler = eventsHandler ;
154+ this . currentHandlerIndex = 0 ;
155+ this . totalNumberOfHandlers = totalNumberOfHandlers ;
156+ }
157+
158+ public void IncremenetHandlerIndex ( )
159+ {
160+ currentHandlerIndex ++ ;
161+ }
162+
163+ public void Report ( int value )
164+ {
165+ //eventsHandler.report( current, total, value)
166+ }
116167 }
117168 }
118169}
0 commit comments