diff --git a/scripts/build/TestPlatform.Dependencies.props b/scripts/build/TestPlatform.Dependencies.props index 9fe91f412c..8212613327 100644 --- a/scripts/build/TestPlatform.Dependencies.props +++ b/scripts/build/TestPlatform.Dependencies.props @@ -31,8 +31,8 @@ 5.0.0 9.0.1 4.7.63 - 16.9.0-preview-4189539 - 16.9.0-beta.20563.1 + 16.9.0-preview-4243816 + 16.9.0-beta.20570.2 16.8.0-beta.20420.2 16.0.461 diff --git a/scripts/verify-nupkgs.ps1 b/scripts/verify-nupkgs.ps1 index 1d9ea23b03..70f48ec763 100644 --- a/scripts/verify-nupkgs.ps1 +++ b/scripts/verify-nupkgs.ps1 @@ -15,12 +15,12 @@ function Verify-Nuget-Packages($packageDirectory, $version) $expectedNumOfFiles = @{ "Microsoft.CodeCoverage" = 44; "Microsoft.NET.Test.Sdk" = 18; - "Microsoft.TestPlatform" = 488; + "Microsoft.TestPlatform" = 486; "Microsoft.TestPlatform.Build" = 19; - "Microsoft.TestPlatform.CLI" = 350; + "Microsoft.TestPlatform.CLI" = 353; "Microsoft.TestPlatform.Extensions.TrxLogger" = 33; "Microsoft.TestPlatform.ObjectModel" = 178; - "Microsoft.TestPlatform.Portable" = 566; + "Microsoft.TestPlatform.Portable" = 568; "Microsoft.TestPlatform.TestHost" = 212; "Microsoft.TestPlatform.TranslationLayer" = 121} diff --git a/src/Microsoft.TestPlatform.Utilities/CodeCoverageDataAttachmentsHandler.cs b/src/Microsoft.TestPlatform.Utilities/CodeCoverageDataAttachmentsHandler.cs index 2b911f6926..3c2ceeff0f 100644 --- a/src/Microsoft.TestPlatform.Utilities/CodeCoverageDataAttachmentsHandler.cs +++ b/src/Microsoft.TestPlatform.Utilities/CodeCoverageDataAttachmentsHandler.cs @@ -11,6 +11,8 @@ namespace Microsoft.VisualStudio.TestPlatform.Utilities using System.Reflection; using System.Threading; using System.Threading.Tasks; + + using Microsoft.VisualStudio.Coverage.CoreLib.Net; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollection; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; @@ -22,10 +24,6 @@ public class CodeCoverageDataAttachmentsHandler : IDataCollectorAttachmentProces private const string CoverageFileExtension = ".coverage"; private const string CoverageFriendlyName = "Code Coverage"; - private const string CodeCoverageAnalysisAssemblyName = "Microsoft.VisualStudio.Coverage.Analysis"; - private const string MergeMethodName = "MergeCoverageFiles"; - private const string CoverageInfoTypeName = "CoverageInfo"; - private static readonly Uri CodeCoverageDataCollectorUri = new Uri(CoverageUri); public bool SupportsIncrementalProcessing => true; @@ -35,93 +33,68 @@ public IEnumerable GetExtensionUris() yield return CodeCoverageDataCollectorUri; } - public Task> ProcessAttachmentSetsAsync(ICollection attachments, IProgress progressReporter, IMessageLogger logger, CancellationToken cancellationToken) + public async Task> ProcessAttachmentSetsAsync(ICollection attachments, IProgress progressReporter, IMessageLogger logger, CancellationToken cancellationToken) { if (attachments != null && attachments.Any()) { var codeCoverageFiles = attachments.Select(coverageAttachment => coverageAttachment.Attachments[0].Uri.LocalPath).ToArray(); - var outputFile = MergeCodeCoverageFiles(codeCoverageFiles, progressReporter, cancellationToken); + var outputFile = await this.MergeCodeCoverageFilesAsync(codeCoverageFiles, progressReporter, cancellationToken).ConfigureAwait(false); var attachmentSet = new AttachmentSet(CodeCoverageDataCollectorUri, CoverageFriendlyName); if (!string.IsNullOrEmpty(outputFile)) { attachmentSet.Attachments.Add(new UriDataAttachment(new Uri(outputFile), CoverageFriendlyName)); - return Task.FromResult((ICollection)new Collection { attachmentSet }); + return new Collection { attachmentSet }; } // In case merging fails(esp in dotnet core we cannot merge), so return filtered list of Code Coverage Attachments - return Task.FromResult(attachments); + return attachments; } - return Task.FromResult((ICollection)new Collection()); + return new Collection(); } - private string MergeCodeCoverageFiles(IList files, IProgress progressReporter, CancellationToken cancellationToken) + private async Task MergeCodeCoverageFilesAsync(IList files, IProgress progressReporter, CancellationToken cancellationToken) { - if(files.Count == 1) + if (files.Count == 1) { return files[0]; } - string tempFileName = Path.Combine(Path.GetTempPath(), Guid.NewGuid() + CoverageFileExtension); - string outputfileName = files[0]; - - File.Create(tempFileName).Dispose(); - var assemblyPath = Path.Combine(Path.GetDirectoryName(typeof(CodeCoverageDataAttachmentsHandler).GetTypeInfo().Assembly.GetAssemblyLocation()), CodeCoverageAnalysisAssemblyName + ".dll"); - try { - cancellationToken.ThrowIfCancellationRequested(); - Assembly assembly = new PlatformAssemblyLoadContext().LoadAssemblyFromPath(assemblyPath); - var type = assembly.GetType(CodeCoverageAnalysisAssemblyName + "." + CoverageInfoTypeName); - - var methodInfo = type?.GetMethod(MergeMethodName); - - if (methodInfo != null) - { - IList filesToDelete = new List(files.Count) { tempFileName }; - - for (int i = 1; i < files.Count; i++) - { - cancellationToken.ThrowIfCancellationRequested(); - progressReporter?.Report(100 * i / files.Count); - - cancellationToken.ThrowIfCancellationRequested(); - methodInfo.Invoke(null, new object[] { files[i], outputfileName, tempFileName, true }); - - cancellationToken.ThrowIfCancellationRequested(); - File.Copy(tempFileName, outputfileName, true); - - filesToDelete.Add(files[i]); - } - - cancellationToken.ThrowIfCancellationRequested(); - foreach (string fileName in filesToDelete) - { - File.Delete(fileName); - } - } - + // Warning: Don't remove this method call. + // + // We took a dependency on Coverage.CoreLib.Net. In the unlikely case it cannot be + // resolved, this method call will throw an exception that will be caught and + // absorbed here. + await this.MergeCodeCoverageFilesAsync(files, cancellationToken).ConfigureAwait(false); progressReporter?.Report(100); - return outputfileName; } catch (OperationCanceledException) { - if (EqtTrace.IsWarningEnabled) - { - EqtTrace.Warning("CodeCoverageDataCollectorAttachmentsHandler: operation was cancelled."); - } + // Occurs due to cancellation, ok to re-throw. throw; } catch (Exception ex) { - if (EqtTrace.IsErrorEnabled) - { - EqtTrace.Error("CodeCoverageDataCollectorAttachmentsHandler: Failed to load datacollector of type : {0} from location : {1}. Error : {2}", CodeCoverageAnalysisAssemblyName, assemblyPath, ex.ToString()); - } + EqtTrace.Error( + "CodeCoverageDataCollectorAttachmentsHandler: Failed to load datacollector. Error: {0}", + ex.ToString()); } - return string.Empty; + return files[0]; + } + + private async Task MergeCodeCoverageFilesAsync(IList files, CancellationToken cancellationToken) + { + var coverageUtility = new CoverageFileUtility(); + + var coverageData = await coverageUtility.MergeCoverageFilesAsync( + files, + cancellationToken).ConfigureAwait(false); + + coverageUtility.WriteCoverageFile(files[0], coverageData); } } } diff --git a/src/Microsoft.TestPlatform.Utilities/Microsoft.TestPlatform.Utilities.csproj b/src/Microsoft.TestPlatform.Utilities/Microsoft.TestPlatform.Utilities.csproj index 0323baf7e8..7d1416479c 100644 --- a/src/Microsoft.TestPlatform.Utilities/Microsoft.TestPlatform.Utilities.csproj +++ b/src/Microsoft.TestPlatform.Utilities/Microsoft.TestPlatform.Utilities.csproj @@ -15,8 +15,9 @@ + - + diff --git a/src/package/nuspec/Microsoft.TestPlatform.Portable.nuspec b/src/package/nuspec/Microsoft.TestPlatform.Portable.nuspec index 6bad5f5517..579a948c62 100644 --- a/src/package/nuspec/Microsoft.TestPlatform.Portable.nuspec +++ b/src/package/nuspec/Microsoft.TestPlatform.Portable.nuspec @@ -34,6 +34,7 @@ + @@ -286,6 +287,7 @@ + diff --git a/src/package/nuspec/Microsoft.TestPlatform.nuspec b/src/package/nuspec/Microsoft.TestPlatform.nuspec index 678d736810..504f900f82 100644 --- a/src/package/nuspec/Microsoft.TestPlatform.nuspec +++ b/src/package/nuspec/Microsoft.TestPlatform.nuspec @@ -109,8 +109,7 @@ - - + @@ -268,7 +267,6 @@ - diff --git a/src/package/sign/sign.proj b/src/package/sign/sign.proj index 67b7e8b404..4173e79f43 100644 --- a/src/package/sign/sign.proj +++ b/src/package/sign/sign.proj @@ -131,13 +131,11 @@ - - + - @@ -622,4 +620,4 @@ IntermediatesDirectory="$(IntermediatesDirectory)" Type="$(SignType)" /> - \ No newline at end of file + diff --git a/test/Microsoft.TestPlatform.AcceptanceTests/TranslationLayerTests/CodeCoverageTests.cs b/test/Microsoft.TestPlatform.AcceptanceTests/TranslationLayerTests/CodeCoverageTests.cs index 1185e8bd40..94fabb2a4b 100644 --- a/test/Microsoft.TestPlatform.AcceptanceTests/TranslationLayerTests/CodeCoverageTests.cs +++ b/test/Microsoft.TestPlatform.AcceptanceTests/TranslationLayerTests/CodeCoverageTests.cs @@ -53,8 +53,7 @@ public void TestRunWithCodeCoverage(RunnerInfo runnerInfo) // assert Assert.AreEqual(6, this.runEventHandler.TestResults.Count); - int expectedNumberOfAttachments = testEnvironment.RunnerFramework.Equals(IntegrationTestBase.CoreRunnerFramework) && - testEnvironment.TargetFramework.Equals(IntegrationTestBase.CoreRunnerFramework) ? 2 : 1; + int expectedNumberOfAttachments = 1; Assert.AreEqual(expectedNumberOfAttachments, this.runEventHandler.Attachments.Count); AssertCoverageResults(this.runEventHandler.Attachments); @@ -74,7 +73,7 @@ public void TestRunWithCodeCoverageParallel(RunnerInfo runnerInfo) // assert Assert.AreEqual(6, this.runEventHandler.TestResults.Count); - Assert.AreEqual(testEnvironment.RunnerFramework.Equals(IntegrationTestBase.DesktopRunnerFramework) ? 1 : 2, this.runEventHandler.Attachments.Count); + Assert.AreEqual(1, this.runEventHandler.Attachments.Count); AssertCoverageResults(this.runEventHandler.Attachments); } @@ -99,7 +98,7 @@ public async Task TestRunWithCodeCoverageAndAttachmentsProcessing(RunnerInfo run // Assert testRunAttachmentsProcessingEventHandler.EnsureSuccess(); - Assert.AreEqual(testEnvironment.RunnerFramework.Equals(IntegrationTestBase.DesktopRunnerFramework) ? 1 : 2, this.testRunAttachmentsProcessingEventHandler.Attachments.Count); + Assert.AreEqual(1, this.testRunAttachmentsProcessingEventHandler.Attachments.Count); AssertCoverageResults(this.testRunAttachmentsProcessingEventHandler.Attachments); @@ -121,7 +120,7 @@ public async Task TestRunWithCodeCoverageAndAttachmentsProcessing(RunnerInfo run Assert.AreEqual("Completed", testRunAttachmentsProcessingEventHandler.CompleteArgs.Metrics[TelemetryDataConstants.AttachmentsProcessingState]); Assert.AreEqual(2L, testRunAttachmentsProcessingEventHandler.CompleteArgs.Metrics[TelemetryDataConstants.NumberOfAttachmentsSentForProcessing]); - Assert.AreEqual(testEnvironment.RunnerFramework.Equals(IntegrationTestBase.DesktopRunnerFramework) ? 1L : 2L, testRunAttachmentsProcessingEventHandler.CompleteArgs.Metrics[TelemetryDataConstants.NumberOfAttachmentsAfterProcessing]); + Assert.AreEqual(1L, testRunAttachmentsProcessingEventHandler.CompleteArgs.Metrics[TelemetryDataConstants.NumberOfAttachmentsAfterProcessing]); Assert.IsTrue(testRunAttachmentsProcessingEventHandler.CompleteArgs.Metrics.ContainsKey(TelemetryDataConstants.TimeTakenInSecForAttachmentsProcessing)); Assert.IsTrue(File.Exists(runEventHandler.Attachments.First().Attachments.First().Uri.LocalPath)); @@ -148,7 +147,7 @@ public async Task TestRunWithCodeCoverageAndAttachmentsProcessingNoMetrics(Runne // Assert testRunAttachmentsProcessingEventHandler.EnsureSuccess(); - Assert.AreEqual(testEnvironment.RunnerFramework.Equals(IntegrationTestBase.DesktopRunnerFramework) ? 1 : 2, this.testRunAttachmentsProcessingEventHandler.Attachments.Count); + Assert.AreEqual(1, this.testRunAttachmentsProcessingEventHandler.Attachments.Count); AssertCoverageResults(this.testRunAttachmentsProcessingEventHandler.Attachments); @@ -195,7 +194,7 @@ public async Task TestRunWithCodeCoverageAndAttachmentsProcessingModuleDuplicate // Assert testRunAttachmentsProcessingEventHandler.EnsureSuccess(); - Assert.AreEqual(testEnvironment.RunnerFramework.Equals(IntegrationTestBase.DesktopRunnerFramework) ? 1 : 3, this.testRunAttachmentsProcessingEventHandler.Attachments.Count); + Assert.AreEqual(1, this.testRunAttachmentsProcessingEventHandler.Attachments.Count); AssertCoverageResults(this.testRunAttachmentsProcessingEventHandler.Attachments); @@ -217,7 +216,7 @@ public async Task TestRunWithCodeCoverageAndAttachmentsProcessingModuleDuplicate Assert.AreEqual("Completed", testRunAttachmentsProcessingEventHandler.CompleteArgs.Metrics[TelemetryDataConstants.AttachmentsProcessingState]); Assert.AreEqual(3L, testRunAttachmentsProcessingEventHandler.CompleteArgs.Metrics[TelemetryDataConstants.NumberOfAttachmentsSentForProcessing]); - Assert.AreEqual(testEnvironment.RunnerFramework.Equals(IntegrationTestBase.DesktopRunnerFramework) ? 1L : 3L, testRunAttachmentsProcessingEventHandler.CompleteArgs.Metrics[TelemetryDataConstants.NumberOfAttachmentsAfterProcessing]); + Assert.AreEqual(1L, testRunAttachmentsProcessingEventHandler.CompleteArgs.Metrics[TelemetryDataConstants.NumberOfAttachmentsAfterProcessing]); Assert.IsTrue(testRunAttachmentsProcessingEventHandler.CompleteArgs.Metrics.ContainsKey(TelemetryDataConstants.TimeTakenInSecForAttachmentsProcessing)); Assert.IsTrue(File.Exists(runEventHandler.Attachments.First().Attachments.First().Uri.LocalPath)); @@ -271,7 +270,7 @@ public async Task TestRunWithCodeCoverageAndAttachmentsProcessingCancelled(Runne Assert.IsTrue(testRunAttachmentsProcessingEventHandler.CompleteArgs.IsCanceled); Assert.IsNull(testRunAttachmentsProcessingEventHandler.CompleteArgs.Error); - Assert.IsTrue((testEnvironment.RunnerFramework.Equals(IntegrationTestBase.DesktopRunnerFramework) ? 3 : 0) <= testRunAttachmentsProcessingEventHandler.ProgressArgs.Count); + Assert.IsTrue(3 <= testRunAttachmentsProcessingEventHandler.ProgressArgs.Count); for (int i = 0; i < testRunAttachmentsProcessingEventHandler.ProgressArgs.Count; i++) { VisualStudio.TestPlatform.ObjectModel.Client.TestRunAttachmentsProcessingProgressEventArgs progressArgs = testRunAttachmentsProcessingEventHandler.ProgressArgs[i]; diff --git a/test/Microsoft.TestPlatform.Utilities.UnitTests/CodeCoverageDataAttachmentsHandlerTests.cs b/test/Microsoft.TestPlatform.Utilities.UnitTests/CodeCoverageDataAttachmentsHandlerTests.cs index ff89d295bd..b87bdc8dae 100644 --- a/test/Microsoft.TestPlatform.Utilities.UnitTests/CodeCoverageDataAttachmentsHandlerTests.cs +++ b/test/Microsoft.TestPlatform.Utilities.UnitTests/CodeCoverageDataAttachmentsHandlerTests.cs @@ -78,31 +78,5 @@ public async Task HandleDataCollectionAttachmentSetsShouldThrowIfCancellationReq mockProgressReporter.Verify(p => p.Report(It.IsAny()), Times.Never); } - - [TestMethod] - public async Task HandleDataCollectionAttachmentSetsShouldReturnExistingAttachmentsIfFailedToLoadLibrary() - { - var attachmentSet1 = new AttachmentSet(new Uri("//badrui//"), string.Empty); - attachmentSet1.Attachments.Add(new UriDataAttachment(new Uri("C:\\temp\\aa"), "coverage")); - - var attachmentSet2 = new AttachmentSet(new Uri("//badruj//"), string.Empty); - attachmentSet2.Attachments.Add(new UriDataAttachment(new Uri("C:\\temp\\ab"), "coverage")); - - CancellationTokenSource cts = new CancellationTokenSource(); - - Collection attachment = new Collection - { - attachmentSet1, - attachmentSet2 - }; - - var result = await coverageDataAttachmentsHandler.ProcessAttachmentSetsAsync(attachment, mockProgressReporter.Object, null, cts.Token); - - Assert.AreEqual(2, result.Count); - Assert.IsTrue(result.Contains(attachmentSet1)); - Assert.IsTrue(result.Contains(attachmentSet2)); - - mockProgressReporter.Verify(p => p.Report(It.IsAny()), Times.Never); - } } }