diff --git a/src/DataCollectors/TraceDataCollector/Microsoft.VisualStudio.TraceDataCollector.csproj b/src/DataCollectors/TraceDataCollector/Microsoft.VisualStudio.TraceDataCollector.csproj index a1f23c7cae..b88a138708 100644 --- a/src/DataCollectors/TraceDataCollector/Microsoft.VisualStudio.TraceDataCollector.csproj +++ b/src/DataCollectors/TraceDataCollector/Microsoft.VisualStudio.TraceDataCollector.csproj @@ -15,6 +15,7 @@ + diff --git a/src/DataCollectors/TraceDataCollector/VanguardCollector/DynamicCoverageDataCollectorImpl.cs b/src/DataCollectors/TraceDataCollector/VanguardCollector/DynamicCoverageDataCollectorImpl.cs index bac2a03655..40a8a9a38f 100644 --- a/src/DataCollectors/TraceDataCollector/VanguardCollector/DynamicCoverageDataCollectorImpl.cs +++ b/src/DataCollectors/TraceDataCollector/VanguardCollector/DynamicCoverageDataCollectorImpl.cs @@ -11,6 +11,7 @@ namespace Microsoft.VisualStudio.Coverage using System.Xml; using Interfaces; using Microsoft.VisualStudio.TestPlatform.ObjectModel.DataCollection; + using Microsoft.VisualStudio.TestPlatform.Utilities; using TestPlatform.ObjectModel; using TraceCollector; using TraceCollector.Interfaces; @@ -107,10 +108,29 @@ public virtual void Initialize( IDataCollectionSink dataSink, IDataCollectionLogger logger) { + var defaultConfigurationElement = DynamicCoverageDataCollectorImpl.GetDefaultConfiguration(); + + try + { + var processor = new CodeCoverageRunSettingsProcessor(defaultConfigurationElement); + configurationElement = (XmlElement)processor.Process(configurationElement); + } + catch (Exception ex) + { + EqtTrace.Warning( + string.Format( + CultureInfo.CurrentCulture, + string.Join( + " ", + "DynamicCoverageDataCollectorImpl.Initialize: Exception encountered while processing the configuration element.", + "Keeping the configuration element unaltered. More info about the exception: {0}"), + ex.Message)); + } + EqtTrace.Info("DynamicCoverageDataCollectorImpl.Initialize: Initialize configuration. "); if (string.IsNullOrEmpty(configurationElement?.InnerXml)) { - configurationElement = DynamicCoverageDataCollectorImpl.GetDefaultConfiguration(); + configurationElement = defaultConfigurationElement; } this.logger = logger; diff --git a/src/Microsoft.TestPlatform.Utilities/CodeCoverageRunSettingsProcessor.cs b/src/Microsoft.TestPlatform.Utilities/CodeCoverageRunSettingsProcessor.cs new file mode 100644 index 0000000000..6e63832c43 --- /dev/null +++ b/src/Microsoft.TestPlatform.Utilities/CodeCoverageRunSettingsProcessor.cs @@ -0,0 +1,318 @@ +// 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.Utilities +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Xml; + using System.Xml.XPath; + + using Microsoft.VisualStudio.TestPlatform.ObjectModel; + + /// + /// Represents the run settings processor for code coverage data collectors. + /// + public class CodeCoverageRunSettingsProcessor + { + #region Members + /// + /// Represents the default settings loaded as an . + /// + private XmlNode defaultSettingsRootNode; + #endregion + + #region Constructors & Helpers + /// + /// Constructs an object. + /// + /// + /// The default settings root node. + public CodeCoverageRunSettingsProcessor(XmlNode defaultSettingsRootNode) + { + if (defaultSettingsRootNode == null) + { + throw new ArgumentNullException("Default settings root node is null."); + } + + this.defaultSettingsRootNode = defaultSettingsRootNode; + } + #endregion + + #region Public Interface + /// + /// Processes the current settings for the code coverage data collector. + /// + /// + /// The code coverage settings. + /// + /// An updated version of the current run settings. + public XmlNode Process(string currentSettings) + { + if (string.IsNullOrEmpty(currentSettings)) + { + return null; + } + + // Load current settings from string. + var document = new XmlDocument(); + document.LoadXml(currentSettings); + + return this.Process(document.DocumentElement); + } + + /// + /// Processes the current settings for the code coverage data collector. + /// + /// + /// + /// The code coverage settings document. + /// + /// + /// An updated version of the current run settings. + public XmlNode Process(XmlDocument currentSettingsDocument) + { + if (currentSettingsDocument == null) + { + return null; + } + + return this.Process(currentSettingsDocument.DocumentElement); + } + + /// + /// Processes the current settings for the code coverage data collector. + /// + /// + /// The code coverage root element. + /// + /// An updated version of the current run settings. + public XmlNode Process(XmlNode currentSettingsRootNode) + { + if (currentSettingsRootNode == null) + { + return null; + } + + // Get the code coverage node from the current settings. If unable to get any + // particular component down the path just add the default values for that component + // from the default settings document and return since there's nothing else to be done. + var codeCoveragePathComponents = new List() { "CodeCoverage" }; + var currentCodeCoverageNode = this.SelectNodeOrAddDefaults( + currentSettingsRootNode, + this.defaultSettingsRootNode, + codeCoveragePathComponents); + + // Cannot extract current code coverage node from the given settings so we bail out. + // However, the default code coverage node has already been added to the document's + // root. + if (currentCodeCoverageNode == null) + { + return currentSettingsRootNode; + } + + // Get the code coverage node from the default settings. + var defaultCodeCoverageNode = this.ExtractNode( + this.defaultSettingsRootNode, + this.BuildPath(codeCoveragePathComponents)); + + // Create the exclusion type list. + var exclusions = new List> + { + new List { "ModulePaths", "Exclude" }, + new List { "Attributes", "Exclude" }, + new List { "Sources", "Exclude" }, + new List { "Functions", "Exclude" } + }; + + foreach (var exclusion in exclusions) + { + // Get the node for the current exclusion type. If unable to get any + // particular component down the path just add the default values for that + // component from the default settings document and continue since there's nothing + // else to be done. + var currentNode = this.SelectNodeOrAddDefaults( + currentCodeCoverageNode, + defaultCodeCoverageNode, + exclusion); + + // Check if the node extraction was successful and we should process the current + // node in order to merge the current exclusion rules with the default ones. + if (currentNode == null) + { + continue; + } + + // Extract the node from the default settings. + var defaultNode = this.ExtractNode( + defaultCodeCoverageNode, + this.BuildPath(exclusion)); + + // Merge the current and default settings for the current exclusion rule. + this.MergeNodes(currentNode, defaultNode); + } + + return currentSettingsRootNode; + } + #endregion + + #region Private Methods + /// + /// Selects the node from the current settings node using the given + /// style path. If unable to select the requested node it adds + /// default settings along the path. + /// + /// + /// + /// The root node from the current settings document for the extraction. + /// + /// + /// The corresponding root node from the default settings document. + /// + /// The path components. + /// + /// The requested node if successful, otherwise. + private XmlNode SelectNodeOrAddDefaults( + XmlNode currentRootNode, + XmlNode defaultRootNode, + IList pathComponents) + { + var currentNode = currentRootNode; + var partialPath = new StringBuilder(); + + partialPath.Append("."); + + foreach (var component in pathComponents) + { + var currentPathComponent = "/" + component; + + // Append the current path component to the partial path. + partialPath.Append(currentPathComponent); + + // Extract the node corresponding to the latest path component. + var tempNode = this.ExtractNode(currentNode, "." + currentPathComponent); + + // Extraction is pruned here because we shouldn't be processing the current node. + if (tempNode != null && !this.ShouldProcessCurrentExclusion(tempNode)) + { + return null; + } + + // If the current node extraction is unsuccessful then add the corresponding + // default settings node and bail out. + if (tempNode == null) + { + var defaultNode = this.ExtractNode( + defaultRootNode, + partialPath.ToString()); + + var importedChild = currentNode.OwnerDocument.ImportNode(defaultNode, true); + currentNode.AppendChild(importedChild); + + return null; + } + + // Node corresponding to the latest path component is the new root node for the + // next extraction. + currentNode = tempNode; + } + + return currentNode; + } + + /// + /// Checks if we should process the current exclusion node. + /// + /// + /// The current exclusion node. + /// + /// + /// if the node should be processed, otherwise. + /// + private bool ShouldProcessCurrentExclusion(XmlNode node) + { + const string attributeName = "mergeDefaults"; + + foreach (XmlAttribute attribute in node.Attributes) + { + // If the attribute is present and set on 'false' we skip processing for the + // current exclusion. + if (attribute.Name == attributeName + && bool.TryParse(attribute.Value, out var value) + && !value) + { + return false; + } + } + + return true; + } + + /// + /// Assembles a relative path from the path given as components. + /// + /// + /// A relative path built from path components. + private string BuildPath(IList pathComponents) + { + return string.Join("/", new[] { "." }.Concat(pathComponents)); + } + + /// + /// Extracts the node specified by the current path using the provided node as root. + /// + /// + /// The root to be used for extraction. + /// The path used to specify the requested node. + /// + /// The extracted node if successful, otherwise. + private XmlNode ExtractNode(XmlNode node, string path) + { + try + { + return node.SelectSingleNode(path); + } + catch (XPathException ex) + { + EqtTrace.Error( + "CodeCoverageRunSettingsProcessor.ExtractNode: Cannot select single node \"{0}\".", + ex.Message); + } + + return null; + } + + /// + /// Merges the current settings rules with the default settings rules. + /// + /// + /// The current settings root node. + /// The default settings root node. + private void MergeNodes(XmlNode currentNode, XmlNode defaultNode) + { + var exclusionCache = new HashSet(); + + // Add current exclusions to the exclusion cache. + foreach (XmlNode child in currentNode.ChildNodes) + { + exclusionCache.Add(child.OuterXml); + } + + // Iterate through default exclusions and import missing ones. + foreach (XmlNode child in defaultNode.ChildNodes) + { + if (exclusionCache.Contains(child.OuterXml)) + { + continue; + } + + // Import missing default exclusions. + var importedChild = currentNode.OwnerDocument.ImportNode(child, true); + currentNode.AppendChild(importedChild); + } + } + #endregion + } +} diff --git a/test/DataCollectors/TraceDataCollector.UnitTests/DynamicCoverageDataCollectorImplTests.cs b/test/DataCollectors/TraceDataCollector.UnitTests/DynamicCoverageDataCollectorImplTests.cs index 82d2ee58aa..65b3610833 100644 --- a/test/DataCollectors/TraceDataCollector.UnitTests/DynamicCoverageDataCollectorImplTests.cs +++ b/test/DataCollectors/TraceDataCollector.UnitTests/DynamicCoverageDataCollectorImplTests.cs @@ -4,6 +4,7 @@ namespace Microsoft.VisualStudio.TraceDataCollector.UnitTests { using System; + using System.Collections.Generic; using System.ComponentModel; using System.Globalization; using System.IO; @@ -85,9 +86,8 @@ public void InitializeShouldCreateDefaultCodeCoverageSettingsIfConfigElementIsNu [TestMethod] public void InitializeShouldInitializeVanguardWithRightCoverageSettings() { - var expectedContent = "CoverageSettingsContent"; XmlElement configElement = - DynamicCoverageDataCollectorImplTests.CreateXmlElement($"{expectedContent}"); + DynamicCoverageDataCollectorImplTests.CreateXmlElement(@""); this.directoryHelperMock.Setup(d => d.CreateDirectory(It.IsAny())) .Callback((path) => @@ -101,8 +101,20 @@ public void InitializeShouldInitializeVanguardWithRightCoverageSettings() this.collectorImpl.Initialize(configElement, this.dataCollectionSinkMock.Object, this.dataCollectionLoggerMock.Object); + XmlDocument defaultDocument = new XmlDocument(); + defaultDocument.LoadXml(DynamicCoverageDataCollectorImplTests.GetDefaultCodeCoverageConfig()); + Assert.AreEqual(DynamicCoverageDataCollectorImplTests.DefaultConfigFileName, Path.GetFileName(this.aConfigFileName)); - Assert.AreEqual(expectedContent, File.ReadAllText(this.aConfigFileName)); + + XmlDocument currentDocument = new XmlDocument(); + currentDocument.LoadXml(File.ReadAllText(this.aConfigFileName)); + + var codeCoverageNodes = new Tuple(currentDocument.DocumentElement, defaultDocument.DocumentElement); + + this.CompareResults(codeCoverageNodes.Item1, codeCoverageNodes.Item2, "./ModulePaths/Exclude"); + this.CompareResults(codeCoverageNodes.Item1, codeCoverageNodes.Item2, "./Functions/Exclude"); + this.CompareResults(codeCoverageNodes.Item1, codeCoverageNodes.Item2, "./Attributes/Exclude"); + this.CompareResults(codeCoverageNodes.Item1, codeCoverageNodes.Item2, "./Sources/Exclude"); } [TestMethod] @@ -374,6 +386,58 @@ private void CompareWithDefaultConfig() File.ReadAllText(this.aConfigFileName).Replace(" ", string.Empty).Replace(Environment.NewLine, string.Empty)); } + private XmlNode ExtractNode(XmlNode node, string path) + { + try + { + return node.SelectSingleNode(path); + } + catch + { + } + + return null; + } + + private Tuple ExtractNodes(XmlNode currentSettingsRoot, XmlNode defaultSettingsRoot, string path) + { + var currentNode = this.ExtractNode(currentSettingsRoot, path); + var defaultNode = this.ExtractNode(defaultSettingsRoot, path); + Assert.IsNotNull(currentNode); + Assert.IsNotNull(defaultNode); + + return new Tuple(currentNode, defaultNode); + } + + private void CompareResults(XmlNode currentSettingsRoot, XmlNode defaultSettingsRoot, string path) + { + var nodes = this.ExtractNodes(currentSettingsRoot, defaultSettingsRoot, path); + + Assert.AreEqual(nodes.Item1.ChildNodes.Count, nodes.Item2.ChildNodes.Count); + + var set = new HashSet(); + foreach (XmlNode child in nodes.Item1.ChildNodes) + { + if (!set.Contains(child.OuterXml)) + { + set.Add(child.OuterXml); + } + } + + foreach (XmlNode child in nodes.Item2.ChildNodes) + { + if (!set.Contains(child.OuterXml)) + { + set.Add(child.OuterXml); + continue; + } + + set.Remove(child.OuterXml); + } + + Assert.AreEqual(set.Count, 0); + } + #endregion } } diff --git a/test/Microsoft.TestPlatform.Utilities.UnitTests/CodeCoverageRunSettingsProcessorTests.cs b/test/Microsoft.TestPlatform.Utilities.UnitTests/CodeCoverageRunSettingsProcessorTests.cs new file mode 100644 index 0000000000..7968ccee59 --- /dev/null +++ b/test/Microsoft.TestPlatform.Utilities.UnitTests/CodeCoverageRunSettingsProcessorTests.cs @@ -0,0 +1,284 @@ +// 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.TestPlatform.Utilities.UnitTests +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Reflection; + using System.Xml; + using Microsoft.VisualStudio.TestPlatform.Utilities; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class CodeCoverageRunSettingsProcessorTests + { + #region Members + private XmlElement defaultSettings; + + private CodeCoverageRunSettingsProcessor processor; + #endregion + + #region Constructors + public CodeCoverageRunSettingsProcessorTests() + { + this.defaultSettings = this.GetDefaultConfiguration(); + this.processor = new CodeCoverageRunSettingsProcessor(this.defaultSettings); + } + #endregion + + #region Test Methods + [TestMethod] + public void ProcessingShouldReturnNullForNullOrEmptySettings() + { + Assert.IsNull(processor.Process((string)null)); + Assert.IsNull(processor.Process("")); + + Assert.IsNull(processor.Process((XmlNode)null)); + + Assert.IsNull(processor.Process((XmlDocument)null)); + } + + [TestMethod] + public void MissingCodeCoverageTagShouldAddDefaultTag() + { + const string settings = ""; + string expected = $"{this.defaultSettings.OuterXml}"; + + Assert.AreEqual(expected, processor.Process(settings).OuterXml); + } + + [TestMethod] + public void EmptyCodeCoverageTagShouldAddDefaultTag() + { + const string settings = ""; + var processedNode = processor.Process(settings); + Assert.IsNotNull(processedNode); + + var codeCoverageNodes = this.ExtractNodes(processedNode, this.defaultSettings, "./CodeCoverage"); + + this.CompareResults(codeCoverageNodes.Item1, codeCoverageNodes.Item2, "./ModulePaths/Exclude"); + this.CompareResults(codeCoverageNodes.Item1, codeCoverageNodes.Item2, "./Functions/Exclude"); + this.CompareResults(codeCoverageNodes.Item1, codeCoverageNodes.Item2, "./Attributes/Exclude"); + this.CompareResults(codeCoverageNodes.Item1, codeCoverageNodes.Item2, "./Sources/Exclude"); + } + + [TestMethod] + public void MergeDefaultsDisabledShouldReturnInputUnaltered() + { + var settings = string.Join( + Environment.NewLine, + @"", + @" ", + @" ", + @" ", + @" ", + @" ", + @" ", + @" ", + @" .*\\atlmfc\\.*", + @" .*\\atlmbfc\\.*", + @" .*\\vctools\\.*", + @" .*\\public\\sdk2\\.*", + @" .*\\externalapis\\.*", + @" .*\\microsoft sdks\\.*", + @" .*\\vc\\include\\.*", + @" .*\\msclr\\.*", + @" .*\\ucrt\\.*", + @" ", + @" ", + @" ", + @" ", + @""); + + var document = new XmlDocument(); + document.LoadXml(settings); + + Assert.AreEqual(document.OuterXml, processor.Process(settings).OuterXml); + } + + [TestMethod] + public void MixedTestShouldCorrectlyAddMissingTags() + { + var settings = string.Join( + Environment.NewLine, + @"", + @" ", + @" ", + @" ", + @" ", + @" ", + @" ", + @" ", + @" .*\\atlmfc\\.*", + @" .*\\atlmbfc\\.*", + @" .*\\vctools\\.*", + @" .*\\public\\sdk2\\.*", + @" .*\\externalapis\\.*", + @" .*\\microsoft sdks\\.*", + @" .*\\vc\\include\\.*", + @" .*\\msclr\\.*", + @" .*\\ucrt\\.*", + @" ", + @" ", + @" ", + @""); + + var expectedResult = string.Join( + Environment.NewLine, + @"", + @" ", + @" ", + @" ", + @" .*CPPUnitTestFramework.*", + @" .*vstest.console.*", + @" .*microsoft.intellitrace.*", + @" .*testhost.*", + @" .*datacollector.*", + @" .*microsoft.teamfoundation.testplatform.*", + @" .*microsoft.visualstudio.testplatform.*", + @" .*microsoft.visualstudio.testwindow.*", + @" .*microsoft.visualstudio.mstest.*", + @" .*microsoft.visualstudio.qualitytools.*", + @" .*microsoft.vssdk.testhostadapter.*", + @" .*microsoft.vssdk.testhostframework.*", + @" .*qtagent32.*", + @" .*msvcr.*dll$", + @" .*msvcp.*dll$", + @" .*clr.dll$", + @" .*clr.ni.dll$", + @" .*clrjit.dll$", + @" .*clrjit.ni.dll$", + @" .*mscoree.dll$", + @" .*mscoreei.dll$", + @" .*mscoreei.ni.dll$", + @" .*mscorlib.dll$", + @" .*mscorlib.ni.dll$", + @" .*cryptbase.dll$", + @" .*bcryptPrimitives.dll$", + @" ", + @" ", + @" ", + @" ", + @" ^std::.*", + @" ^ATL::.*", + @" .*::__GetTestMethodInfo.*", + @" .*__CxxPureMSILEntry.*", + @" ^Microsoft::VisualStudio::CppCodeCoverageFramework::.*", + @" ^Microsoft::VisualStudio::CppUnitTestFramework::.*", + @" .*::YOU_CAN_ONLY_DESIGNATE_ONE_.*", + @" ^__.*", + @" .*::__.*", + @" ", + @" ", + @" ", + @" ", + @" ^System.Diagnostics.DebuggerHiddenAttribute$", + @" ^System.Diagnostics.DebuggerNonUserCodeAttribute$", + @" System.Runtime.CompilerServices.CompilerGeneratedAttribute$", + @" ^System.CodeDom.Compiler.GeneratedCodeAttribute$", + @" ^System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute$", + @" ^Microsoft.VisualStudio.TestPlatform.TestSDKAutoGeneratedCode.*", + @" ", + @" ", + @" ", + @" ", + @" .*\\atlmfc\\.*", + @" .*\\atlmbfc\\.*", + @" .*\\vctools\\.*", + @" .*\\public\\sdk2\\.*", + @" .*\\externalapis\\.*", + @" .*\\microsoft sdks\\.*", + @" .*\\vc\\include\\.*", + @" .*\\msclr\\.*", + @" .*\\ucrt\\.*", + @" .*\\public\\sdk\\.*", + @" ", + @" ", + @" ", + @""); + + var expectedResultDocument = new XmlDocument(); + expectedResultDocument.LoadXml(expectedResult); + + var processedNode = processor.Process(settings); + Assert.IsNotNull(processedNode); + + var codeCoverageNodes = this.ExtractNodes(processedNode, expectedResultDocument.DocumentElement, "./CodeCoverage"); + + this.CompareResults(codeCoverageNodes.Item1, codeCoverageNodes.Item2, "./ModulePaths/Exclude"); + this.CompareResults(codeCoverageNodes.Item1, codeCoverageNodes.Item2, "./Functions/Exclude"); + this.CompareResults(codeCoverageNodes.Item1, codeCoverageNodes.Item2, "./Attributes/Exclude"); + this.CompareResults(codeCoverageNodes.Item1, codeCoverageNodes.Item2, "./Sources/Exclude"); + } + #endregion + + #region Helpers + private XmlNode ExtractNode(XmlNode node, string path) + { + try + { + return node.SelectSingleNode(path); + } + catch + { + } + + return null; + } + + private XmlElement GetDefaultConfiguration() + { + var document = new XmlDocument(); + Assembly assembly = typeof(CodeCoverageRunSettingsProcessorTests).GetTypeInfo().Assembly; + using (Stream stream = assembly.GetManifestResourceStream( + "Microsoft.TestPlatform.Utilities.UnitTests.DefaultCodeCoverageConfig.xml")) + { + document.Load(stream); + } + + return document.DocumentElement; + } + + private Tuple ExtractNodes(XmlNode currentSettingsRoot, XmlNode defaultSettingsRoot, string path) + { + var currentNode = this.ExtractNode(currentSettingsRoot, path); + var defaultNode = this.ExtractNode(defaultSettingsRoot, path); + Assert.IsNotNull(currentNode); + Assert.IsNotNull(defaultNode); + + return new Tuple(currentNode, defaultNode); + } + + private void CompareResults(XmlNode currentSettingsRoot, XmlNode defaultSettingsRoot, string path) + { + var nodes = this.ExtractNodes(currentSettingsRoot, defaultSettingsRoot, path); + + Assert.AreEqual(nodes.Item1.ChildNodes.Count, nodes.Item2.ChildNodes.Count); + + var set = new HashSet(); + foreach (XmlNode child in nodes.Item1.ChildNodes) + { + if (!set.Contains(child.OuterXml)) + { + set.Add(child.OuterXml); + } + } + + foreach (XmlNode child in nodes.Item2.ChildNodes) + { + if (!set.Contains(child.OuterXml)) + { + set.Add(child.OuterXml); + continue; + } + + set.Remove(child.OuterXml); + } + + Assert.AreEqual(set.Count, 0); + } + #endregion + } +} diff --git a/test/Microsoft.TestPlatform.Utilities.UnitTests/DefaultCodeCoverageConfig.xml b/test/Microsoft.TestPlatform.Utilities.UnitTests/DefaultCodeCoverageConfig.xml new file mode 100644 index 0000000000..3bc0b33877 --- /dev/null +++ b/test/Microsoft.TestPlatform.Utilities.UnitTests/DefaultCodeCoverageConfig.xml @@ -0,0 +1,77 @@ + + + + + + .*CPPUnitTestFramework.* + .*vstest.console.* + .*microsoft.intellitrace.* + .*testhost.* + .*datacollector.* + .*microsoft.teamfoundation.testplatform.* + .*microsoft.visualstudio.testplatform.* + .*microsoft.visualstudio.testwindow.* + .*microsoft.visualstudio.mstest.* + .*microsoft.visualstudio.qualitytools.* + .*microsoft.vssdk.testhostadapter.* + .*microsoft.vssdk.testhostframework.* + .*qtagent32.* + .*msvcr.*dll$ + .*msvcp.*dll$ + .*clr.dll$ + .*clr.ni.dll$ + .*clrjit.dll$ + .*clrjit.ni.dll$ + .*mscoree.dll$ + .*mscoreei.dll$ + .*mscoreei.ni.dll$ + .*mscorlib.dll$ + .*mscorlib.ni.dll$ + .*cryptbase.dll$ + .*bcryptPrimitives.dll$ + + + True + True + True + false + + + + ^std::.* + ^ATL::.* + .*::__GetTestMethodInfo.* + .*__CxxPureMSILEntry.* + ^Microsoft::VisualStudio::CppCodeCoverageFramework::.* + ^Microsoft::VisualStudio::CppUnitTestFramework::.* + .*::YOU_CAN_ONLY_DESIGNATE_ONE_.* + ^__.* + .*::__.* + + + + + ^System.Diagnostics.DebuggerHiddenAttribute$ + ^System.Diagnostics.DebuggerNonUserCodeAttribute$ + System.Runtime.CompilerServices.CompilerGeneratedAttribute$ + ^System.CodeDom.Compiler.GeneratedCodeAttribute$ + ^System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute$ + ^Microsoft.VisualStudio.TestPlatform.TestSDKAutoGeneratedCode.* + + + + + .*\\atlmfc\\.* + .*\\vctools\\.* + .*\\public\\sdk\\.* + .*\\externalapis\\.* + .*\\microsoft sdks\\.* + .*\\vc\\include\\.* + .*\\msclr\\.* + .*\\ucrt\\.* + + + + + + \ No newline at end of file diff --git a/test/Microsoft.TestPlatform.Utilities.UnitTests/Microsoft.TestPlatform.Utilities.UnitTests.csproj b/test/Microsoft.TestPlatform.Utilities.UnitTests/Microsoft.TestPlatform.Utilities.UnitTests.csproj index b123a6bb4c..d0c2957dff 100644 --- a/test/Microsoft.TestPlatform.Utilities.UnitTests/Microsoft.TestPlatform.Utilities.UnitTests.csproj +++ b/test/Microsoft.TestPlatform.Utilities.UnitTests/Microsoft.TestPlatform.Utilities.UnitTests.csproj @@ -24,5 +24,8 @@ + + +