Skip to content

Commit

Permalink
Passing runsettings as command line arguments. (#297)
Browse files Browse the repository at this point in the history
* Allow TranslationLayer to specify Diag parameters
Log message for logging file of test host

* Passing runsettings as command line arguments.

* Removed unused variable.

* Added regex, testcases.

* Added new parameter VSTestCLIRunSettings in VSTest Task.

* Added htlm encoding to the RunSettings values coming as CLI arguments.

* Style fixes

* Fix typo

* Work done under this commit: (#302)

1) Create xlf file for all language
2) Create language resx file from xlf file
3) create satellite dll

* Testhost Diag log file name format change (#303)

Update diag log format for testhost. New format ensures log files are unique so that we don't run multiple testhosts with same file name in case of parallel runs.

* Changes for passing RunSettings args as array of string.

* Doc changes.

* test fixes.

* Removed unused namespaces, improved documentation, added trim to key.

* Removed HTML Encoding as it is already done while validating xml.

* Removed ununsed namespace and package.run
  • Loading branch information
harshjain2 authored Dec 27, 2016
1 parent fc1f7b9 commit 77f351f
Show file tree
Hide file tree
Showing 15 changed files with 793 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Copyright (c) .NET Foundation. All rights reserved.
VSTestLogger="$(VSTestLogger)"
VSTestListTests="$(VSTestListTests)"
VSTestDiag="$(VSTestDiag)"
VSTestCLIRunSettings="$(VSTestCLIRunSettings)"
/>
</Target>

Expand Down Expand Up @@ -72,6 +73,7 @@ Copyright (c) .NET Foundation. All rights reserved.
<Message Text="VSTestLogger = $(VSTestLogger)" Importance="low" />
<Message Text="VSTestListTests = $(VSTestListTests)" Importance="low" />
<Message Text="VSTestDiag = $(VSTestDiag)" Importance="low" />
<Message Text="VSTestCLIRunSettings = $(VSTestCLIRunSettings)" Importance="low" />
</Target>

</Project>
12 changes: 12 additions & 0 deletions src/Microsoft.TestPlatform.Build/Tasks/VSTestTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ public string VSTestDiag
set;
}

public string[] VSTestCLIRunSettings
{
get;
set;
}

public override bool Execute()
{
var traceEnabledValue = Environment.GetEnvironmentVariable("VSTEST_BUILD_TRACE");
Expand Down Expand Up @@ -159,6 +165,12 @@ private IEnumerable<string> CreateArgument()
}
}

if (this.VSTestCLIRunSettings!=null && this.VSTestCLIRunSettings.Length>0)
{
allArgs.Add("--");
allArgs.AddRange(this.VSTestCLIRunSettings);
}

return allArgs;
}
}
Expand Down
14 changes: 12 additions & 2 deletions src/vstest.console/CommandLine/Executor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ internal class Executor
/// <summary>
/// Default constructor.
/// </summary>
public Executor(IOutput output): this(output, TestPlatformEventSource.Instance)
public Executor(IOutput output) : this(output, TestPlatformEventSource.Instance)
{
}

Expand Down Expand Up @@ -152,8 +152,18 @@ private int GetArgumentProcessors(string[] args, out List<IArgumentProcessor> pr
int result = 0;
var processorFactory = ArgumentProcessorFactory.Create();

foreach (string arg in args)
for (var index = 0; index < args.Length; index++)
{
var arg = args[index];

// If argument is '--', following arguments are key=value pairs for run settings.
if (arg.Equals("--"))
{
var cliRunSettingsProcessor = processorFactory.CreateArgumentProcessor(arg, args.Skip(index + 1).ToArray());
processors.Add(cliRunSettingsProcessor);
break;
}

var processor = processorFactory.CreateArgumentProcessor(arg);

if (processor != null)
Expand Down
222 changes: 222 additions & 0 deletions src/vstest.console/Processors/CLIRunSettingsArgumentProcessor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
// 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.CommandLine.Processors
{
using System;
using System.Diagnostics.Contracts;
using System.IO;
using System.Xml;
using System.Xml.XPath;

using Microsoft.VisualStudio.TestPlatform.Common;
using Microsoft.VisualStudio.TestPlatform.Common.Interfaces;
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities;

using CommandLineResources = Microsoft.VisualStudio.TestPlatform.CommandLine.Resources.Resources;

/// <summary>
/// The argument processor for runsettings passed as argument through cli
/// </summary>
internal class CLIRunSettingsArgumentProcessor : IArgumentProcessor
{
#region Constants

/// <summary>
/// The name of the command line argument that the PortArgumentExecutor handles.
/// </summary>
public const string CommandName = "--";

#endregion

private Lazy<IArgumentProcessorCapabilities> metadata;

private Lazy<IArgumentExecutor> executor;

/// <summary>
/// Gets the metadata.
/// </summary>
public Lazy<IArgumentProcessorCapabilities> Metadata
{
get
{
if (this.metadata == null)
{
this.metadata = new Lazy<IArgumentProcessorCapabilities>(() => new CLIRunSettingsArgumentProcessorCapabilities());
}

return this.metadata;
}
}

/// <summary>
/// Gets or sets the executor.
/// </summary>
public Lazy<IArgumentExecutor> Executor
{
get
{
if (this.executor == null)
{
this.executor = new Lazy<IArgumentExecutor>(() => new CLIRunSettingsArgumentExecutor(RunSettingsManager.Instance));
}

return this.executor;
}

set
{
this.executor = value;
}
}
}

internal class CLIRunSettingsArgumentProcessorCapabilities : BaseArgumentProcessorCapabilities
{
public override string CommandName => CLIRunSettingsArgumentProcessor.CommandName;

public override bool AllowMultiple => false;

public override bool IsAction => false;

public override ArgumentProcessorPriority Priority => ArgumentProcessorPriority.CLIRunSettings;

public override string HelpContentResourceName => CommandLineResources.CLIRunSettingsArgumentHelp;

public override HelpContentPriority HelpPriority => HelpContentPriority.CLIRunSettingsArgumentProcessorHelpPriority;
}

internal class CLIRunSettingsArgumentExecutor : IArgumentsExecutor
{
private IRunSettingsProvider runSettingsManager;

internal CLIRunSettingsArgumentExecutor(IRunSettingsProvider runSettingsManager)
{
this.runSettingsManager = runSettingsManager;
}

public void Initialize(string argument)
{
throw new NotImplementedException();
}

public void Initialize(string[] arguments)
{
// if argument is null or doesn't contain any element, don't do anything.
if (arguments == null || arguments.Length == 0)
{
return;
}

Contract.EndContractBlock();

// Load up the run settings and set it as the active run settings.
try
{
var doc = new XmlDocument();

if (this.runSettingsManager.ActiveRunSettings != null && !string.IsNullOrEmpty(this.runSettingsManager.ActiveRunSettings.SettingsXml))
{
var settingsXml = this.runSettingsManager.ActiveRunSettings.SettingsXml;

#if net46
using (var reader = XmlReader.Create(new StringReader(settingsXml), new XmlReaderSettings() { XmlResolver = null, CloseInput = true, DtdProcessing = DtdProcessing.Prohibit }))
{
#else
using (var reader = XmlReader.Create(new StringReader(settingsXml), new XmlReaderSettings() { CloseInput = true, DtdProcessing = DtdProcessing.Prohibit }))
{
#endif
doc.Load(reader);
}
}
else
{
#if net46
doc = (XmlDocument)XmlRunSettingsUtilities.CreateDefaultRunSettings();
#else
using (var reader = XmlReader.Create(new StringReader(XmlRunSettingsUtilities.CreateDefaultRunSettings().CreateNavigator().OuterXml), new XmlReaderSettings() { CloseInput = true, DtdProcessing = DtdProcessing.Prohibit }))
{
doc.Load(reader);
}
#endif
}

// Append / Override run settings supplied in CLI
CreateOrOverwriteRunSettings(doc, arguments);

// Set Active Run Settings.
var runSettings = new RunSettings();
runSettings.LoadSettingsXml(doc.OuterXml);
this.runSettingsManager.SetActiveRunSettings(runSettings);
}
catch (XPathException exception)
{
throw new CommandLineException(CommandLineResources.MalformedRunSettingsKey, exception);
}
catch (SettingsException exception)
{
throw new CommandLineException(exception.Message, exception);
}
}

public ArgumentProcessorResult Execute()
{
// Nothing to do here, the work was done in initialization.
return ArgumentProcessorResult.Success;
}

private void CreateOrOverwriteRunSettings(XmlDocument xmlDoc, string[] args)
{
var length = args.Length;

for (int index = 0; index < length; index++)
{
var keyValuePair = args[index];
var indexOfSeparator = keyValuePair.IndexOf("=");
if (indexOfSeparator <= 0 || indexOfSeparator >= keyValuePair.Length - 1)
{
continue;
}
var key = keyValuePair.Substring(0, indexOfSeparator).Trim();
var value = keyValuePair.Substring(indexOfSeparator + 1);

if (string.IsNullOrWhiteSpace(key))
{
continue;
}

// Check if the key exists.
var xPath = key.Replace('.', '/');
var node = xmlDoc.SelectSingleNode(string.Format("//RunSettings/{0}", xPath));

if (node == null)
{
node = CreateNode(xmlDoc, key.Split('.'));
}

node.InnerText = value;
}
}

private XmlNode CreateNode(XmlDocument doc, string[] xPath)
{
XmlNode node = null;
XmlNode parent = doc.DocumentElement;

for (int i = 0; i < xPath.Length; i++)
{
node = parent.SelectSingleNode(xPath[i]);

if (node == null)
{
node = parent.AppendChild(doc.CreateElement(xPath[i]));
}

parent = node;
}

return node;
}
}
}
18 changes: 18 additions & 0 deletions src/vstest.console/Processors/Interfaces/IArgumentsExecutor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// 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.CommandLine.Processors
{
/// <summary>
/// Defines interface for interacting with a command line arguments executor.
/// Items exporting this interface will be used in processing command line arguments.
/// </summary>
internal interface IArgumentsExecutor : IArgumentExecutor
{
/// <summary>
/// Initializes the Argument Processor with the arguments that was provided with the command.
/// </summary>
/// <param name="arguments">Arguments that are provided with the command.</param>
void Initialize(string[] arguments);
}
}
Loading

0 comments on commit 77f351f

Please sign in to comment.