Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable Fakes Datacollector settings to be added in design mode #2586

Merged
merged 6 commits into from
Oct 15, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 32 additions & 10 deletions src/Microsoft.TestPlatform.Common/Utilities/FakesUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -104,12 +104,6 @@ private static bool TryAddFakesDataCollectorSettings(
IEnumerable<string> 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
Expand All @@ -120,19 +114,42 @@ private static bool TryAddFakesDataCollectorSettings(
{
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<string, FrameworkVersion> CreateDictionary(IEnumerable<string> sources, FrameworkVersion framework)
{
var dict = new Dictionary<string, FrameworkVersion>();
Expand Down Expand Up @@ -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;
}
Expand All @@ -290,7 +307,12 @@ internal static class FakesMetadata
/// <summary>
/// Gets the URI of the data collector
/// </summary>
public const string DataCollectorUri = "datacollector://microsoft/unittestisolation/1.0";
public const string DataCollectorUriV1 = "datacollector://microsoft/unittestisolation/1.0";

/// <summary>
/// Gets the URI of the data collector
/// </summary>
public const string DataCollectorUriV2 = "datacollector://microsoft/unittestisolation/2.0";

/// <summary>
/// Gets the assembly qualified name of the data collector type
Expand Down
3 changes: 2 additions & 1 deletion src/vstest.console/CommandLine/GenerateFakesUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ public static class GenerateFakesUtilities
internal static void GenerateFakesSettings(CommandLineOptions commandLineOptions, IEnumerable<string> 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)
vritant24 marked this conversation as resolved.
Show resolved Hide resolved
{
runSettingsXml = FakesUtilities.GenerateFakesSettingsForRunConfiguration(sources.ToArray(), runSettingsXml);
}
Expand Down
37 changes: 22 additions & 15 deletions src/vstest.console/TestPlatformHelpers/TestRequestManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

/// <summary>
/// Defines the TestRequestManger which can fire off discovery and test run requests
Expand Down Expand Up @@ -267,11 +266,19 @@ public void RunTests(TestRunRequestPayload testRunRequestPayload, ITestHostLaunc
this.LogTelemetryForLegacySettings(requestData, runsettings);
}

if (!commandLineOptions.IsDesignMode)
// get Fakes data collector settings
if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_Disable_Fakes_DataCollector_Configuration")))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Who would use this? We usually name env variables like this VSTEST__ (e.g. VSTEST_RUNNER_DEBUG`, and spell them in uppercase, in case some OSes would consider spelling when grabbing the variable. We also consider 0 to be off, not just null.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for the users in the vstest task. By Shreyas' suggestion, if something is being enabled that wasn't before, it's best to have a fallback to be able to replicate previous behavior. I can change the var name and behavior to meet the standard in the vstest repo

{
// 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())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 = @"<RunSettings><RunConfiguration><TargetFrameworkVersion>.netstandard,Version=5.0</TargetFrameworkVersion></RunConfiguration ></RunSettings>";
var generatedRunSettings = FakesUtilities.GenerateFakesSettingsForRunConfiguration(new string[] { }, runSettingsXml);
Assert.AreEqual(generatedRunSettings, runSettingsXml);
}

[TestMethod]
public void FakesSettingsShouldThrowExceptionIfSourcesArePassedAsNull()
{
Expand All @@ -35,9 +30,95 @@ public void FakesSettingsShouldThrowExceptionIfRunSettingsIsPassedAsNull()
[TestMethod]
public void FakesSettingsShouldBeNotGeneratedIfFakeConfiguratorAssemblyIsNotPresent()
{
string runSettingsXml = @"<RunSettings><RunConfiguration></RunConfiguration ></RunSettings>";
string runSettingsXml = @"<RunSettings><RunConfiguration></RunConfiguration></RunSettings>";
var generatedRunSettings = FakesUtilities.GenerateFakesSettingsForRunConfiguration(new string[] {@"C:\temp\UT.dll" }, runSettingsXml);
Assert.AreEqual(generatedRunSettings, runSettingsXml);
}

[TestMethod]
public void FakesDataCollectorSettingsShouldBeOverridden()
{
string runSettingsXml = @"<RunSettings><RunConfiguration></RunConfiguration></RunSettings>";
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 = @"<RunSettings><RunConfiguration></RunConfiguration></RunSettings>";
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 = @"<RunSettings><RunConfiguration><TargetFrameworkVersion>FrameworkCore10</TargetFrameworkVersion></RunConfiguration></RunSettings>";
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);
vritant24 marked this conversation as resolved.
Show resolved Hide resolved
Assert.IsTrue(XmlRunSettingsUtilities.ContainsDataCollector(doc, FakesUtilities.FakesMetadata.DataCollectorUriV2));
XmlNodeList nodes = doc.SelectNodes("//RunSettings/RunConfiguration/TargetFrameworkVersion");
Assert.AreEqual(nodes[0].InnerText, "FrameworkCore10");
}
}
}