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

Logger extensibility #557

Merged
merged 16 commits into from
Mar 3, 2017
Merged
Show file tree
Hide file tree
Changes from 8 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
4 changes: 2 additions & 2 deletions scripts/build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -490,10 +490,10 @@ function Update-VsixVersion
Write-Log "Update-VsixVersion: Started."

$packageDir = Get-FullCLRPackageDirectory
$vsixVersion = "15.0.3" # Hardcode since we want to keep 15.0.0 for other assemblies.
$vsixVersion = "15.1.0" # Hardcode since we want to keep 15.0.0 for other assemblies.

# VersionSuffix in microbuild comes in the form preview-20170111-01(preview-yyyymmdd-buildNoOfThatDay)
# So Version of the vsix will be 15.0.3.2017011101
# So Version of the vsix will be 15.1.0.2017011101
$vsixVersionSuffix = $VersionSuffix.Split("-");
if($vsixVersionSuffix.Length -ige 2) {
$vsixVersion = "$vsixVersion.$($vsixVersionSuffix[1])$($vsixVersionSuffix[2])"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// 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.Client
{
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using System;

public class InvalidLoggerException : TestPlatformException
{
#region Constructors

/// <summary>
/// Initializes with the message.
/// </summary>
/// <param name="message">Message for the exception.</param>
public InvalidLoggerException(string message)
: base(message)
{
}

/// <summary>
/// Initializes with message and inner exception.
/// </summary>
/// <param name="message">Message for the exception.</param>
/// <param name="innerException">The inner exception.</param>
public InvalidLoggerException(string message, Exception innerException)
: base(message, innerException)
{
}

#endregion
}
}
67 changes: 67 additions & 0 deletions src/Microsoft.TestPlatform.Client/Execution/Logger/LoggerList.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// 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.Client
{
using System.Collections.Generic;
public class LoggerList
{
private static LoggerList loggerList;
private List<LoggerInfo> loggers = new List<LoggerInfo>();

protected LoggerList()
{
}

public static LoggerList Instance
{
get
{
if (loggerList == null)
{
loggerList = new LoggerList();
}
return loggerList;
}

protected set
{
loggerList = value;
}
}

public IEnumerable<LoggerInfo> Loggers
{
get
{
return this.loggers;
}
}

/// <summary>
/// Update the list of logger with their identifier and parameter.
/// </summary>
/// <param name="arument">Argument pass by user</param>
/// <param name="loggerIdentifier">Identifier of the logger</param>
/// <param name="parameters">parameter for logger</param>
public void AddLogger(string arument, string loggerIdentifier, Dictionary<string, string> parameters)
{
this.loggers.Add(new LoggerInfo(arument, loggerIdentifier, parameters));
}
}

public class LoggerInfo
{
public string arument;
public string loggerIdentifier;
public Dictionary<string, string> parameters = new Dictionary<string, string>();

public LoggerInfo(string arument, string loggerIdentifier, Dictionary<string, string> parameters)
{
this.arument = arument;
this.loggerIdentifier = loggerIdentifier;
this.parameters = parameters;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TestPlatformRoot Condition="$(TestPlatformRoot) == ''">..\..\</TestPlatformRoot>
Expand All @@ -10,7 +10,7 @@
<PackageTargetFallback Condition=" '$(TargetFramework)' == 'netstandard1.5' ">$(PackageTargetFallback);dnxcore50;portable-net45+win8</PackageTargetFallback>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\Resources.resx"/>
<EmbeddedResource Include="Resources\Resources.resx" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.TestPlatform.ObjectModel\Microsoft.TestPlatform.ObjectModel.csproj" />
Expand Down
22 changes: 22 additions & 0 deletions src/Microsoft.TestPlatform.Client/Resources/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions src/Microsoft.TestPlatform.Client/Resources/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@
<data name="InvalidStateForExecution" xml:space="preserve">
<value>The test run could not be executed because the initial state was invalid.</value>
</data>
<data name="LoggerNotFound" xml:space="preserve">
<value>Could not find a test logger with URI or FriendlyName '{0}'.</value>
</data>
<data name="LoggerUriInvalid" xml:space="preserve">
<value>The Test Logger URI '{0}' is not valid. The Test Logger will be ignored.</value>
</data>
<data name="WaitForCompletionOperationIsNotAllowedWhenNoTestRunIsActive" xml:space="preserve">
<value>Wait for completion operation is not allowed when there is no active test run. </value>
</data>
Expand Down
108 changes: 105 additions & 3 deletions src/Microsoft.TestPlatform.Client/TestPlatform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,35 @@ namespace Microsoft.VisualStudio.TestPlatform.Client
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;

using Microsoft.VisualStudio.TestPlatform.Client.Discovery;
using Microsoft.VisualStudio.TestPlatform.Client.Execution;
using ClientResources = Microsoft.VisualStudio.TestPlatform.Client.Resources.Resources;
using Microsoft.VisualStudio.TestPlatform.Common;
using Microsoft.VisualStudio.TestPlatform.Common.Logging;
using Microsoft.VisualStudio.TestPlatform.Common.Utilities;
using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine;
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities;
using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers;
using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces;

/// <summary>
/// Implementation for TestPlatform
/// </summary>
public class TestPlatform : ITestPlatform
{
protected IFileHelper fileHelper;
/// <summary>
/// Initializes a new instance of the <see cref="TestPlatform"/> class.
/// </summary>
public TestPlatform() : this(new TestEngine())
{
fileHelper = new FileHelper();
Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't it better is inject IFileHelper via ctor?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, its a valid point. Fixed in next commit.

}

/// <summary>
Expand Down Expand Up @@ -62,7 +70,7 @@ public IDiscoveryRequest CreateDiscoveryRequest(DiscoveryCriteria discoveryCrite

var runconfiguration = XmlRunSettingsUtilities.GetRunConfigurationNode(discoveryCriteria.RunSettings);
var testHostManager = this.TestEngine.GetDefaultTestHostManager(runconfiguration);

var discoveryManager = this.TestEngine.GetDiscoveryManager(testHostManager, discoveryCriteria);
discoveryManager.Initialize();

Expand All @@ -85,6 +93,13 @@ public ITestRunRequest CreateTestRunRequest(TestRunCriteria testRunCriteria)
UpdateTestAdapterPaths(testRunCriteria.TestRunSettings);

var runConfiguration = XmlRunSettingsUtilities.GetRunConfigurationNode(testRunCriteria.TestRunSettings);

// Update and initialize loggers only when DesignMode is false
if (runConfiguration.DesignMode == false)
{
UpdateAndInitializeLoggers(testRunCriteria);
}

var testHostManager = this.TestEngine.GetDefaultTestHostManager(runConfiguration);

if (testRunCriteria.TestHostLauncher != null)
Expand Down Expand Up @@ -148,14 +163,101 @@ private void UpdateTestAdapterPaths(string runSettings)
continue;
}
List<string> adapterFiles = new List<string>(
Directory.EnumerateFiles(adapterPath,TestPlatformConstants.TestAdapterPattern , SearchOption.AllDirectories)
this.fileHelper.EnumerateFiles(adapterPath, TestPlatformConstants.TestAdapterResxPattern, SearchOption.AllDirectories)
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: typo RegexPattern instead of ResxPattern

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in next commit

);
if (adapterFiles.Count > 0)
{
this.UpdateExtensions(adapterFiles, false);
this.UpdateExtensions(adapterFiles, true);
}
}
}
}

/// <summary>
/// Update the test adapter paths provided through run settings to be used by the test service
/// </summary>
private void UpdateAndInitializeLoggers(TestRunCriteria testRunCriteria)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think TP.Common is the right place for this logic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in next commit

{
this.UpdateTestLoggerPath(testRunCriteria);

// Initialize Loggers
TestLoggerManager loggerManager = TestLoggerManager.Instance;

foreach (var logger in LoggerList.Instance.Loggers)
{
string loggerIdentifier = logger.loggerIdentifier;
Dictionary<string, string> parameters = logger.parameters;

// First assume the logger is specified by URI. If that fails try with friendly name.
try
{
this.AddLoggerByUri(loggerManager, loggerIdentifier, parameters);
}
catch (InvalidLoggerException)
{
string loggerUri;
if (loggerManager.TryGetUriFromFriendlyName(loggerIdentifier, out loggerUri))
{
this.AddLoggerByUri(loggerManager, loggerUri, parameters);
}
else
{
throw new InvalidLoggerException(
String.Format(
CultureInfo.CurrentUICulture,
ClientResources.LoggerNotFound,
logger.arument));
}
}
}
}

private void AddLoggerByUri(TestLoggerManager loggerManager, string argument, Dictionary<string, string> parameters)
{
// Get the uri and if it is not valid, throw.
Uri loggerUri = null;
try
{
loggerUri = new Uri(argument);
}
catch (UriFormatException)
{
throw new InvalidLoggerException(
string.Format(
CultureInfo.CurrentUICulture,
ClientResources.LoggerUriInvalid,
argument));
}

// Add the logger and if it is a non-existent logger, throw.
try
{
loggerManager.AddLogger(loggerUri, parameters);
}
catch (InvalidOperationException e)
{
throw new InvalidLoggerException(e.Message, e);
}
}

private void UpdateTestLoggerPath(TestRunCriteria testRunCriteria)
{
List<string> loggersToUpdate = new List<string>();

var sources = testRunCriteria.Sources;
foreach (var source in sources)
{
var sourceDirectory = Path.GetDirectoryName(source);
if (!string.IsNullOrEmpty(sourceDirectory) && this.fileHelper.DirectoryExists(sourceDirectory))
{
loggersToUpdate.AddRange(this.fileHelper.EnumerateFiles(sourceDirectory, TestPlatformConstants.TestLoggerResxPattern, SearchOption.TopDirectoryOnly).ToList());
}
}

if (loggersToUpdate.Count > 0)
{
this.UpdateExtensions(loggersToUpdate, true);
}
}
}
}
8 changes: 4 additions & 4 deletions src/Microsoft.TestPlatform.Common/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,14 @@ public static class TestPlatformDefaults
public static class TestPlatformConstants
{
/// <summary>
/// string pattern used to find the test adapters
/// Regex pattern used to find the test adapters
/// </summary>
public const string TestAdapterPattern = @"*.TestAdapter.dll";
public const string TestAdapterResxPattern = @".*.TestAdapter.dll";

/// <summary>
/// Regex pattern used to find the test adapters
/// Regex pattern used to find the test logger
/// </summary>
public const string TestAdapterRedexPattern = @".*.TestAdapter.dll";
public const string TestLoggerResxPattern = @".*.TestLogger.dll";

}
}
1 change: 1 addition & 0 deletions src/Microsoft.TestPlatform.Common/Friends.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
[assembly: InternalsVisibleTo("datacollector, PublicKey =002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")]
[assembly: InternalsVisibleTo("Microsoft.TestPlatform.CommunicationUtilities, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")]
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.TestPlatform.Common, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")]
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.TestPlatform.Client, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")]

#endregion

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ namespace Microsoft.VisualStudio.TestPlatform.Common.Logging
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities;

using CommonResources = Microsoft.VisualStudio.TestPlatform.Common.Resources.Resources;
using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework;

/// <summary>
/// Responsible for managing logger extensions and broadcasting results
Expand Down Expand Up @@ -90,6 +91,14 @@ public static TestLoggerManager Instance
}
}
}
else if (TestPluginCache.Instance.AreDefaultExtensionsDiscovered == false)
{
lock (Synclock)
{
// If extension path has been modified, update testLoggerExtensionManager
testLoggerManager.testLoggerExtensionManager = TestLoggerExtensionManager.Create(testLoggerManager.messageLogger);
}
}
return testLoggerManager;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ public IEnumerable<string> GetTestPlatformExtensions(IEnumerable<string> sources

if (!string.IsNullOrEmpty(sourceDirectory) && this.fileHelper.DirectoryExists(sourceDirectory))
{
return this.fileHelper.EnumerateFiles(sourceDirectory, TestPlatformConstants.TestAdapterRedexPattern, SearchOption.TopDirectoryOnly);
return this.fileHelper.EnumerateFiles(sourceDirectory, TestPlatformConstants.TestAdapterResxPattern, SearchOption.TopDirectoryOnly);
}

return Enumerable.Empty<string>();
Expand Down
Loading