diff --git a/src/Microsoft.TestPlatform.Common/Utilities/FakesUtilities.cs b/src/Microsoft.TestPlatform.Common/Utilities/FakesUtilities.cs index adb4ce29d9..2e2ef87189 100644 --- a/src/Microsoft.TestPlatform.Common/Utilities/FakesUtilities.cs +++ b/src/Microsoft.TestPlatform.Common/Utilities/FakesUtilities.cs @@ -9,7 +9,7 @@ namespace Microsoft.VisualStudio.TestPlatform.Common.Utilities using System.IO; using System.Reflection; using System.Xml; - + using System.Xml.XPath; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities; @@ -104,12 +104,6 @@ public static string GenerateFakesSettingsForRunConfiguration(string[] sources, IEnumerable sources, FrameworkVersion framework) { - // If user provided fakes settings don't do anything - if (XmlRunSettingsUtilities.ContainsDataCollector(runSettings.CreateNavigator(), FakesMetadata.DataCollectorUri)) - { - return false; - } - // A new Fakes Congigurator API makes the decision to add the right datacollector uri to the configuration // There now exist two data collector URIs to support two different scenarios. The new scenario involves // using the CLRIE profiler, and the old involves using the Intellitrace profiler (which isn't supported in @@ -120,19 +114,42 @@ public static string GenerateFakesSettingsForRunConfiguration(string[] sources, { var sourceTFMMap = CreateDictionary(sources, framework); var fakesSettings = crossPlatformConfigurator(sourceTFMMap); + // if no fakes, return settings unchanged if (fakesSettings == null) { return false; } - XmlRunSettingsUtilities.InsertDataCollectorsNode(runSettings.CreateNavigator(), fakesSettings); + InsertOrReplaceFakesDataCollectorNode(runSettings, fakesSettings); return true; } return AddFallbackFakesSettings(runSettings, sources, framework); } + internal static void InsertOrReplaceFakesDataCollectorNode(XmlDocument runSettings, DataCollectorSettings settings) + { + // override current settings + var navigator = runSettings.CreateNavigator(); + var nodes = navigator.Select("/RunSettings/DataCollectionRunSettings/DataCollectors/DataCollector"); + + foreach (XPathNavigator dataCollectorNavigator in nodes) + { + var uri = dataCollectorNavigator.GetAttribute("uri", string.Empty); + // We assume that only one uri can exist in a given runsettings + if (string.Equals(FakesMetadata.DataCollectorUriV1, uri, StringComparison.OrdinalIgnoreCase) || + string.Equals(FakesMetadata.DataCollectorUriV2, uri, StringComparison.OrdinalIgnoreCase)) + { + dataCollectorNavigator.ReplaceSelf(settings.ToXml().CreateNavigator()); + return; + } + } + + // insert new node + XmlRunSettingsUtilities.InsertDataCollectorsNode(runSettings.CreateNavigator(), settings); + } + private static IDictionary CreateDictionary(IEnumerable sources, FrameworkVersion framework) { var dict = new Dictionary(); @@ -275,7 +292,7 @@ private static DataCollectorSettings CreateFakesDataCollectorSettings() AssemblyQualifiedName = FakesMetadata.DataCollectorAssemblyQualifiedName, FriendlyName = FakesMetadata.FriendlyName, IsEnabled = true, - Uri = new Uri(FakesMetadata.DataCollectorUri) + Uri = new Uri(FakesMetadata.DataCollectorUriV1) }; return settings; } @@ -290,7 +307,12 @@ internal static class FakesMetadata /// /// Gets the URI of the data collector /// - public const string DataCollectorUri = "datacollector://microsoft/unittestisolation/1.0"; + public const string DataCollectorUriV1 = "datacollector://microsoft/unittestisolation/1.0"; + + /// + /// Gets the URI of the data collector + /// + public const string DataCollectorUriV2 = "datacollector://microsoft/unittestisolation/2.0"; /// /// Gets the assembly qualified name of the data collector type diff --git a/src/vstest.console/CommandLine/GenerateFakesUtilities.cs b/src/vstest.console/CommandLine/GenerateFakesUtilities.cs index 72aed21207..eb46ffc394 100644 --- a/src/vstest.console/CommandLine/GenerateFakesUtilities.cs +++ b/src/vstest.console/CommandLine/GenerateFakesUtilities.cs @@ -14,7 +14,8 @@ public static class GenerateFakesUtilities internal static void GenerateFakesSettings(CommandLineOptions commandLineOptions, IEnumerable sources, ref string runSettingsXml) { // dynamically compute the fakes datacollector settings - if (!commandLineOptions.DisableAutoFakes) + // This runs with or without design mode. + if (commandLineOptions == null || !commandLineOptions.DisableAutoFakes) { runSettingsXml = FakesUtilities.GenerateFakesSettingsForRunConfiguration(sources.ToArray(), runSettingsXml); } diff --git a/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs b/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs index ad3fa2ccef..5832a59534 100644 --- a/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs +++ b/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs @@ -3,21 +3,12 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.TestPlatformHelpers { - using System; - using System.Xml; - using System.IO; - using System.Linq; - using System.Xml.XPath; - using System.Threading; - using System.Reflection; - using System.Globalization; - using System.Threading.Tasks; - using System.Collections.Generic; using Microsoft.VisualStudio.TestPlatform.Client; using Microsoft.VisualStudio.TestPlatform.Client.RequestHelper; using Microsoft.VisualStudio.TestPlatform.CommandLine.Internal; using Microsoft.VisualStudio.TestPlatform.CommandLine.Processors.Utilities; using Microsoft.VisualStudio.TestPlatform.CommandLine.Publisher; + using Microsoft.VisualStudio.TestPlatform.CommandLine.Resources; using Microsoft.VisualStudio.TestPlatform.CommandLineUtilities; using Microsoft.VisualStudio.TestPlatform.Common; using Microsoft.VisualStudio.TestPlatform.Common.Interfaces; @@ -34,7 +25,15 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.TestPlatformHelpers using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions; using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; using Microsoft.VisualStudio.TestPlatform.Utilities; - using Microsoft.VisualStudio.TestPlatform.CommandLine.Resources; + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Reflection; + using System.Threading; + using System.Threading.Tasks; + using System.Xml; + using System.Xml.XPath; /// /// Defines the TestRequestManger which can fire off discovery and test run requests @@ -267,11 +266,19 @@ public void RunTests(TestRunRequestPayload testRunRequestPayload, ITestHostLaunc this.LogTelemetryForLegacySettings(requestData, runsettings); } - if (!commandLineOptions.IsDesignMode) + // get Fakes data collector settings + if (!string.Equals(Environment.GetEnvironmentVariable("VSTEST_SKIP_FAKES_CONFIGURATION"), "1")) { - // Generate fakes settings only for command line scenarios. In case of - // Editors/IDEs, this responsibility is with the caller. - GenerateFakesUtilities.GenerateFakesSettings(this.commandLineOptions, this.commandLineOptions.Sources.ToList(), ref runsettings); + // The commandline Options do not have sources in design time mode, + // and so we fall back to using sources instead + if (this.commandLineOptions.Sources.Any()) + { + GenerateFakesUtilities.GenerateFakesSettings(this.commandLineOptions, this.commandLineOptions.Sources.ToList(), ref runsettings); + } + else if (sources.Any()) + { + GenerateFakesUtilities.GenerateFakesSettings(this.commandLineOptions, sources, ref runsettings); + } } if (testRunRequestPayload.Sources != null && testRunRequestPayload.Sources.Any()) diff --git a/test/Microsoft.TestPlatform.Common.UnitTests/Utilities/FakesUtilitiesTests.cs b/test/Microsoft.TestPlatform.Common.UnitTests/Utilities/FakesUtilitiesTests.cs index dc862ac7d3..1d286ace96 100644 --- a/test/Microsoft.TestPlatform.Common.UnitTests/Utilities/FakesUtilitiesTests.cs +++ b/test/Microsoft.TestPlatform.Common.UnitTests/Utilities/FakesUtilitiesTests.cs @@ -4,21 +4,16 @@ namespace TestPlatform.Common.UnitTests.Utilities { using System; + using System.IO; + using System.Xml; using Microsoft.VisualStudio.TestPlatform.Common.Utilities; + using Microsoft.VisualStudio.TestPlatform.ObjectModel; + using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities; using Microsoft.VisualStudio.TestTools.UnitTesting; [TestClass] public class FakesUtilitiesTests { - - [TestMethod] - public void FakesSettingsShouldBeNotGeneratedIfTargetFrameWorkIsNetCore() - { - string runSettingsXml = @".netstandard,Version=5.0"; - var generatedRunSettings = FakesUtilities.GenerateFakesSettingsForRunConfiguration(new string[] { }, runSettingsXml); - Assert.AreEqual(generatedRunSettings, runSettingsXml); - } - [TestMethod] public void FakesSettingsShouldThrowExceptionIfSourcesArePassedAsNull() { @@ -35,9 +30,95 @@ public void FakesSettingsShouldThrowExceptionIfRunSettingsIsPassedAsNull() [TestMethod] public void FakesSettingsShouldBeNotGeneratedIfFakeConfiguratorAssemblyIsNotPresent() { - string runSettingsXml = @""; + string runSettingsXml = @""; var generatedRunSettings = FakesUtilities.GenerateFakesSettingsForRunConfiguration(new string[] {@"C:\temp\UT.dll" }, runSettingsXml); Assert.AreEqual(generatedRunSettings, runSettingsXml); } + + [TestMethod] + public void FakesDataCollectorSettingsShouldBeOverridden() + { + string runSettingsXml = @""; + var doc = new XmlDocument(); + using (var xmlReader = XmlReader.Create( + new StringReader(runSettingsXml), + new XmlReaderSettings() { CloseInput = true })) + { + doc.Load(xmlReader); + } + + var dataCollectorNode = new DataCollectorSettings() + { + AssemblyQualifiedName = FakesUtilities.FakesMetadata.DataCollectorAssemblyQualifiedName, + Uri = new Uri(FakesUtilities.FakesMetadata.DataCollectorUriV1), + FriendlyName = FakesUtilities.FakesMetadata.FriendlyName, + IsEnabled = true, + Configuration = doc.FirstChild as XmlElement + }; + XmlRunSettingsUtilities.InsertDataCollectorsNode(doc.CreateNavigator(), dataCollectorNode); + + var dataCollectorNode2 = new DataCollectorSettings() + { + AssemblyQualifiedName = FakesUtilities.FakesMetadata.DataCollectorAssemblyQualifiedName, + Uri = new Uri(FakesUtilities.FakesMetadata.DataCollectorUriV2), + FriendlyName = FakesUtilities.FakesMetadata.FriendlyName, + IsEnabled = true, + Configuration = doc.FirstChild as XmlElement + }; + FakesUtilities.InsertOrReplaceFakesDataCollectorNode(doc, dataCollectorNode2); + + Assert.IsFalse(XmlRunSettingsUtilities.ContainsDataCollector(doc, FakesUtilities.FakesMetadata.DataCollectorUriV1)); + Assert.IsTrue(XmlRunSettingsUtilities.ContainsDataCollector(doc, FakesUtilities.FakesMetadata.DataCollectorUriV2)); + } + + [TestMethod] + public void FakesDataCollectorSettingsShouldBeInserted() + { + string runSettingsXml = @""; + var doc = new XmlDocument(); + using (var xmlReader = XmlReader.Create( + new StringReader(runSettingsXml), + new XmlReaderSettings() { CloseInput = true })) + { + doc.Load(xmlReader); + } + + var dataCollectorNode2 = new DataCollectorSettings() + { + AssemblyQualifiedName = FakesUtilities.FakesMetadata.DataCollectorAssemblyQualifiedName, + Uri = new Uri(FakesUtilities.FakesMetadata.DataCollectorUriV2), + FriendlyName = FakesUtilities.FakesMetadata.FriendlyName, + IsEnabled = true, + Configuration = doc.FirstChild as XmlElement + }; + FakesUtilities.InsertOrReplaceFakesDataCollectorNode(doc, dataCollectorNode2); + Assert.IsTrue(XmlRunSettingsUtilities.ContainsDataCollector(doc, FakesUtilities.FakesMetadata.DataCollectorUriV2)); + } + + [TestMethod] + public void OtherRunsettingsShouldNotBeChanged() + { + string runSettingsXml = @"FrameworkCore10"; + var doc = new XmlDocument(); + using (var xmlReader = XmlReader.Create( + new StringReader(runSettingsXml), + new XmlReaderSettings() { CloseInput = true })) + { + doc.Load(xmlReader); + } + + var dataCollectorNode2 = new DataCollectorSettings() + { + AssemblyQualifiedName = FakesUtilities.FakesMetadata.DataCollectorAssemblyQualifiedName, + Uri = new Uri(FakesUtilities.FakesMetadata.DataCollectorUriV2), + FriendlyName = FakesUtilities.FakesMetadata.FriendlyName, + IsEnabled = true, + Configuration = doc.CreateElement("Configuration") + }; + FakesUtilities.InsertOrReplaceFakesDataCollectorNode(doc, dataCollectorNode2); + Assert.IsTrue(XmlRunSettingsUtilities.ContainsDataCollector(doc, FakesUtilities.FakesMetadata.DataCollectorUriV2)); + XmlNodeList nodes = doc.SelectNodes("//RunSettings/RunConfiguration/TargetFrameworkVersion"); + Assert.AreEqual(nodes[0].InnerText, "FrameworkCore10"); + } } }