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 code coverage when "Code Coverage;arg1=val1;arg2=val2" is provided in cli #3172

Merged
merged 14 commits into from
Nov 16, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
Adding elements to code coverage config passed via commandline,
e.g.
Input:
--collect:"Code Coverage;CLRIEInstrumentationNetCore=true;CLRIEInstrumentationNetFramework=false"

Output:
      <DataCollector friendlyName="Code Coverage" enabled="True">
        <Configuration>
          <CLRIEInstrumentationNetCore>true</CLRIEInstrumentationNetCore>
          <CLRIEInstrumentationNetFramework>false</CLRIEInstrumentationNetFramework>
        </Configuration>
      </DataCollector>
  • Loading branch information
fhnaseer committed Nov 10, 2021
commit 88da72d58db89c4bb9f9e53c28b092bf6ce51c9f
73 changes: 60 additions & 13 deletions src/vstest.console/Processors/CollectArgumentProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.Processors
{
using System;
using System.Collections.Generic;

using System.Globalization;
using System.IO;
using System.Linq;
using System.Xml;
using Microsoft.VisualStudio.TestPlatform.CommandLine.Processors.Utilities;
using Microsoft.VisualStudio.TestPlatform.Common;
using Microsoft.VisualStudio.TestPlatform.Common.Interfaces;
using Microsoft.VisualStudio.TestPlatform.Common.Utilities;
Expand Down Expand Up @@ -108,21 +110,22 @@ public void Initialize(string argument)
// 1. Disable all other data collectors. Enable only those data collectors that are explicitly specified by user.
// 2. Check if Code Coverage Data Collector is specified in runsettings, if not add it and also set enable to true.

string exceptionMessage = string.Format(CultureInfo.CurrentUICulture, CommandLineResources.DataCollectorFriendlyNameInvalid, argument);

// if argument is null or doesn't contain any element, don't do anything.
if (string.IsNullOrWhiteSpace(argument))
{
throw new CommandLineException(
string.Format(
CultureInfo.CurrentUICulture,
CommandLineResources.DataCollectorFriendlyNameInvalid,
argument));
throw new CommandLineException(exceptionMessage);
}

// Get collect argument list.
var collectArgumentList = ArgumentProcessorUtilities.GetArgumentList(argument, ArgumentProcessorUtilities.SemiColonArgumentSeparator, exceptionMessage);

if (InferRunSettingsHelper.IsTestSettingsEnabled(this.runSettingsManager.ActiveRunSettings.SettingsXml))
{
throw new SettingsException(string.Format(CommandLineResources.CollectWithTestSettingErrorMessage, argument));
}
AddDataCollectorToRunSettings(argument, this.runSettingsManager, this.fileHelper);
AddDataCollectorToRunSettings(collectArgumentList, this.runSettingsManager, this.fileHelper, exceptionMessage);
}

/// <summary>
Expand All @@ -149,7 +152,7 @@ public ArgumentProcessorResult Execute()
return ArgumentProcessorResult.Success;
}

internal static void EnableDataCollectorUsingFriendlyName(string argument, DataCollectionRunSettings dataCollectionRunSettings)
internal static DataCollectorSettings EnableDataCollectorUsingFriendlyName(string argument, DataCollectionRunSettings dataCollectionRunSettings)
{
DataCollectorSettings dataCollectorSettings = null;

Expand All @@ -164,6 +167,38 @@ internal static void EnableDataCollectorUsingFriendlyName(string argument, DataC
{
dataCollectorSettings.IsEnabled = true;
}

return dataCollectorSettings;
}

private static void AddDataCollectorConfigurations(string[] configurations, DataCollectorSettings dataCollectorSettings, string exceptionMessage)
{
if (dataCollectorSettings.Configuration == null)
{
XmlDocument doc = new XmlDocument();
dataCollectorSettings.Configuration = doc.CreateElement("Configuration");
}

foreach (var configuration in configurations)
{
var keyValuePair = ArgumentProcessorUtilities.GetArgumentList(configuration, ArgumentProcessorUtilities.EqualNameValueSeparator, exceptionMessage);

if (keyValuePair.Length == 2)
{
AddConfiguration(dataCollectorSettings.Configuration, keyValuePair[0], keyValuePair[1]);
}
else
{
throw new CommandLineException(exceptionMessage);
}
}
}

private static void AddConfiguration(XmlElement configuration, string configurationName, string configurationValue)
{
XmlElement attribute = configuration.OwnerDocument.CreateElement(configurationName);
attribute.InnerText = configurationValue;
configuration.AppendChild(attribute);
}

/// <summary>
Expand Down Expand Up @@ -209,9 +244,16 @@ private static bool DoesDataCollectorSettingsExist(string friendlyName,
return false;
}

internal static void AddDataCollectorToRunSettings(string argument, IRunSettingsProvider runSettingsManager, IFileHelper fileHelper)
internal static void AddDataCollectorToRunSettings(string arguments, IRunSettingsProvider runSettingsManager, IFileHelper fileHelper)
{
EnabledDataCollectors.Add(argument.ToLower());
AddDataCollectorToRunSettings(new string[] { arguments }, runSettingsManager, fileHelper, string.Empty);
}

internal static void AddDataCollectorToRunSettings(string[] arguments, IRunSettingsProvider runSettingsManager, IFileHelper fileHelper, string exceptionMessage)
{
var collectorName = arguments[0];
var additionalConfigurations = arguments.Skip(1).ToArray();
EnabledDataCollectors.Add(collectorName.ToLower());

var settings = runSettingsManager.ActiveRunSettings?.SettingsXml;
if (settings == null)
Expand All @@ -228,14 +270,19 @@ internal static void AddDataCollectorToRunSettings(string argument, IRunSettings
Constants.InProcDataCollectorSettingName);

// Add data collectors if not already present, enable if already present.
EnableDataCollectorUsingFriendlyName(argument, dataCollectionRunSettings);
var dataCollectorSettings = EnableDataCollectorUsingFriendlyName(collectorName, dataCollectionRunSettings);

if (additionalConfigurations.Length > 0)
{
AddDataCollectorConfigurations(additionalConfigurations, dataCollectorSettings, exceptionMessage);
}

runSettingsManager.UpdateRunSettingsNodeInnerXml(Constants.DataCollectionRunSettingsName, dataCollectionRunSettings.ToXml().InnerXml);

if (string.Equals(argument, CoverletConstants.CoverletDataCollectorFriendlyName, StringComparison.OrdinalIgnoreCase))
if (string.Equals(collectorName, CoverletConstants.CoverletDataCollectorFriendlyName, StringComparison.OrdinalIgnoreCase))
{
// Add in-proc data collector to runsettings if coverlet code coverage is enabled
EnableCoverletInProcDataCollector(argument, inProcDataCollectionRunSettings, runSettingsManager, fileHelper);
EnableCoverletInProcDataCollector(collectorName, inProcDataCollectionRunSettings, runSettingsManager, fileHelper);
runSettingsManager.UpdateRunSettingsNodeInnerXml(Constants.InProcDataCollectionRunSettingsName, inProcDataCollectionRunSettings.ToXml().InnerXml);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ internal class EnableCodeCoverageArgumentExecutor : IArgumentExecutor
private CommandLineOptions commandLineOptions;
private IFileHelper fileHelper;

private const string FriendlyName = "Code Coverage";
internal const string FriendlyName = "Code Coverage";

private static string xPathSeperator = "/";
private static string[] nodeNames = new string[] { Constants.RunSettingsName, Constants.DataCollectionRunSettingsName, Constants.DataCollectorsSettingName, Constants.DataCollectorSettingName };
Expand Down