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

Generation of CodeCoverage.deps.json file #2627

Merged
merged 1 commit into from
Nov 12, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion scripts/verify-nupkgs.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function Verify-Nuget-Packages($packageDirectory)
{
Write-Log "Starting Verify-Nuget-Packages."
$expectedNumOfFiles = @{
"Microsoft.CodeCoverage" = 43;
"Microsoft.CodeCoverage" = 44;
"Microsoft.NET.Test.Sdk" = 18;
"Microsoft.TestPlatform" = 488;
"Microsoft.TestPlatform.Build" = 19;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,13 @@ public class DynamicCoverageDataCollector : BaseDataCollector
private const string ClrIeDisableCodeSignatureValidationVariable = @"MicrosoftInstrumentationEngine_DisableCodeSignatureValidation";
private const string ClrieFileLogPathVariable = @"MicrosoftInstrumentationEngine_FileLogPath";

private const string InjectDotnetAdditionalDepsSettingName = "InjectDotnetAdditionalDeps";
private const string VanguardDotnetAdditionalDepsVariable = "VANGUARD_DOTNET_ADDITIONAL_DEPS";

private readonly IEnvironment environment;
private bool useClrIeInstrumentationForNetCore;
private bool useClrIeInstrumentationForNetFramework;
private bool injectDotnetAdditionalDeps;

/// <summary>
/// Data collector implementation
Expand Down Expand Up @@ -116,6 +120,7 @@ protected override void OnInitialize(XmlElement configurationElement)
{
this.useClrIeInstrumentationForNetCore = IsClrInstrumentationEnabled(configurationElement, ClrIeInstrumentationForNetCoreSettingName, ClrIeInstrumentationForNetCoreVariable);
this.useClrIeInstrumentationForNetFramework = IsClrInstrumentationEnabled(configurationElement, ClrIeInstrumentationForNetFrameworkSettingName, ClrIeInstrumentationForNetFrameworkVariable);
this.injectDotnetAdditionalDeps = GetConfigurationValue(configurationElement, InjectDotnetAdditionalDepsSettingName) ?? true;

this.implementation.Initialize(configurationElement, this.DataSink, this.Logger);
this.Events.SessionStart += this.SessionStart;
Expand Down Expand Up @@ -177,6 +182,11 @@ protected override IEnumerable<KeyValuePair<string, string>> GetEnvironmentVaria
envVaribles.Add(new KeyValuePair<string, string>(ClrieFileLogPathVariable, Path.Combine(Path.GetTempPath(), this.implementation.GetSessionName(), Guid.NewGuid() + ".log")));
}

if (this.injectDotnetAdditionalDeps && !string.IsNullOrEmpty(this.implementation.CodeCoverageDepsJsonFilePath))
{
envVaribles.Add(new KeyValuePair<string, string>(VanguardDotnetAdditionalDepsVariable, this.implementation.CodeCoverageDepsJsonFilePath));
}

if (EqtTrace.IsInfoEnabled)
{
EqtTrace.Info("DynamicCoverageDataCollector.GetEnvironmentVariables: Returning following environment variables: {0}", string.Join(",", envVaribles));
Expand All @@ -194,10 +204,9 @@ protected override IEnumerable<KeyValuePair<string, string>> GetEnvironmentVaria
/// <returns>If CLR IE should be enabled</returns>
private static bool IsClrInstrumentationEnabled(XmlElement configurationElement, string configurationSettingName, string environmentVariableName)
{
XmlElement configurationSetting = configurationElement != null ? configurationElement[configurationSettingName] : null;
string configurationSettingValue = configurationSetting != null ? configurationSetting.InnerText : null;
var clrInstrumentationEnabledByConfiguration = GetConfigurationValue(configurationElement, configurationSettingName);

if (bool.TryParse(configurationSettingValue, out var clrInstrumentationEnabled) && clrInstrumentationEnabled)
if (clrInstrumentationEnabledByConfiguration == true)
{
return true;
}
Expand All @@ -211,6 +220,22 @@ private static bool IsClrInstrumentationEnabled(XmlElement configurationElement,
return int.TryParse(environmentVariableValue, out var environmentVariableIntValue) && environmentVariableIntValue > 0;
}

/// <summary>
/// Check flag in configuration
/// </summary>
/// <param name="configurationElement">Configuration</param>
/// <param name="configurationSettingName">Configuration setting name</param>
/// <returns>Flag value in configuration. Null if not present.</returns>
private static bool? GetConfigurationValue(XmlElement configurationElement, string configurationSettingName)
{
if (bool.TryParse(configurationElement?[configurationSettingName]?.InnerText, out var settingValue))
{
return settingValue;
}

return null;
}

/// <summary>
/// On session end
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,35 +33,70 @@ internal class DynamicCoverageDataCollectorImpl : IDynamicCoverageDataCollectorI
/// </summary>
private const string VanguardConfigFileName = "CodeCoverage.config";

/// <summary>
/// File name of deps.json file with reference to Microsoft.VisualStudio.CodeCoverage.Shim.dll.
/// </summary>
private const string CodeCoverageDepsJsonFileName = "CodeCoverage.deps.json";

/// <summary>
/// Name of element for custom coverage filename.
/// </summary>
private const string CoverageFileSettingName = "CoverageFileName";

private const string CodeCoverageDepsJsonTemplate = @"
{{
Copy link
Contributor

Choose a reason for hiding this comment

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

Will this work in different platforms? Is it better to concatenate strings with Environment.NewLine?

Copy link
Member Author

Choose a reason for hiding this comment

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

logic is invoked only on windows now, new lines doesn't matter for JSON files

""runtimeTarget"": {{
""name"": ""codecoverage"",
""signature"": """"
}},
""targets"": {{
""codecoverage"": {{
""Microsoft.VisualStudio.CodeCoverage.Shim/15.0.0.0"": {{
""runtime"": {{
""{0}"": {{ }}
}}
}}
}}
}},
""libraries"": {{
""Microsoft.VisualStudio.CodeCoverage.Shim/15.0.0.0"": {{
""type"": ""reference"",
""serviceable"": false,
""sha512"": """"
}}
}}
}}
";

/// <summary>
/// Coverage file name
/// Directory helper
/// </summary>
private string coverageFileName;
private readonly IDirectoryHelper directoryHelper;

/// <summary>
/// Logger
/// Profilers location provider
/// </summary>
private IDataCollectionLogger logger;
private readonly IProfilersLocationProvider profilersLocationProvider;

/// <summary>
/// Data sink
/// File helper
/// </summary>
private TraceCollector.IDataCollectionSink dataSink;
private readonly IFileHelper fileHelper;

/// <summary>
/// Directory helper
/// Coverage file name
/// </summary>
private IDirectoryHelper directoryHelper;
private string coverageFileName;

/// <summary>
/// File helper
/// Logger
/// </summary>
private IDataCollectionLogger logger;

/// <summary>
/// Data sink
/// </summary>
private IFileHelper fileHelper;
private TraceCollector.IDataCollectionSink dataSink;

/// <summary>
/// Folder to store temporary files
Expand All @@ -71,17 +106,23 @@ internal class DynamicCoverageDataCollectorImpl : IDynamicCoverageDataCollectorI
private string coverageFilePath;

public DynamicCoverageDataCollectorImpl()
: this(new Vanguard(), new DirectoryHelper(), new FileHelper())
: this(new Vanguard(), new DirectoryHelper(), new FileHelper(), new ProfilersLocationProvider())
{
}

internal DynamicCoverageDataCollectorImpl(IVanguard vanguard, IDirectoryHelper directoryHelper, IFileHelper fileHelper)
internal DynamicCoverageDataCollectorImpl(IVanguard vanguard, IDirectoryHelper directoryHelper, IFileHelper fileHelper, IProfilersLocationProvider profilersLocationProvider)
{
this.Vanguard = vanguard;
this.directoryHelper = directoryHelper;
this.fileHelper = fileHelper;
this.profilersLocationProvider = profilersLocationProvider;
}

/// <summary>
/// Gets path to deps.json file with reference to Microsoft.VisualStudio.CodeCoverage.Shim.dll.
/// </summary>
public string CodeCoverageDepsJsonFilePath { get; private set; }

/// <summary>
/// Gets or sets session name
/// </summary>
Expand Down Expand Up @@ -295,9 +336,12 @@ private void PrepareVanguardProcess(XmlElement configurationElement)
?? DynamicCoverageDataCollectorImpl.GetDefaultConfiguration()[ConfigCodeCoverageElementName];

string configurationFileName = Path.Combine(this.sessionDirectory, VanguardConfigFileName);

this.fileHelper.WriteAllText(configurationFileName, config.OuterXml);

this.CodeCoverageDepsJsonFilePath = Path.Combine(this.sessionDirectory, CodeCoverageDepsJsonFileName);
var codeCoverageDepsJsonContent = this.profilersLocationProvider.GetCodeCoverageShimPath()?.Replace(@"\", "/");
this.fileHelper.WriteAllText(this.CodeCoverageDepsJsonFilePath, string.Format(CodeCoverageDepsJsonTemplate, codeCoverageDepsJsonContent));

EqtTrace.Info("DynamicCoverageDataCollectorImpl.PrepareVanguardProcess: Initializing with config: {0}.", config.OuterXml);
this.Vanguard.Initialize(this.SessionName, configurationFileName, this.logger);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ namespace Microsoft.VisualStudio.Coverage.Interfaces
/// </summary>
internal interface IDynamicCoverageDataCollectorImpl : IDisposable
{
string CodeCoverageDepsJsonFilePath { get; }

string GetSessionName();

void Initialize(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,11 @@ internal interface IProfilersLocationProvider
/// </summary>
/// <returns>x64 CLR IE Path</returns>
string GetClrInstrumentationEngineX64Path();

/// <summary>
/// Get path to Microsoft.VisualStudio.CodeCoverage.Shim library
/// </summary>
/// <returns>Path to Microsoft.VisualStudio.CodeCoverage.Shim library</returns>
string GetCodeCoverageShimPath();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ internal class ProfilersLocationProvider : IProfilersLocationProvider
private const string VanguardX64ProfilerPath = @"amd64\covrun64.dll";
private const string VanguardX86ProfilerConfigPath = @"VanguardInstrumentationProfiler_x86.config";
private const string VanguardX64ProfilerConfigPath = @"amd64\VanguardInstrumentationProfiler_x64.config";
private const string VanguardShimPath = @"coreclr\Microsoft.VisualStudio.CodeCoverage.Shim.dll";

/// <summary>
/// Vanguard executable name
Expand Down Expand Up @@ -76,6 +77,12 @@ public string GetClrInstrumentationEngineX64Path()
return this.GetClrInstrumentationEnginePath("x64", ClrIeX64FileName, ClrIeX64InstallDirVariable);
}

/// <inheritdoc />
public string GetCodeCoverageShimPath()
{
return Path.Combine(this.GetVanguardDirectory(), VanguardShimPath);
}

private string GetClrInstrumentationEnginePath(string arch, string fileName, string environmentVariableName)
{
var installationPath = Environment.GetEnvironmentVariable(environmentVariableName);
Expand Down
2 changes: 2 additions & 0 deletions src/package/nuspec/Microsoft.CodeCoverage.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
<file src="Microsoft.CodeCoverage\CodeCoverage\vcruntime140.dll" target="build\netstandard1.0\CodeCoverage\" />
<file src="Microsoft.CodeCoverage\CodeCoverage\VanguardInstrumentationProfiler_x86.config" target="build\netstandard1.0\CodeCoverage\" />

<file src="Microsoft.CodeCoverage\Shim\netcoreapp1.0\Microsoft.VisualStudio.CodeCoverage.Shim.dll" target="build\netstandard1.0\CodeCoverage\coreclr\" />

<file src="Microsoft.CodeCoverage\CodeCoverage\amd64\CodeCoverage.exe" target="build\netstandard1.0\CodeCoverage\amd64\" />
<file src="Microsoft.CodeCoverage\CodeCoverage\amd64\covrun64.dll" target="build\netstandard1.0\CodeCoverage\amd64\" />
<file src="Microsoft.CodeCoverage\CodeCoverage\amd64\msdia140.dll" target="build\netstandard1.0\CodeCoverage\amd64\" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ namespace Microsoft.VisualStudio.TraceDataCollector.UnitTests
using Coverage.Interfaces;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using TestPlatform.ObjectModel.DataCollection;
using TraceCollector;
using TraceCollector.Interfaces;
Expand All @@ -36,6 +38,7 @@ public class DynamicCoverageDataCollectorImplTests
private Mock<IDataCollectionLogger> dataCollectionLoggerMock;
private Mock<IDirectoryHelper> directoryHelperMock;
private Mock<IFileHelper> fileHelperMock;
private Mock<IProfilersLocationProvider> profilersLocationProviderMock;

private string aConfigFileName;
private string atempDirectory;
Expand All @@ -48,8 +51,9 @@ public DynamicCoverageDataCollectorImplTests()
this.dataCollectionLoggerMock = new Mock<IDataCollectionLogger>();
this.directoryHelperMock = new Mock<IDirectoryHelper>();
this.fileHelperMock = new Mock<IFileHelper>();
this.profilersLocationProviderMock = new Mock<IProfilersLocationProvider>();
this.tempSessionDir = null;
this.collectorImpl = new DynamicCoverageDataCollectorImpl(this.vanguardMock.Object, this.directoryHelperMock.Object, this.fileHelperMock.Object);
this.collectorImpl = new DynamicCoverageDataCollectorImpl(this.vanguardMock.Object, this.directoryHelperMock.Object, this.fileHelperMock.Object, this.profilersLocationProviderMock.Object);
this.SetupForInitialize();
this.collectorImpl.Initialize(DynamicCoverageDataCollectorImplTests.sampleConfigurationElement, this.dataCollectionSinkMock.Object, this.dataCollectionLoggerMock.Object);
}
Expand Down Expand Up @@ -83,6 +87,48 @@ public void InitializeShouldCreateDefaultCodeCoverageSettingsIfConfigElementIsNu
this.CompareWithDefaultConfig();
}

[TestMethod]
public void InitializeShouldGenerateCodeCoverageDepsJsonFile()
{
this.directoryHelperMock.Setup(d => d.CreateDirectory(It.IsAny<string>()))
.Callback<string>((path) => Directory.CreateDirectory(path));

this.fileHelperMock.Setup(f => f.WriteAllText(It.IsAny<string>(), It.IsAny<string>()))
.Callback<string, string>((path, content) => { File.WriteAllText(path, content); });

this.profilersLocationProviderMock.Setup(lp => lp.GetCodeCoverageShimPath()).Returns(@"C:\aaa\bbb\Microsoft.VisualStudio.CodeCoverage.Shim.dll");

this.collectorImpl.Initialize(null, this.dataCollectionSinkMock.Object, this.dataCollectionLoggerMock.Object);

var obj = JObject.Parse(File.ReadAllText(this.collectorImpl.CodeCoverageDepsJsonFilePath));

var expected = @"
Copy link
Contributor

Choose a reason for hiding this comment

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

The same as above.

Copy link
Contributor

@Haplois Haplois Nov 12, 2020

Choose a reason for hiding this comment

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

Since it's a json file, a new line shouldn't affect anything other than formatting.

Copy link
Member Author

Choose a reason for hiding this comment

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

also this stuff is working only on Windows now

{
""runtimeTarget"": {
""name"": ""codecoverage"",
""signature"": """"
},
""targets"": {
""codecoverage"": {
""Microsoft.VisualStudio.CodeCoverage.Shim/15.0.0.0"": {
""runtime"": {
""C:/aaa/bbb/Microsoft.VisualStudio.CodeCoverage.Shim.dll"": { }
}
}
}
},
""libraries"": {
""Microsoft.VisualStudio.CodeCoverage.Shim/15.0.0.0"": {
""type"": ""reference"",
""serviceable"": false,
""sha512"": """"
}
}
}";

Assert.AreEqual(expected.Trim(), File.ReadAllText(this.collectorImpl.CodeCoverageDepsJsonFilePath).Trim());
}

[TestMethod]
public void InitializeShouldInitializeVanguardWithRightCoverageSettings()
{
Expand Down
Loading