From 56c3c675c90d33f952160e5f63d613b17fbc5193 Mon Sep 17 00:00:00 2001 From: abhishkk Date: Fri, 6 Jul 2018 19:16:46 +0530 Subject: [PATCH 01/10] Diag verbosity param support initial commit --- .../Processors/EnableDiagArgumentProcessor.cs | 174 +++++++++++++++++- .../Resources/Resources.Designer.cs | 1 + 2 files changed, 171 insertions(+), 4 deletions(-) diff --git a/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs b/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs index bd5a6c95b3..11bafbc366 100644 --- a/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs +++ b/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs @@ -12,6 +12,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.Processors using CommandLineResources = Microsoft.VisualStudio.TestPlatform.CommandLine.Resources.Resources; using Microsoft.VisualStudio.TestPlatform.Utilities; + using System.Collections.Generic; internal class EnableDiagArgumentProcessor : IArgumentProcessor { @@ -123,10 +124,91 @@ public EnableDiagArgumentExecutor(IFileHelper fileHelper) /// Argument that was provided with the command. public void Initialize(string argument) { - if (string.IsNullOrWhiteSpace(argument)) - { - throw new CommandLineException(CommandLineResources.EnableDiagUsage); - } + ValidateArgumentNotEmpty(argument); + + var diagFilePath = GetDiagFilePath(argument); + ValidateArgumentNotEmpty(diagFilePath); + + var arguments = GetDiagArguments(argument); + + InitializeDiagLogging(diagFilePath, arguments); + + // Following patterns should match + // "abc" + // "abc";verbosity=xyz + // abc;verbosity=xyz + // Here abc and xyz can have any character including ", ;, = + + // Pattern 1: + // Starts with quote + // Atleast 2 quotes in string (including starting one) + // Between first 2 quotes, there should be atleast one non-whitespace char. + // After 2 quotes, there can be string or not. + // If there is string after 2 quotes, it should start with ; + // Remaining of the string expect can be empty or non empty + // Remaining of the string needs be split using ; [remove empty entries] + // Search among all the values and split each value using =. Each split should have exactly one =. + // Understand verbosity key. Ignore rest key value pairs. + + // Pattern 2: + // Doesn't start with quote + // Entire arg should be considered as diag file path. + + //if (string.IsNullOrWhiteSpace(argument)) + //{ + // // /diag:, /diag: , + // // Check if /diag, belong here. + // throw new CommandLineException(CommandLineResources.EnableDiagUsage); + //} + + //if (argument.StartsWith('"')) + //{ + // int startQuoteOfFilePath = 0; + // int endQuoteOfFilePath = argument.IndexOf('"', startQuoteOfFilePath + 1); // TODO: does this throw error on / diag:", scenario? + // int diagFilePathLength = endQuoteOfFilePath - startQuoteOfFilePath - 1; + // if (endQuoteOfFilePath > 0 && diagFilePathLength > 0) + // { + // // /diag:" ", /diag:"a", + // var diagFilePath = argument.Substring(startQuoteOfFilePath + 1, endQuoteOfFilePath - startQuoteOfFilePath); + // // var parameters + // } + // else + // { + // // / diag:", /diag:"", /diag:"abc, + // throw new CommandLineException(CommandLineResources.EnableDiagUsage); + // } + //} + //else + //{ + // // pattern 2 + //} + + // TODO: try /diag, /diag:, /diag: , /diag: , /diag:"", + //if (string.IsNullOrWhiteSpace(argument) || + // argument.StartsWith(@"""")) + //{ + // throw new CommandLineException(CommandLineResources.EnableDiagUsage); + //} + + //var diagFilePath = string.Empty; + + //if (argument.StartsWith('"')) + //{ + // // TODO: /diag:"a, /diag:"abc"def", /diag:"abc"d"ef", , /diag:"abc"def, /diag:"abc" , /diag:" "abc; + // var ArgumentSeperator = new char[] { '"' }; + // var argumentParts = argument.Split(ArgumentSeperator, StringSplitOptions.None); + // if (argumentParts.Length > 0) + // { + // diagFilePath = argumentParts[0]; + // } + // else + // { + // // TODO: /diag:", /diag:" , /diag:" ", + // throw new CommandLineException(CommandLineResources.EnableDiagUsage); + // } + //} + + // TODO: /diag:a, /diag:a" if (string.IsNullOrWhiteSpace(Path.GetExtension(argument))) { @@ -153,6 +235,49 @@ public void Initialize(string argument) } } + private void InitializeDiagLogging(string diagFilePath, object arguments) + { + throw new NotImplementedException(); + } + + private object GetDiagArguments(string argument) + { + throw new NotImplementedException(); + } + + /// + /// Validates that argument is not empty. + /// Throws CommandLineException in case argument is empty. + /// + /// Diag argument. + private void ValidateArgumentNotEmpty(string argument) + { + if (string.IsNullOrWhiteSpace(argument)) + { + throw new CommandLineException(CommandLineResources.EnableDiagUsage); + } + } + + /// + /// Gets diag file path. + /// + /// Argument. + /// Diag file path. + private string GetDiagFilePath(string argument) + { + // If quotes are present in argument, value between first two quotes is considered as diag file path. + bool startsWithQuote = argument.StartsWith('"'); + if (startsWithQuote) + { + var firstQuoteIndex = 0; + var secondQuoteIndex = argument.IndexOf('"', firstQuoteIndex + 1); + return argument.Substring(firstQuoteIndex + 1, secondQuoteIndex - firstQuoteIndex); + } + + // If no quotes are present, entire argument is considered as diag file path. + return argument; + } + /// /// Executes the argument processor. /// @@ -164,5 +289,46 @@ public ArgumentProcessorResult Execute() } #endregion + + public static bool TryParseDiagArgument(string argument, out string diagFilePath, out Dictionary parameters) + { + diagFilePath = null; + parameters = null; + + var parseSucceeded = true; + var ArgumentSeperator = new char[] { ';' }; + var NameValueSeperator = new char[] { '=' }; + + var argumentParts = argument.Split(ArgumentSeperator, StringSplitOptions.RemoveEmptyEntries); + + if (argumentParts.Length > 0 && !argumentParts[0].Contains("=")) + { + diagFilePath = argumentParts[0]; + + if (argumentParts.Length > 1) + { + parameters = new Dictionary(StringComparer.OrdinalIgnoreCase); + for (int index = 1; index < argumentParts.Length; ++index) + { + string[] nameValuePair = argumentParts[index].Split(NameValueSeperator, StringSplitOptions.RemoveEmptyEntries); + if (nameValuePair.Length == 2) + { + parameters[nameValuePair[0]] = nameValuePair[1]; + } + else + { + parseSucceeded = false; + break; + } + } + } + } + else + { + parseSucceeded = false; + } + + return parseSucceeded; + } } } diff --git a/src/vstest.console/Resources/Resources.Designer.cs b/src/vstest.console/Resources/Resources.Designer.cs index 6043c954e7..b76b4d0eb2 100644 --- a/src/vstest.console/Resources/Resources.Designer.cs +++ b/src/vstest.console/Resources/Resources.Designer.cs @@ -480,6 +480,7 @@ public static string EnableCodeCoverageArgumentProcessorHelp /// public static string EnableDiagUsage { + // TODO: Check this EnableLoggersArgumentHelp to change the help here. get { return ResourceManager.GetString("EnableDiagUsage", resourceCulture); From e188a59c022686e245df09605059fe1d7a336ace Mon Sep 17 00:00:00 2001 From: Abhishek Kumawat Date: Mon, 9 Jul 2018 11:42:21 +0530 Subject: [PATCH 02/10] Trace level changes --- .../Tracing/EqtTrace.cs | 14 +- .../Client/ProxyOperationManager.cs | 2 +- .../ProxyDataCollectionManager.cs | 4 + .../TestRunnerConnectionInfo.cs | 9 + .../TestRunnerConnectionInfoExtensions.cs | 1 + .../Interfaces/Tracing/IPlatformEqtTrace.cs | 9 + .../common/Tracing/PlatformEqtTrace.cs | 14 +- .../Tracing/PlatformEqtTrace.cs | 5 + .../uap10.0/Tracing/PlatformEqtTrace.cs | 12 +- .../ConsoleParameters.cs | 5 + .../VsTestConsoleProcessManager.cs | 4 +- src/datacollector/DataCollectorMain.cs | 8 +- src/testhost.x86/DefaultEngineInvoker.cs | 5 +- .../Processors/EnableDiagArgumentProcessor.cs | 303 ++++++++---------- .../Tracing/EqtTraceTests.cs | 2 +- .../Client/ProxyOperationManagerTests.cs | 2 +- .../ProxyDataCollectionManagerTests.cs | 4 +- .../EnableDiagArgumentProcessorTests.cs | 2 +- 18 files changed, 219 insertions(+), 186 deletions(-) diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Tracing/EqtTrace.cs b/src/Microsoft.TestPlatform.CoreUtilities/Tracing/EqtTrace.cs index 0ebfa16aa3..0f0cb2fe3f 100644 --- a/src/Microsoft.TestPlatform.CoreUtilities/Tracing/EqtTrace.cs +++ b/src/Microsoft.TestPlatform.CoreUtilities/Tracing/EqtTrace.cs @@ -146,7 +146,19 @@ public static bool IsWarningEnabled /// public static bool InitializeVerboseTrace(string customLogFile) { - if (!traceImpl.InitializeVerboseTrace(customLogFile)) + return InitializeTrace(customLogFile, PlatformTraceLevel.Verbose); + } + + /// + /// Initializes the tracing with custom log file and trace level. + /// Overrides if any trace is set before. + /// + /// Customr log file for trace messages. + /// Trace level. + /// Trace initialized flag. + public static bool InitializeTrace(string customLogFile, PlatformTraceLevel traceLevel) + { + if (!traceImpl.InitializeTrace(customLogFile, traceLevel)) { ErrorOnInitialization = PlatformEqtTrace.ErrorOnInitialization; return false; diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyOperationManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyOperationManager.cs index 0a2a83b2f5..681db2a770 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyOperationManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyOperationManager.cs @@ -116,7 +116,7 @@ public virtual bool SetupChannel(IEnumerable sources) } var processId = this.processHelper.GetCurrentProcessId(); - var connectionInfo = new TestRunnerConnectionInfo { Port = portNumber, ConnectionInfo = testHostConnectionInfo, RunnerProcessId = processId, LogFile = this.GetTimestampedLogFile(EqtTrace.LogFile) }; + var connectionInfo = new TestRunnerConnectionInfo { Port = portNumber, ConnectionInfo = testHostConnectionInfo, RunnerProcessId = processId, LogFile = this.GetTimestampedLogFile(EqtTrace.LogFile), TraceLevel = (int)EqtTrace.TraceLevel }; // Subscribe to TestHost Event this.testHostManager.HostLaunched += this.TestHostManagerHostLaunched; diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/ProxyDataCollectionManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/ProxyDataCollectionManager.cs index c8f5cdf63c..72a5f9f7d5 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/ProxyDataCollectionManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/ProxyDataCollectionManager.cs @@ -38,6 +38,7 @@ internal class ProxyDataCollectionManager : IProxyDataCollectionManager private const string PortOption = "--port"; private const string DiagOption = "--diag"; private const string ParentProcessIdOption = "--parentprocessid"; + private const string TraceLevelOption = "--tracelevel"; public const string DebugEnvironmentVaribleName = "VSTEST_DATACOLLECTOR_DEBUG"; private IDataCollectionRequestSender dataCollectionRequestSender; @@ -299,6 +300,9 @@ private IList GetCommandLineArguments(int portNumber) { commandlineArguments.Add(DiagOption); commandlineArguments.Add(this.GetTimestampedLogFile(EqtTrace.LogFile)); + + commandlineArguments.Add(TraceLevelOption); + commandlineArguments.Add(((int)EqtTrace.TraceLevel).ToString()); } return commandlineArguments; diff --git a/src/Microsoft.TestPlatform.ObjectModel/ConnectionInfo/TestRunnerConnectionInfo.cs b/src/Microsoft.TestPlatform.ObjectModel/ConnectionInfo/TestRunnerConnectionInfo.cs index 77d6925ae4..52364a369e 100644 --- a/src/Microsoft.TestPlatform.ObjectModel/ConnectionInfo/TestRunnerConnectionInfo.cs +++ b/src/Microsoft.TestPlatform.ObjectModel/ConnectionInfo/TestRunnerConnectionInfo.cs @@ -98,6 +98,15 @@ public string LogFile set; } + /// + /// Gets or sets the trace level of logs. + /// + public int TraceLevel + { + get; + set; + } + /// /// Gets or sets the runner process id. /// diff --git a/src/Microsoft.TestPlatform.ObjectModel/ConnectionInfo/TestRunnerConnectionInfoExtensions.cs b/src/Microsoft.TestPlatform.ObjectModel/ConnectionInfo/TestRunnerConnectionInfoExtensions.cs index fbf6042b84..87ef7f5789 100644 --- a/src/Microsoft.TestPlatform.ObjectModel/ConnectionInfo/TestRunnerConnectionInfoExtensions.cs +++ b/src/Microsoft.TestPlatform.ObjectModel/ConnectionInfo/TestRunnerConnectionInfoExtensions.cs @@ -19,6 +19,7 @@ public static string ToCommandLineOptions(this TestRunnerConnectionInfo connecti if (!string.IsNullOrEmpty(connectionInfo.LogFile)) { options += " --diag " + connectionInfo.LogFile; + options += " --tracelevel " + connectionInfo.TraceLevel; } return options; diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/Interfaces/Tracing/IPlatformEqtTrace.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/Interfaces/Tracing/IPlatformEqtTrace.cs index 4e9aadcf4b..1f47eb20a0 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/Interfaces/Tracing/IPlatformEqtTrace.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/Interfaces/Tracing/IPlatformEqtTrace.cs @@ -37,6 +37,15 @@ bool DoNotInitialize /// bool InitializeVerboseTrace(string customLogFile); + /// + /// Initializes the tracing with custom log file and trace level. + /// Overrides if any trace is set before. + /// + /// Customr log file for trace messages. + /// Trace level. + /// Trace initialized flag. + bool InitializeTrace(string customLogFile, PlatformTraceLevel traceLevel); + /// /// Gets a value indicating if tracing is enabled for a trace level. /// diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/common/Tracing/PlatformEqtTrace.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/common/Tracing/PlatformEqtTrace.cs index 69e8050429..d9c66fbf6b 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/common/Tracing/PlatformEqtTrace.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/common/Tracing/PlatformEqtTrace.cs @@ -161,12 +161,18 @@ private static TraceSource Source /// public bool InitializeVerboseTrace(string customLogFile) + { + return this.InitializeTrace(customLogFile, PlatformTraceLevel.Verbose); + } + + /// + public bool InitializeTrace(string customLogFile, PlatformTraceLevel platformTraceLevel) { isInitialized = false; LogFile = customLogFile; - TraceLevel = TraceLevel.Verbose; - Source.Switch.Level = SourceLevels.All; + TraceLevel = this.MapPlatformTraceToTrace(platformTraceLevel); + Source.Switch.Level = TraceSourceLevelsMap[TraceLevel]; // Ensure trace is initlized return EnsureTraceIsInitialized(); @@ -351,7 +357,7 @@ private static bool EnsureTraceIsInitialized() } catch (Exception e) { - UnInitializeVerboseTrace(); + UnInitializeTrace(); ErrorOnInitialization = e.ToString(); return false; } @@ -419,7 +425,7 @@ private static int GetProcessId() } } - private static void UnInitializeVerboseTrace() + private static void UnInitializeTrace() { isInitialized = false; diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/netstandard1.0/Tracing/PlatformEqtTrace.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/netstandard1.0/Tracing/PlatformEqtTrace.cs index 4f65b03031..97b1387497 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/netstandard1.0/Tracing/PlatformEqtTrace.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/netstandard1.0/Tracing/PlatformEqtTrace.cs @@ -39,6 +39,11 @@ public bool InitializeVerboseTrace(string customLogFile) throw new NotImplementedException(); } + public bool InitializeTrace(string customLogFile, PlatformTraceLevel traceLevel) + { + throw new NotImplementedException(); + } + public bool ShouldTrace(PlatformTraceLevel traceLevel) { throw new NotImplementedException(); diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/uap10.0/Tracing/PlatformEqtTrace.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/uap10.0/Tracing/PlatformEqtTrace.cs index e87a00d4b5..20cdac9b00 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/uap10.0/Tracing/PlatformEqtTrace.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/uap10.0/Tracing/PlatformEqtTrace.cs @@ -69,6 +69,12 @@ public void WriteLine(PlatformTraceLevel level, string message) /// public bool InitializeVerboseTrace(string customLogFile) + { + return this.InitializeTrace(customLogFile, PlatformTraceLevel.Verbose); + } + + /// + public bool InitializeTrace(string customLogFile, PlatformTraceLevel traceLevel) { string logFileName = string.Empty; try @@ -81,7 +87,7 @@ public bool InitializeVerboseTrace(string customLogFile) } LogFile = Path.Combine(Path.GetTempPath(), logFileName + ".TpTrace.log"); - TraceLevel = PlatformTraceLevel.Verbose; + TraceLevel = traceLevel; return this.TraceInitialized(); } @@ -154,7 +160,7 @@ private bool TraceInitialized() } catch (Exception ex) { - this.UnInitializeVerboseTrace(); + this.UnInitializeTrace(); ErrorOnInitialization = ex.Message; return false; } @@ -163,7 +169,7 @@ private bool TraceInitialized() } } - private void UnInitializeVerboseTrace() + private void UnInitializeTrace() { isInitialized = false; LogFile = null; diff --git a/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/ConsoleParameters.cs b/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/ConsoleParameters.cs index d45fcdc44e..efd9783c5b 100644 --- a/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/ConsoleParameters.cs +++ b/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/ConsoleParameters.cs @@ -35,6 +35,11 @@ public ConsoleParameters(IFileHelper fileHelper) this.fileHelper = fileHelper; } + /// + /// Trace level for logs. + /// + public PlatformTraceLevel TraceLevel { get; set; } = PlatformTraceLevel.Verbose; + /// /// Full path for the log file /// diff --git a/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs b/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs index a12ba19292..e8e7cf82e9 100644 --- a/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs +++ b/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs @@ -32,7 +32,7 @@ internal class VsTestConsoleProcessManager : IProcessManager /// Diagnostics argument for Vstest CLI /// Enables Diagnostic logging for Vstest CLI and TestHost - Optional /// - private const string DIAG_ARGUMENT = "/diag:{0}"; + private const string DIAG_ARGUMENT = "/diag:{0};tracelevel={1}"; private string vstestConsolePath; private object syncObject = new object(); @@ -135,7 +135,7 @@ private string[] BuildArguments(ConsoleParameters parameters) if(!string.IsNullOrEmpty(parameters.LogFilePath)) { // Extra args: --diag|/diag: - args.Add(string.Format(CultureInfo.InvariantCulture, DIAG_ARGUMENT, parameters.LogFilePath)); + args.Add(string.Format(CultureInfo.InvariantCulture, DIAG_ARGUMENT, parameters.LogFilePath, parameters.TraceLevel)); } return args.ToArray(); diff --git a/src/datacollector/DataCollectorMain.cs b/src/datacollector/DataCollectorMain.cs index e57f914da6..0f20de8048 100644 --- a/src/datacollector/DataCollectorMain.cs +++ b/src/datacollector/DataCollectorMain.cs @@ -35,6 +35,11 @@ public class DataCollectorMain /// private const string LogFileArgument = "--diag"; + /// + /// Trace level for logs. + /// + private const string TraceLevelArgument = "--tracelevel"; + private IProcessHelper processHelper; private IEnvironment environment; @@ -65,7 +70,8 @@ public void Run(string[] args) string logFile; if (argsDictionary.TryGetValue(LogFileArgument, out logFile)) { - EqtTrace.InitializeVerboseTrace(logFile); + var traceLevel = CommandLineArgumentsHelper.GetIntArgFromDict(argsDictionary, TraceLevelArgument); + EqtTrace.InitializeTrace(logFile, (PlatformTraceLevel)traceLevel); } else { diff --git a/src/testhost.x86/DefaultEngineInvoker.cs b/src/testhost.x86/DefaultEngineInvoker.cs index 12acfc0d44..87796c9882 100644 --- a/src/testhost.x86/DefaultEngineInvoker.cs +++ b/src/testhost.x86/DefaultEngineInvoker.cs @@ -44,6 +44,8 @@ internal class DefaultEngineInvoker : private const string LogFileArgument = "--diag"; + private const string TraceLevelArgument = "--tracelevel"; + private const string DataCollectionPortArgument = "--datacollectionport"; private const string TelemetryOptedIn = "--telemetryoptedin"; @@ -228,7 +230,8 @@ private static void InitializeEqtTrace(IDictionary argsDictionar // Setup logging if enabled if (argsDictionary.TryGetValue(LogFileArgument, out string logFile)) { - EqtTrace.InitializeVerboseTrace(logFile); + var traceLevelInt = CommandLineArgumentsHelper.GetIntArgFromDict(argsDictionary, TraceLevelArgument); + EqtTrace.InitializeTrace(logFile, (PlatformTraceLevel)traceLevelInt); } else { diff --git a/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs b/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs index 11bafbc366..c8b565db83 100644 --- a/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs +++ b/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs @@ -4,15 +4,15 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.Processors { using System; + using System.Collections.Generic; using System.IO; - + using System.Linq; using Microsoft.VisualStudio.TestPlatform.ObjectModel; + using Microsoft.VisualStudio.TestPlatform.Utilities; using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; using CommandLineResources = Microsoft.VisualStudio.TestPlatform.CommandLine.Resources.Resources; - using Microsoft.VisualStudio.TestPlatform.Utilities; - using System.Collections.Generic; internal class EnableDiagArgumentProcessor : IArgumentProcessor { @@ -103,6 +103,11 @@ internal class EnableDiagArgumentExecutor : IArgumentExecutor { private readonly IFileHelper fileHelper; + /// + /// Parameter for trace level + /// + public const string TraceLevelParam = "tracelevel"; + #region Constructor /// @@ -124,211 +129,173 @@ public EnableDiagArgumentExecutor(IFileHelper fileHelper) /// Argument that was provided with the command. public void Initialize(string argument) { - ValidateArgumentNotEmpty(argument); - - var diagFilePath = GetDiagFilePath(argument); - ValidateArgumentNotEmpty(diagFilePath); - - var arguments = GetDiagArguments(argument); - - InitializeDiagLogging(diagFilePath, arguments); - - // Following patterns should match - // "abc" - // "abc";verbosity=xyz - // abc;verbosity=xyz - // Here abc and xyz can have any character including ", ;, = - - // Pattern 1: - // Starts with quote - // Atleast 2 quotes in string (including starting one) - // Between first 2 quotes, there should be atleast one non-whitespace char. - // After 2 quotes, there can be string or not. - // If there is string after 2 quotes, it should start with ; - // Remaining of the string expect can be empty or non empty - // Remaining of the string needs be split using ; [remove empty entries] - // Search among all the values and split each value using =. Each split should have exactly one =. - // Understand verbosity key. Ignore rest key value pairs. - - // Pattern 2: - // Doesn't start with quote - // Entire arg should be considered as diag file path. - - //if (string.IsNullOrWhiteSpace(argument)) - //{ - // // /diag:, /diag: , - // // Check if /diag, belong here. - // throw new CommandLineException(CommandLineResources.EnableDiagUsage); - //} - - //if (argument.StartsWith('"')) - //{ - // int startQuoteOfFilePath = 0; - // int endQuoteOfFilePath = argument.IndexOf('"', startQuoteOfFilePath + 1); // TODO: does this throw error on / diag:", scenario? - // int diagFilePathLength = endQuoteOfFilePath - startQuoteOfFilePath - 1; - // if (endQuoteOfFilePath > 0 && diagFilePathLength > 0) - // { - // // /diag:" ", /diag:"a", - // var diagFilePath = argument.Substring(startQuoteOfFilePath + 1, endQuoteOfFilePath - startQuoteOfFilePath); - // // var parameters - // } - // else - // { - // // / diag:", /diag:"", /diag:"abc, - // throw new CommandLineException(CommandLineResources.EnableDiagUsage); - // } - //} - //else - //{ - // // pattern 2 - //} - - // TODO: try /diag, /diag:, /diag: , /diag: , /diag:"", - //if (string.IsNullOrWhiteSpace(argument) || - // argument.StartsWith(@"""")) - //{ - // throw new CommandLineException(CommandLineResources.EnableDiagUsage); - //} - - //var diagFilePath = string.Empty; - - //if (argument.StartsWith('"')) - //{ - // // TODO: /diag:"a, /diag:"abc"def", /diag:"abc"d"ef", , /diag:"abc"def, /diag:"abc" , /diag:" "abc; - // var ArgumentSeperator = new char[] { '"' }; - // var argumentParts = argument.Split(ArgumentSeperator, StringSplitOptions.None); - // if (argumentParts.Length > 0) - // { - // diagFilePath = argumentParts[0]; - // } - // else - // { - // // TODO: /diag:", /diag:" , /diag:" ", - // throw new CommandLineException(CommandLineResources.EnableDiagUsage); - // } - //} - - // TODO: /diag:a, /diag:a" - - if (string.IsNullOrWhiteSpace(Path.GetExtension(argument))) + // Throw error if argument is null or empty. + if (string.IsNullOrWhiteSpace(argument)) { - // Throwing error if the argument is just path and not a file - throw new CommandLineException(CommandLineResources.EnableDiagUsage); + HandleInvalidDiagArgument(); } - // Create the base directory for logging if doesn't exist. Directory could be empty if just a - // filename is provided. E.g. log.txt - var logDirectory = Path.GetDirectoryName(argument); - if (!string.IsNullOrEmpty(logDirectory) && !this.fileHelper.DirectoryExists(logDirectory)) - { - this.fileHelper.CreateDirectory(logDirectory); - } + // Get diag argument list. + var diagArgumentList = GetDiagArgumentList(argument); - // Find full path and send this to testhost so that vstest and testhost create logs at same location. - argument = Path.GetFullPath(argument); + // Get diag file path. + var diagFilePathArg = diagArgumentList[0]; + var diagFilePath = GetDiagFilePath(diagFilePathArg); - // Catch exception(UnauthorizedAccessException, PathTooLongException...) if there is any at time of initialization. - if (!EqtTrace.InitializeVerboseTrace(argument)) - { - if (!string.IsNullOrEmpty(EqtTrace.ErrorOnInitialization)) - ConsoleOutput.Instance.Warning(false, EqtTrace.ErrorOnInitialization); - } - } + // Get diag parameters. + var diagParameterArgs = diagArgumentList.Skip(1); + var diagParameters = GetDiagParameters(diagParameterArgs); - private void InitializeDiagLogging(string diagFilePath, object arguments) - { - throw new NotImplementedException(); + // Initialize diag logging. + InitializeDiagLogging(diagFilePath, diagParameters); } - private object GetDiagArguments(string argument) + /// + /// Executes the argument processor. + /// + /// The . + public ArgumentProcessorResult Execute() { - throw new NotImplementedException(); + // Nothing to do since we updated the parameter during initialize parameter + return ArgumentProcessorResult.Success; } /// - /// Validates that argument is not empty. - /// Throws CommandLineException in case argument is empty. + /// Get diag parameters. /// - /// Diag argument. - private void ValidateArgumentNotEmpty(string argument) + /// Diag parameter args. + /// Diag parameters dictionary. + private Dictionary GetDiagParameters(IEnumerable diagParameterArgs) { - if (string.IsNullOrWhiteSpace(argument)) + var nameValueSeperator = new char[] { '=' }; + var parameters = new Dictionary(StringComparer.OrdinalIgnoreCase); + + // Get parameters from parameterNameValuePairs. + // Throw error in case of invalid name value pairs. + foreach (string diagParameterArg in diagParameterArgs) { - throw new CommandLineException(CommandLineResources.EnableDiagUsage); + var nameValuePair = diagParameterArg?.Split(nameValueSeperator, StringSplitOptions.RemoveEmptyEntries); + if (nameValuePair.Length == 2) + { + parameters[nameValuePair[0]] = nameValuePair[1]; + } + else + { + HandleInvalidDiagArgument(); + } } + + return parameters; } /// - /// Gets diag file path. + /// Get diag argument list. /// /// Argument. - /// Diag file path. - private string GetDiagFilePath(string argument) + /// Diag argument list. + private string[] GetDiagArgumentList(string argument) { - // If quotes are present in argument, value between first two quotes is considered as diag file path. - bool startsWithQuote = argument.StartsWith('"'); - if (startsWithQuote) + var argumentSeperator = new char[] { ';' }; + var diagArgumentList = argument?.Split(argumentSeperator, StringSplitOptions.RemoveEmptyEntries); + + // Handle invalid diag argument. + if (diagArgumentList == null || diagArgumentList.Length <= 0) { - var firstQuoteIndex = 0; - var secondQuoteIndex = argument.IndexOf('"', firstQuoteIndex + 1); - return argument.Substring(firstQuoteIndex + 1, secondQuoteIndex - firstQuoteIndex); + HandleInvalidDiagArgument(); } - // If no quotes are present, entire argument is considered as diag file path. - return argument; + return diagArgumentList; } /// - /// Executes the argument processor. + /// Initialize diag loggin. /// - /// The . - public ArgumentProcessorResult Execute() + /// Diag file path. + /// Diag parameters + private void InitializeDiagLogging(string diagFilePath, Dictionary diagParameters) { - // Nothing to do since we updated the parameter during initialize parameter - return ArgumentProcessorResult.Success; - } + // Get trace level from diag parameters. + var traceLevel = GetDiagTraceLevel(diagParameters); - #endregion + // Initialize trace. + // Trace initialized is false in case of any exception at time of initialization like Catch exception(UnauthorizedAccessException, PathTooLongException...) + var traceInitialized = EqtTrace.InitializeTrace(diagFilePath, traceLevel); - public static bool TryParseDiagArgument(string argument, out string diagFilePath, out Dictionary parameters) + // Show console warning in case trace is not initialized. + if (!traceInitialized && !string.IsNullOrEmpty(EqtTrace.ErrorOnInitialization)) + { + ConsoleOutput.Instance.Warning(false, EqtTrace.ErrorOnInitialization); + } + } + + /// + /// Gets diag trace level. + /// + /// Diag parameters. + /// Diag trace level. + private PlatformTraceLevel GetDiagTraceLevel(Dictionary diagParameters) { - diagFilePath = null; - parameters = null; + // If diag parameters is null, set value of trace level as verbose. + if (diagParameters == null) + { + return PlatformTraceLevel.Verbose; + } - var parseSucceeded = true; - var ArgumentSeperator = new char[] { ';' }; - var NameValueSeperator = new char[] { '=' }; + // Get trace level from diag parameters. + var traceLevelExists = diagParameters.TryGetValue(TraceLevelParam, out string traceLevelStr); + if (traceLevelExists && Enum.TryParse(traceLevelStr, true, out PlatformTraceLevel traceLevel)) + { + return traceLevel; + } - var argumentParts = argument.Split(ArgumentSeperator, StringSplitOptions.RemoveEmptyEntries); + // Default value of diag trace level is verbose. + return PlatformTraceLevel.Verbose; + } - if (argumentParts.Length > 0 && !argumentParts[0].Contains("=")) - { - diagFilePath = argumentParts[0]; + /// + /// Throws an exception indicating that the diag argument is invalid. + /// + private static void HandleInvalidDiagArgument() + { + throw new CommandLineException(CommandLineResources.EnableDiagUsage); + } - if (argumentParts.Length > 1) - { - parameters = new Dictionary(StringComparer.OrdinalIgnoreCase); - for (int index = 1; index < argumentParts.Length; ++index) - { - string[] nameValuePair = argumentParts[index].Split(NameValueSeperator, StringSplitOptions.RemoveEmptyEntries); - if (nameValuePair.Length == 2) - { - parameters[nameValuePair[0]] = nameValuePair[1]; - } - else - { - parseSucceeded = false; - break; - } - } - } - } - else + /// + /// Gets diag file path. + /// + /// Diag file path argument. + /// Diag file path. + private string GetDiagFilePath(string diagFilePathArgument) + { + // Throw error in case diag file path is not a valid file path + var fileExtension = Path.GetExtension(diagFilePathArgument); + if (string.IsNullOrWhiteSpace(fileExtension)) { - parseSucceeded = false; + HandleInvalidDiagArgument(); } - return parseSucceeded; + // Create base directory for diag file path (if doesn't exist) + CreateDirectoryIfNotExists(diagFilePathArgument); + + // return full diag file path. (This is done so that vstest and testhost create logs at same location.) + return Path.GetFullPath(diagFilePathArgument); } + + /// + /// Create directory if not exists. + /// + /// File path. + private void CreateDirectoryIfNotExists(string filePath) + { + // Create the base directory of file path if doesn't exist. + // Directory could be empty if just a filename is provided. E.g. log.txt + var directory = Path.GetDirectoryName(filePath); + if (!string.IsNullOrEmpty(directory) && !this.fileHelper.DirectoryExists(directory)) + { + this.fileHelper.CreateDirectory(directory); + } + } + + #endregion } } diff --git a/test/Microsoft.TestPlatform.CoreUtilities.UnitTests/Tracing/EqtTraceTests.cs b/test/Microsoft.TestPlatform.CoreUtilities.UnitTests/Tracing/EqtTraceTests.cs index 20a067f72c..5380233f96 100644 --- a/test/Microsoft.TestPlatform.CoreUtilities.UnitTests/Tracing/EqtTraceTests.cs +++ b/test/Microsoft.TestPlatform.CoreUtilities.UnitTests/Tracing/EqtTraceTests.cs @@ -33,7 +33,7 @@ public static void Init(TestContext testContext) Console.WriteLine(ex.Message); } - EqtTrace.InitializeVerboseTrace(logFile); + EqtTrace.InitializeTrace(logFile, PlatformTraceLevel.Verbose); } [TestMethod] diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyOperationManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyOperationManagerTests.cs index a2211c3c9a..d90a42f481 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyOperationManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyOperationManagerTests.cs @@ -85,7 +85,7 @@ public void SetupChannelShouldLaunchTestHost() public void SetupChannelShouldCreateTimestampedLogFileForHost() { this.mockRequestSender.Setup(rs => rs.InitializeCommunication()).Returns(123); - EqtTrace.InitializeVerboseTrace("log.txt"); + EqtTrace.InitializeTrace("log.txt", PlatformTraceLevel.Verbose); this.testOperationManager.SetupChannel(Enumerable.Empty()); diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/ProxyDataCollectionManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/ProxyDataCollectionManagerTests.cs index 2388b21be7..74e5a3675f 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/ProxyDataCollectionManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/ProxyDataCollectionManagerTests.cs @@ -118,7 +118,7 @@ public void InitializeShouldPassDiagArgumentsIfDiagIsEnabled() try { - EqtTrace.InitializeVerboseTrace("mylog.txt"); + EqtTrace.InitializeTrace("mylog.txt", PlatformTraceLevel.Verbose); this.mockDataCollectionRequestSender.Setup(x => x.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); this.proxyDataCollectionManager.Initialize(); @@ -133,7 +133,7 @@ public void InitializeShouldPassDiagArgumentsIfDiagIsEnabled() finally { // Restoring to initial state for EqtTrace - EqtTrace.InitializeVerboseTrace(traceFileName); + EqtTrace.InitializeTrace(traceFileName, PlatformTraceLevel.Verbose); #if NET451 EqtTrace.TraceLevel = traceLevel; #else diff --git a/test/vstest.console.UnitTests/Processors/EnableDiagArgumentProcessorTests.cs b/test/vstest.console.UnitTests/Processors/EnableDiagArgumentProcessorTests.cs index d7a0748498..b2a6916c92 100644 --- a/test/vstest.console.UnitTests/Processors/EnableDiagArgumentProcessorTests.cs +++ b/test/vstest.console.UnitTests/Processors/EnableDiagArgumentProcessorTests.cs @@ -48,7 +48,7 @@ public EnableDiagArgumentProcessorTests() public void Cleanup() { // Restoring to initial state for EqtTrace - EqtTrace.InitializeVerboseTrace(traceFileName); + EqtTrace.InitializeTrace(traceFileName, PlatformTraceLevel.Verbose); #if NET451 EqtTrace.TraceLevel = traceLevel; #else From 6f77e3501adf189943f42a704de807da16c46ec0 Mon Sep 17 00:00:00 2001 From: abhishkk Date: Mon, 9 Jul 2018 17:09:18 +0530 Subject: [PATCH 03/10] Adding unit tests --- .../Processors/EnableDiagArgumentProcessor.cs | 4 ++ .../Resources/Resources.Designer.cs | 5 +- src/vstest.console/Resources/Resources.resx | 8 ++- .../Resources/xlf/Resources.cs.xlf | 12 +++-- .../Resources/xlf/Resources.de.xlf | 12 +++-- .../Resources/xlf/Resources.es.xlf | 12 +++-- .../Resources/xlf/Resources.fr.xlf | 12 +++-- .../Resources/xlf/Resources.it.xlf | 12 +++-- .../Resources/xlf/Resources.ja.xlf | 12 +++-- .../Resources/xlf/Resources.ko.xlf | 12 +++-- .../Resources/xlf/Resources.pl.xlf | 12 +++-- .../Resources/xlf/Resources.pt-BR.xlf | 12 +++-- .../Resources/xlf/Resources.ru.xlf | 12 +++-- .../Resources/xlf/Resources.tr.xlf | 12 +++-- .../Resources/xlf/Resources.xlf | 8 ++- .../Resources/xlf/Resources.zh-Hans.xlf | 12 +++-- .../Resources/xlf/Resources.zh-Hant.xlf | 12 +++-- .../Tracing/EqtTraceTests.cs | 18 ++++++- .../Client/ProxyOperationManagerTests.cs | 20 ++++++++ .../ProxyDataCollectionManagerTests.cs | 5 +- .../ConsoleParametersTests.cs | 9 ++++ .../VsTestConsoleWrapperTests.cs | 1 + .../DataCollectorMainTests.cs | 35 ++++++++++++- .../DefaultEngineInvokerTests.cs | 20 +++++++- .../EnableDiagArgumentProcessorTests.cs | 51 +++++++++++++++++++ 25 files changed, 278 insertions(+), 62 deletions(-) diff --git a/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs b/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs index c8b565db83..00cf0c19b5 100644 --- a/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs +++ b/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs @@ -139,6 +139,7 @@ public void Initialize(string argument) var diagArgumentList = GetDiagArgumentList(argument); // Get diag file path. + // Note: Even though semi colon is valid file path, we are not respecting the file name having semi-colon [As we are separating arguments based on semi colon]. var diagFilePathArg = diagArgumentList[0]; var diagFilePath = GetDiagFilePath(diagFilePathArg); @@ -267,6 +268,9 @@ private static void HandleInvalidDiagArgument() /// Diag file path. private string GetDiagFilePath(string diagFilePathArgument) { + // Remove double quotes if present. + diagFilePathArgument = diagFilePathArgument.Replace("\"", ""); + // Throw error in case diag file path is not a valid file path var fileExtension = Path.GetExtension(diagFilePathArgument); if (string.IsNullOrWhiteSpace(fileExtension)) diff --git a/src/vstest.console/Resources/Resources.Designer.cs b/src/vstest.console/Resources/Resources.Designer.cs index b76b4d0eb2..74fada7554 100644 --- a/src/vstest.console/Resources/Resources.Designer.cs +++ b/src/vstest.console/Resources/Resources.Designer.cs @@ -477,10 +477,13 @@ public static string EnableCodeCoverageArgumentProcessorHelp /// Looks up a localized string similar to --Diag|/Diag:<Path to log file> /// Enable verbose logs for test platform. /// Logs are written to the provided file.. + /// + /// Change the trace level for logs as shown below + /// Example: /Diag:<Path to log file>;tracelevel=<Defaults to "verbose"> + /// Allowed values for tracelevel: off, error, warning, info and verbose. /// public static string EnableDiagUsage { - // TODO: Check this EnableLoggersArgumentHelp to change the help here. get { return ResourceManager.GetString("EnableDiagUsage", resourceCulture); diff --git a/src/vstest.console/Resources/Resources.resx b/src/vstest.console/Resources/Resources.resx index b0474546c0..e49ab83805 100644 --- a/src/vstest.console/Resources/Resources.resx +++ b/src/vstest.console/Resources/Resources.resx @@ -230,8 +230,12 @@ --Diag|/Diag:<Path to log file> - Enable verbose logs for test platform. - Logs are written to the provided file. + Enable logs for test platform. + Logs are written to the provided file. + + Change the trace level for logs as shown below + Example: /Diag:<Path to log file>;tracelevel=<Defaults to "verbose"> + Allowed values for tracelevel: off, error, warning, info and verbose. --logger|/logger:<Logger Uri/FriendlyName> diff --git a/src/vstest.console/Resources/xlf/Resources.cs.xlf b/src/vstest.console/Resources/xlf/Resources.cs.xlf index 7e0b81b9d4..5bbb983270 100644 --- a/src/vstest.console/Resources/xlf/Resources.cs.xlf +++ b/src/vstest.console/Resources/xlf/Resources.cs.xlf @@ -1387,12 +1387,16 @@ --Diag|/Diag:<Path to log file> - Enable verbose logs for test platform. - Logs are written to the provided file. - --Diag|/Diag:<Cesta k souboru protokolu> + Enable logs for test platform. + Logs are written to the provided file. + + Change the trace level for logs as shown below + Example: /Diag:<Path to log file>;tracelevel=<Defaults to "verbose"> + Allowed values for tracelevel: off, error, warning, info and verbose. + --Diag|/Diag:<Cesta k souboru protokolu> Povolí podrobné protokoly pro testovací platformu. Protokoly se zapisují do zadaného souboru. - + -Diag | / Diag: < cesta k souboru protokolu > Povolení podrobného protokolování pro testovací platformu. diff --git a/src/vstest.console/Resources/xlf/Resources.de.xlf b/src/vstest.console/Resources/xlf/Resources.de.xlf index 5552a47b5f..3b3e52f2f3 100644 --- a/src/vstest.console/Resources/xlf/Resources.de.xlf +++ b/src/vstest.console/Resources/xlf/Resources.de.xlf @@ -1387,12 +1387,16 @@ --Diag|/Diag:<Path to log file> - Enable verbose logs for test platform. - Logs are written to the provided file. - --Diag|/Diag:<Pfad zur Protokolldatei> + Enable logs for test platform. + Logs are written to the provided file. + + Change the trace level for logs as shown below + Example: /Diag:<Path to log file>;tracelevel=<Defaults to "verbose"> + Allowed values for tracelevel: off, error, warning, info and verbose. + --Diag|/Diag:<Pfad zur Protokolldatei> Aktiviert ausführliche Protokolle für die Testplattform. Protokolle werden in die angegebene Datei geschrieben. - + -Diag | / Diag: < Pfad zur Protokolldatei > Aktivieren Sie ausführliche Protokolle Testplattform. diff --git a/src/vstest.console/Resources/xlf/Resources.es.xlf b/src/vstest.console/Resources/xlf/Resources.es.xlf index cff5994979..41362d449e 100644 --- a/src/vstest.console/Resources/xlf/Resources.es.xlf +++ b/src/vstest.console/Resources/xlf/Resources.es.xlf @@ -1392,12 +1392,16 @@ --Diag|/Diag:<Path to log file> - Enable verbose logs for test platform. - Logs are written to the provided file. - --Diag|/Diag:<RutaDelArchivoDeRegistro> + Enable logs for test platform. + Logs are written to the provided file. + + Change the trace level for logs as shown below + Example: /Diag:<Path to log file>;tracelevel=<Defaults to "verbose"> + Allowed values for tracelevel: off, error, warning, info and verbose. + --Diag|/Diag:<RutaDelArchivoDeRegistro> Habilita registros detallados para la plataforma de pruebas. Los registros se escriben en el archivo proporcionado. - + --Diag | / Diag: < ruta de acceso al archivo de registro > Habilitar registros detallados de la plataforma de pruebas. diff --git a/src/vstest.console/Resources/xlf/Resources.fr.xlf b/src/vstest.console/Resources/xlf/Resources.fr.xlf index bdc627129e..8f8036f2b1 100644 --- a/src/vstest.console/Resources/xlf/Resources.fr.xlf +++ b/src/vstest.console/Resources/xlf/Resources.fr.xlf @@ -1387,12 +1387,16 @@ --Diag|/Diag:<Path to log file> - Enable verbose logs for test platform. - Logs are written to the provided file. - --Diag|/Diag:<chemin du fichier journal> + Enable logs for test platform. + Logs are written to the provided file. + + Change the trace level for logs as shown below + Example: /Diag:<Path to log file>;tracelevel=<Defaults to "verbose"> + Allowed values for tracelevel: off, error, warning, info and verbose. + --Diag|/Diag:<chemin du fichier journal> Permet d'activer les journaux détaillés pour la plateforme de test. Les journaux sont écrits dans le fichier fourni. - + --Diag | / Diag : < chemin d’accès au fichier journal > Activer les fichiers journaux détaillés pour la plate-forme de test. diff --git a/src/vstest.console/Resources/xlf/Resources.it.xlf b/src/vstest.console/Resources/xlf/Resources.it.xlf index 4564266cbf..6fe7bbabc2 100644 --- a/src/vstest.console/Resources/xlf/Resources.it.xlf +++ b/src/vstest.console/Resources/xlf/Resources.it.xlf @@ -1387,12 +1387,16 @@ --Diag|/Diag:<Path to log file> - Enable verbose logs for test platform. - Logs are written to the provided file. - --Diag|/Diag:<Percorso dei file di log> + Enable logs for test platform. + Logs are written to the provided file. + + Change the trace level for logs as shown below + Example: /Diag:<Path to log file>;tracelevel=<Defaults to "verbose"> + Allowed values for tracelevel: off, error, warning, info and verbose. + --Diag|/Diag:<Percorso dei file di log> Abilita i log dettagliati per la piattaforma di test. I log vengono scritti nel file specificato. - + -Diag | / Diag: < percorso file registro > Attiva log dettagliato per la piattaforma di test. diff --git a/src/vstest.console/Resources/xlf/Resources.ja.xlf b/src/vstest.console/Resources/xlf/Resources.ja.xlf index 003034bcc9..64005f437f 100644 --- a/src/vstest.console/Resources/xlf/Resources.ja.xlf +++ b/src/vstest.console/Resources/xlf/Resources.ja.xlf @@ -1387,12 +1387,16 @@ --Diag|/Diag:<Path to log file> - Enable verbose logs for test platform. - Logs are written to the provided file. - --Diag|/Diag:<ログ ファイルのパス> + Enable logs for test platform. + Logs are written to the provided file. + + Change the trace level for logs as shown below + Example: /Diag:<Path to log file>;tracelevel=<Defaults to "verbose"> + Allowed values for tracelevel: off, error, warning, info and verbose. + --Diag|/Diag:<ログ ファイルのパス> テスト プラットフォームの詳細ログを有効にします。 ログは指定されたファイルに書き込まれます。 - + --Diag | または Diag: < ログ ファイルへのパス > テスト プラットフォームの詳細なログを有効にします。 diff --git a/src/vstest.console/Resources/xlf/Resources.ko.xlf b/src/vstest.console/Resources/xlf/Resources.ko.xlf index 0a8462e503..e4c7733803 100644 --- a/src/vstest.console/Resources/xlf/Resources.ko.xlf +++ b/src/vstest.console/Resources/xlf/Resources.ko.xlf @@ -1387,12 +1387,16 @@ --Diag|/Diag:<Path to log file> - Enable verbose logs for test platform. - Logs are written to the provided file. - --Diag|/Diag:<로그 파일 경로> + Enable logs for test platform. + Logs are written to the provided file. + + Change the trace level for logs as shown below + Example: /Diag:<Path to log file>;tracelevel=<Defaults to "verbose"> + Allowed values for tracelevel: off, error, warning, info and verbose. + --Diag|/Diag:<로그 파일 경로> 테스트 플랫폼에 대해 자세한 정보 표시 로그를 사용하도록 설정합니다. 로그가 제공된 파일에 기록됩니다. - + -진단 | / 진단: < 로그 파일 경로 > 테스트 플랫폼에 대 한 자세한 정보 표시 로그를 활성화 합니다. diff --git a/src/vstest.console/Resources/xlf/Resources.pl.xlf b/src/vstest.console/Resources/xlf/Resources.pl.xlf index 12931af6d2..9126da381c 100644 --- a/src/vstest.console/Resources/xlf/Resources.pl.xlf +++ b/src/vstest.console/Resources/xlf/Resources.pl.xlf @@ -1386,12 +1386,16 @@ --Diag|/Diag:<Path to log file> - Enable verbose logs for test platform. - Logs are written to the provided file. - --Diag|/Diag:<ścieżka do pliku dziennika> + Enable logs for test platform. + Logs are written to the provided file. + + Change the trace level for logs as shown below + Example: /Diag:<Path to log file>;tracelevel=<Defaults to "verbose"> + Allowed values for tracelevel: off, error, warning, info and verbose. + --Diag|/Diag:<ścieżka do pliku dziennika> Włącza pełne dzienniki dla platformy testowej. Dzienniki są zapisywane do podanego pliku. - + --Diag | / Diag: < ścieżka do pliku dziennika > Włączyć pełne dzienniki dla platformy testowej. diff --git a/src/vstest.console/Resources/xlf/Resources.pt-BR.xlf b/src/vstest.console/Resources/xlf/Resources.pt-BR.xlf index 2b27ac4c3d..9cb5342c08 100644 --- a/src/vstest.console/Resources/xlf/Resources.pt-BR.xlf +++ b/src/vstest.console/Resources/xlf/Resources.pt-BR.xlf @@ -1386,12 +1386,16 @@ --Diag|/Diag:<Path to log file> - Enable verbose logs for test platform. - Logs are written to the provided file. - --Diag|/Diag:<Path to log file> + Enable logs for test platform. + Logs are written to the provided file. + + Change the trace level for logs as shown below + Example: /Diag:<Path to log file>;tracelevel=<Defaults to "verbose"> + Allowed values for tracelevel: off, error, warning, info and verbose. + --Diag|/Diag:<Path to log file> Habilitar logs detalhados para a plataforma de teste. Os logs são gravados no arquivo fornecido. - + -Diag | / Diag: < caminho para arquivo de log > Habilite logs verbosos para plataforma de teste. diff --git a/src/vstest.console/Resources/xlf/Resources.ru.xlf b/src/vstest.console/Resources/xlf/Resources.ru.xlf index 66b8ffde4d..2d65dd00d8 100644 --- a/src/vstest.console/Resources/xlf/Resources.ru.xlf +++ b/src/vstest.console/Resources/xlf/Resources.ru.xlf @@ -1387,12 +1387,16 @@ --Diag|/Diag:<Path to log file> - Enable verbose logs for test platform. - Logs are written to the provided file. - --Diag|/Diag:<путь к файлу журнала> + Enable logs for test platform. + Logs are written to the provided file. + + Change the trace level for logs as shown below + Example: /Diag:<Path to log file>;tracelevel=<Defaults to "verbose"> + Allowed values for tracelevel: off, error, warning, info and verbose. + --Diag|/Diag:<путь к файлу журнала> Включение подробных журналов для платформы тестирования. Журналы записываются в указанный файл. - + --Diag | / Diag: < путь к файлу журнала > Включение подробных журналов для тестовой платформы. diff --git a/src/vstest.console/Resources/xlf/Resources.tr.xlf b/src/vstest.console/Resources/xlf/Resources.tr.xlf index 6abe9d22c4..db4cfe4935 100644 --- a/src/vstest.console/Resources/xlf/Resources.tr.xlf +++ b/src/vstest.console/Resources/xlf/Resources.tr.xlf @@ -1387,12 +1387,16 @@ --Diag|/Diag:<Path to log file> - Enable verbose logs for test platform. - Logs are written to the provided file. - --Diag|/Diag:<Günlük dosyasının yolu> + Enable logs for test platform. + Logs are written to the provided file. + + Change the trace level for logs as shown below + Example: /Diag:<Path to log file>;tracelevel=<Defaults to "verbose"> + Allowed values for tracelevel: off, error, warning, info and verbose. + --Diag|/Diag:<Günlük dosyasının yolu> Test platformuna yönelik ayrıntılı günlükleri etkinleştirir. Günlükler belirtilen dosyaya yazılır. - + --Diag | / Diag: < günlük dosyası yolu > Test platformu için ayrıntılı günlüklerini etkinleştirir. diff --git a/src/vstest.console/Resources/xlf/Resources.xlf b/src/vstest.console/Resources/xlf/Resources.xlf index 08b70745ed..1d0472fec4 100644 --- a/src/vstest.console/Resources/xlf/Resources.xlf +++ b/src/vstest.console/Resources/xlf/Resources.xlf @@ -591,8 +591,12 @@ --Diag|/Diag:<Path to log file> - Enable verbose logs for test platform. - Logs are written to the provided file. + Enable logs for test platform. + Logs are written to the provided file. + + Change the trace level for logs as shown below + Example: /Diag:<Path to log file>;tracelevel=<Defaults to "verbose"> + Allowed values for tracelevel: off, error, warning, info and verbose. diff --git a/src/vstest.console/Resources/xlf/Resources.zh-Hans.xlf b/src/vstest.console/Resources/xlf/Resources.zh-Hans.xlf index c4b72f72ee..525b4a1ec7 100644 --- a/src/vstest.console/Resources/xlf/Resources.zh-Hans.xlf +++ b/src/vstest.console/Resources/xlf/Resources.zh-Hans.xlf @@ -1387,12 +1387,16 @@ --Diag|/Diag:<Path to log file> - Enable verbose logs for test platform. - Logs are written to the provided file. - --Diag|/Diag:<Path to log file> + Enable logs for test platform. + Logs are written to the provided file. + + Change the trace level for logs as shown below + Example: /Diag:<Path to log file>;tracelevel=<Defaults to "verbose"> + Allowed values for tracelevel: off, error, warning, info and verbose. + --Diag|/Diag:<Path to log file> 为测试平台启用详细日志。 日志写入到所提供的文件。 - + -诊断 | / 诊断︰ < 日志文件路径 > 启用详细日志中的测试平台。 diff --git a/src/vstest.console/Resources/xlf/Resources.zh-Hant.xlf b/src/vstest.console/Resources/xlf/Resources.zh-Hant.xlf index bf7c97abba..a2f2be1ae6 100644 --- a/src/vstest.console/Resources/xlf/Resources.zh-Hant.xlf +++ b/src/vstest.console/Resources/xlf/Resources.zh-Hant.xlf @@ -1387,12 +1387,16 @@ --Diag|/Diag:<Path to log file> - Enable verbose logs for test platform. - Logs are written to the provided file. - --Diag|/Diag:<記錄檔的路徑> + Enable logs for test platform. + Logs are written to the provided file. + + Change the trace level for logs as shown below + Example: /Diag:<Path to log file>;tracelevel=<Defaults to "verbose"> + Allowed values for tracelevel: off, error, warning, info and verbose. + --Diag|/Diag:<記錄檔的路徑> 啟用測試平台的詳細資訊記錄檔。 記錄會寫入提供的檔案中。 - + -诊断 | / 诊断︰ < 日志文件路径 > 启用详细日志中的测试平台。 diff --git a/test/Microsoft.TestPlatform.CoreUtilities.UnitTests/Tracing/EqtTraceTests.cs b/test/Microsoft.TestPlatform.CoreUtilities.UnitTests/Tracing/EqtTraceTests.cs index 5380233f96..1f867808ba 100644 --- a/test/Microsoft.TestPlatform.CoreUtilities.UnitTests/Tracing/EqtTraceTests.cs +++ b/test/Microsoft.TestPlatform.CoreUtilities.UnitTests/Tracing/EqtTraceTests.cs @@ -33,7 +33,7 @@ public static void Init(TestContext testContext) Console.WriteLine(ex.Message); } - EqtTrace.InitializeTrace(logFile, PlatformTraceLevel.Verbose); + EqtTrace.InitializeTrace(logFile, PlatformTraceLevel.Off); } [TestMethod] @@ -134,6 +134,22 @@ public void TraceShouldWriteInfo() Assert.IsTrue(ReadLogFile().Contains("Dummy Info Message"), "Expected Info message"); } + [TestMethod] + public void TraceShouldNotWriteVerboseIfTraceLevelIsInfo() + { +#if NET451 + EqtTrace.TraceLevel = TraceLevel.Info; +#else + EqtTrace.TraceLevel = PlatformTraceLevel.Info; +#endif + EqtTrace.Info("Dummy Info Message"); + EqtTrace.Verbose("Unexpected Dummy Verbose Message"); + + var logFileContent = ReadLogFile(); + Assert.IsFalse(logFileContent.Contains("Unexpected Dummy Verbose Message"), "Verbose message not expected"); + Assert.IsTrue(logFileContent.Contains("Dummy Info Message"), "Expected Info message"); + } + [TestMethod] public void TraceShouldNotWriteIfDoNotInitializationIsSetToTrue() { diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyOperationManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyOperationManagerTests.cs index d90a42f481..96bafc2b74 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyOperationManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyOperationManagerTests.cs @@ -119,6 +119,26 @@ public void SetupChannelShouldAddRunnerProcessIdForTestHost() It.Is(t => t.RunnerProcessId.Equals(Process.GetCurrentProcess().Id)))); } + [TestMethod] + public void SetupChannelShouldAddCorrectTraceLevelForTestHost() + { +#if NET451 + EqtTrace.TraceLevel = TraceLevel.Info; +#else + EqtTrace.TraceLevel = PlatformTraceLevel.Info; +#endif + + this.mockRequestSender.Setup(rs => rs.InitializeCommunication()).Returns(123); + this.testOperationManager.SetupChannel(Enumerable.Empty()); + + this.mockTestHostManager.Verify( + th => + th.GetTestHostProcessStartInfo( + It.IsAny>(), + null, + It.Is(t => t.TraceLevel == (int)PlatformTraceLevel.Info))); + } + [TestMethod] public void SetupChannelShouldSetupServerForCommunication() { diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/ProxyDataCollectionManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/ProxyDataCollectionManagerTests.cs index 74e5a3675f..274ec42080 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/ProxyDataCollectionManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/ProxyDataCollectionManagerTests.cs @@ -118,16 +118,17 @@ public void InitializeShouldPassDiagArgumentsIfDiagIsEnabled() try { - EqtTrace.InitializeTrace("mylog.txt", PlatformTraceLevel.Verbose); + EqtTrace.InitializeTrace("mylog.txt", PlatformTraceLevel.Info); this.mockDataCollectionRequestSender.Setup(x => x.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); this.proxyDataCollectionManager.Initialize(); + var expectedTraceLevel = (int)PlatformTraceLevel.Info; this.mockDataCollectionLauncher.Verify( x => x.LaunchDataCollector( It.IsAny>(), - It.Is>(list => list.Contains("--diag"))), + It.Is>(list => list.Contains("--diag") && list.Contains("--tracelevel") && list.Contains(expectedTraceLevel.ToString()))), Times.Once); } finally diff --git a/test/TranslationLayer.UnitTests/ConsoleParametersTests.cs b/test/TranslationLayer.UnitTests/ConsoleParametersTests.cs index 2772859644..5e4a8a8bce 100644 --- a/test/TranslationLayer.UnitTests/ConsoleParametersTests.cs +++ b/test/TranslationLayer.UnitTests/ConsoleParametersTests.cs @@ -4,6 +4,8 @@ namespace Microsoft.TestPlatform.VsTestConsole.TranslationLayer.UnitTests { using Microsoft.TestPlatform.VsTestConsole.TranslationLayer; + using Microsoft.VisualStudio.TestPlatform.ObjectModel; + using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -26,5 +28,12 @@ public void LogFilePathShouldEnsureDoubleQuote() Assert.IsTrue(result.StartsWith("\"")); } + + [TestMethod] + public void TraceLevelShouldHaveVerboseAsDefaultValue() + { + var consoleParameters = new ConsoleParameters(new FileHelper()); + Assert.AreEqual(consoleParameters.TraceLevel, PlatformTraceLevel.Verbose); + } } } diff --git a/test/TranslationLayer.UnitTests/VsTestConsoleWrapperTests.cs b/test/TranslationLayer.UnitTests/VsTestConsoleWrapperTests.cs index 5777957c99..0ad3f00317 100644 --- a/test/TranslationLayer.UnitTests/VsTestConsoleWrapperTests.cs +++ b/test/TranslationLayer.UnitTests/VsTestConsoleWrapperTests.cs @@ -63,6 +63,7 @@ public void StartSessionShouldStartVsTestConsoleWithCorrectArguments() Assert.AreEqual(expectedParentProcessId, this.consoleParameters.ParentProcessId, "Parent process Id must be set"); Assert.AreEqual(inputPort, this.consoleParameters.PortNumber, "Port number must be set"); + Assert.AreEqual(PlatformTraceLevel.Verbose, this.consoleParameters.TraceLevel, "Default value of trace level should be verbose."); this.mockProcessManager.Verify(pm => pm.StartProcess(this.consoleParameters), Times.Once); } diff --git a/test/datacollector.UnitTests/DataCollectorMainTests.cs b/test/datacollector.UnitTests/DataCollectorMainTests.cs index 9a122778c5..5933c8d047 100644 --- a/test/datacollector.UnitTests/DataCollectorMainTests.cs +++ b/test/datacollector.UnitTests/DataCollectorMainTests.cs @@ -4,9 +4,15 @@ namespace Microsoft.VisualStudio.TestPlatform.Common.DataCollector.UnitTests { using System; + using System.Diagnostics; using System.Globalization; using CommunicationUtilities.DataCollection.Interfaces; using CoreUtilities.Helpers; + using Microsoft.VisualStudio.TestPlatform.Common.DataCollector.Interfaces; + using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities; + using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.DataCollection; + using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Interfaces; + using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -20,11 +26,13 @@ namespace Microsoft.VisualStudio.TestPlatform.Common.DataCollector.UnitTests [TestClass] public class DataCollectorMainTests { - private readonly string[] args = {"--port", "1025", "--parentprocessid", "100" }; + private readonly string[] args = {"--port", "1025", "--parentprocessid", "100", "--diag", "abc.txt", "--tracelevel", "3" }; private static readonly string TimoutErrorMessage = "datacollector process failed to connect to vstest.console process after 90 seconds. This may occur due to machine slowness, please set environment variable VSTEST_CONNECTION_TIMEOUT to increase timeout."; private Mock mockProcessHelper; + private Mock mockMessageSink; + private Mock mockCommunicationManager; private Mock mockEnvironment; private Mock mockDataCollectionRequestHandler; private DataCollectorMain dataCollectorMain; @@ -32,6 +40,8 @@ public class DataCollectorMainTests public DataCollectorMainTests() { this.mockProcessHelper = new Mock(); + this.mockMessageSink = new Mock(); + this.mockCommunicationManager = new Mock(); this.mockEnvironment = new Mock(); this.mockDataCollectionRequestHandler = new Mock(); this.dataCollectorMain = new DataCollectorMain(this.mockProcessHelper.Object, this.mockEnvironment.Object, this.mockDataCollectionRequestHandler.Object); @@ -60,6 +70,29 @@ public void RunShouldTimeoutBasedDefaulValueIfEnvVariableNotSet() this.mockDataCollectionRequestHandler.Verify(rh => rh.WaitForRequestSenderConnection(EnvironmentHelper.DefaultConnectionTimeout * 1000)); } + [TestMethod] + public void RunShouldInitializeTraceWithCorrectTraceLevel() + { + // Setting EqtTrace.TraceLevel to a value other than info. +#if NET451 + EqtTrace.TraceLevel = TraceLevel.Verbose; +#else + EqtTrace.TraceLevel = PlatformTraceLevel.Verbose; +#endif + // Action + try + { + this.dataCollectorMain.Run(args); // Passing tracelevel as info from args. + } + catch (Exception) + { + // Ignore exceptions as they are coming because of trying to type cast mock interface into different object. + } + + // Verify + Assert.AreEqual(PlatformTraceLevel.Info, EqtTrace.TraceLevel); + } + [TestMethod] public void RunShouldThrowIfTimeoutOccured() { diff --git a/test/testhost.UnitTests/DefaultEngineInvokerTests.cs b/test/testhost.UnitTests/DefaultEngineInvokerTests.cs index 3f392d06b1..293f0d3eda 100644 --- a/test/testhost.UnitTests/DefaultEngineInvokerTests.cs +++ b/test/testhost.UnitTests/DefaultEngineInvokerTests.cs @@ -5,6 +5,7 @@ namespace testhost.UnitTests { using System; using System.Collections.Generic; + using System.Diagnostics; using System.Globalization; using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Interfaces; using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Helpers; @@ -28,7 +29,8 @@ public class DefaultEngineInvokerTests { "--endpoint", "127.0.0.1:021291" }, { "--role", "client"}, { "--parentprocessid", ParentProcessId.ToString() }, - { "--diag", @"C:\Users\samadala\src\vstest\log_3.host.18-04-17_20-25-45_48171_1.txt"}, + { "--diag", "temp.txt"}, + { "--tracelevel", "3"}, { "--telemetryoptedin", "false"}, { "--datacollectionport", "21290"} }; @@ -93,5 +95,21 @@ public void InvokeShouldSetParentProcessExistCallback() this.mockProcssHelper.Verify(h => h.SetExitCallback(ParentProcessId, It.IsAny>())); } + + [TestMethod] + public void InvokeShouldInitializeTraceWithCorrectTraceLevel() + { + // Setting EqtTrace.TraceLevel to a value other than info. +#if NET451 + EqtTrace.TraceLevel = TraceLevel.Verbose; +#else + EqtTrace.TraceLevel = PlatformTraceLevel.Verbose; +#endif + + this.engineInvoker.Invoke(argsDictionary); + + // Verify + Assert.AreEqual(PlatformTraceLevel.Info, EqtTrace.TraceLevel); + } } } diff --git a/test/vstest.console.UnitTests/Processors/EnableDiagArgumentProcessorTests.cs b/test/vstest.console.UnitTests/Processors/EnableDiagArgumentProcessorTests.cs index b2a6916c92..09a5d817ad 100644 --- a/test/vstest.console.UnitTests/Processors/EnableDiagArgumentProcessorTests.cs +++ b/test/vstest.console.UnitTests/Processors/EnableDiagArgumentProcessorTests.cs @@ -3,6 +3,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.UnitTests.Processors { + using System; using System.Diagnostics; using System.IO; @@ -91,6 +92,56 @@ public void EnableDiagArgumentProcessorExecutorShouldThrowIfAPathIsProvided() Assert.ThrowsException(() => this.diagProcessor.Executor.Value.Initialize("foo")); } + [TestMethod] + [DataRow("")] + [DataRow(" ")] + [DataRow("abs;dfsdc.txt;verbosity=normal")] // ; in file path is not supported + [DataRow("abc.txt;verbosity=normal=verbose")] // Multiple '=' in parameters + [DataRow("\"abs;dfsdc.txt\";verbosity=normal")] // Even though in escaped double quotes, semi colon is not supported in file path + public void EnableDiagArgumentProcessorExecutorShouldThrowIfInvalidArgument(string argument) + { + Assert.ThrowsException(() => this.diagProcessor.Executor.Value.Initialize(argument)); + } + + [TestMethod] + [DataRow("abc.txt")] + [DataRow("abc.txt;verbosity=normal")] + [DataRow("abc.txt;tracelevel=info;newkey=newvalue")] + [DataRow("\"abc.txt\";verbosity=normal;newkey=newvalue")] //escaped double quotes are allowed for file path. + [DataRow(";;abc.txt;;;;verbosity=normal;;;;")] + public void EnableDiagArgumentProcessorExecutorShouldNotThrowIfValidArgument(string argument) + { + try + { + this.diagProcessor.Executor.Value.Initialize(argument); + } + catch (Exception ex) + { + Assert.Fail("Expected no exception, but got: " + ex.Message); + } + } + + [TestMethod] + [DataRow("abc.txt;tracelevel=info;newkey=newvalue")] + [DataRow("abc.txt;tracelevel=info;")] + [DataRow("abc.txt;tracelevel=INfO")] + [DataRow("abc.txt;traCELevel=info")] + [DataRow("abc.txt;traCELevel=INfO")] + public void EnableDiagArgumentProcessorExecutorShouldInitializeTraceWithCorrectTraceLevel(string argument) + { + // Setting any trace level other than info. +#if NET451 + EqtTrace.TraceLevel = TraceLevel.Verbose; +#else + EqtTrace.TraceLevel = PlatformTraceLevel.Verbose; +#endif + + this.diagProcessor.Executor.Value.Initialize(argument); + + Assert.AreEqual(PlatformTraceLevel.Info, EqtTrace.TraceLevel); + Assert.IsTrue(EqtTrace.LogFile.Contains("abc.txt")); + } + [TestMethod] public void EnableDiagArgumentProcessorExecutorShouldCreateDirectoryOfLogFileIfNotExists() { From ed71fdff3805e001274fae176554b08285a8034d Mon Sep 17 00:00:00 2001 From: abhishkk Date: Mon, 9 Jul 2018 17:13:49 +0530 Subject: [PATCH 04/10] resource correction --- src/vstest.console/Resources/Resources.Designer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vstest.console/Resources/Resources.Designer.cs b/src/vstest.console/Resources/Resources.Designer.cs index 74fada7554..e2154a44d3 100644 --- a/src/vstest.console/Resources/Resources.Designer.cs +++ b/src/vstest.console/Resources/Resources.Designer.cs @@ -475,8 +475,8 @@ public static string EnableCodeCoverageArgumentProcessorHelp /// /// Looks up a localized string similar to --Diag|/Diag:<Path to log file> - /// Enable verbose logs for test platform. - /// Logs are written to the provided file.. + /// Enable logs for test platform. + /// Logs are written to the provided file. /// /// Change the trace level for logs as shown below /// Example: /Diag:<Path to log file>;tracelevel=<Defaults to "verbose"> From fa521cbb03b0b58cdb36ca293139dec73f5d2c29 Mon Sep 17 00:00:00 2001 From: Abhishek Kumawat Date: Mon, 9 Jul 2018 23:42:11 +0530 Subject: [PATCH 05/10] review comments --- .../Processors/EnableDiagArgumentProcessor.cs | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs b/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs index 00cf0c19b5..8eb6220cc7 100644 --- a/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs +++ b/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs @@ -132,7 +132,7 @@ public void Initialize(string argument) // Throw error if argument is null or empty. if (string.IsNullOrWhiteSpace(argument)) { - HandleInvalidDiagArgument(); + throw new CommandLineException(CommandLineResources.EnableDiagUsage); } // Get diag argument list. @@ -182,7 +182,7 @@ private Dictionary GetDiagParameters(IEnumerable diagPar } else { - HandleInvalidDiagArgument(); + throw new CommandLineException(CommandLineResources.EnableDiagUsage); } } @@ -199,10 +199,10 @@ private string[] GetDiagArgumentList(string argument) var argumentSeperator = new char[] { ';' }; var diagArgumentList = argument?.Split(argumentSeperator, StringSplitOptions.RemoveEmptyEntries); - // Handle invalid diag argument. + // Throw error in case of invalid diag argument. if (diagArgumentList == null || diagArgumentList.Length <= 0) { - HandleInvalidDiagArgument(); + throw new CommandLineException(CommandLineResources.EnableDiagUsage); } return diagArgumentList; @@ -253,14 +253,6 @@ private PlatformTraceLevel GetDiagTraceLevel(Dictionary diagPara return PlatformTraceLevel.Verbose; } - /// - /// Throws an exception indicating that the diag argument is invalid. - /// - private static void HandleInvalidDiagArgument() - { - throw new CommandLineException(CommandLineResources.EnableDiagUsage); - } - /// /// Gets diag file path. /// @@ -275,7 +267,7 @@ private string GetDiagFilePath(string diagFilePathArgument) var fileExtension = Path.GetExtension(diagFilePathArgument); if (string.IsNullOrWhiteSpace(fileExtension)) { - HandleInvalidDiagArgument(); + throw new CommandLineException(CommandLineResources.EnableDiagUsage); } // Create base directory for diag file path (if doesn't exist) From 371d522a0984a05dcab7f52e109ce106c797344b Mon Sep 17 00:00:00 2001 From: abhishkk Date: Tue, 10 Jul 2018 15:05:29 +0530 Subject: [PATCH 06/10] review comments --- src/datacollector/DataCollectorMain.cs | 12 ++- src/testhost.x86/DefaultEngineInvoker.cs | 8 +- .../EnableBlameArgumentProcessor.cs | 3 +- .../Processors/EnableDiagArgumentProcessor.cs | 52 +-------- .../EnableLoggerArgumentProcessor.cs | 101 +++--------------- .../Utilities/ArgumemtProcessorUtilities.cs | 62 +++++++++++ .../Processors/Utilities/LoggerUtilities.cs | 92 +++++++++------- ...TestRunnerConnectionInfoExtensionsTests.cs | 8 +- .../DataCollectorMainTests.cs | 62 ++++++----- .../DefaultEngineInvokerTests.cs | 25 ++++- .../EnableDiagArgumentProcessorTests.cs | 2 +- .../ArgumentProcessorUtilitiesTests.cs | 40 +++++++ 12 files changed, 262 insertions(+), 205 deletions(-) create mode 100644 src/vstest.console/Processors/Utilities/ArgumemtProcessorUtilities.cs create mode 100644 test/vstest.console.UnitTests/Processors/Utilities/ArgumentProcessorUtilitiesTests.cs diff --git a/src/datacollector/DataCollectorMain.cs b/src/datacollector/DataCollectorMain.cs index 0f20de8048..7201c0d761 100644 --- a/src/datacollector/DataCollectorMain.cs +++ b/src/datacollector/DataCollectorMain.cs @@ -70,8 +70,14 @@ public void Run(string[] args) string logFile; if (argsDictionary.TryGetValue(LogFileArgument, out logFile)) { - var traceLevel = CommandLineArgumentsHelper.GetIntArgFromDict(argsDictionary, TraceLevelArgument); - EqtTrace.InitializeTrace(logFile, (PlatformTraceLevel)traceLevel); + var traceLevelInt = CommandLineArgumentsHelper.GetIntArgFromDict(argsDictionary, TraceLevelArgument); + + // In case traceLevelInt is not defined in PlatfromTraceLevel, default it to verbose. + var traceLevel = Enum.IsDefined(typeof(PlatformTraceLevel), traceLevelInt) ? + (PlatformTraceLevel)traceLevelInt : + PlatformTraceLevel.Verbose; + + EqtTrace.InitializeTrace(logFile, traceLevel); } else { @@ -106,7 +112,7 @@ public void Run(string[] args) // Can only do this after InitializeCommunication because datacollector cannot "Send Log" unless communications are initialized if (!string.IsNullOrEmpty(EqtTrace.LogFile)) { - ((DataCollectionRequestHandler)this.requestHandler).SendDataCollectionMessage(new DataCollectionMessageEventArgs(TestMessageLevel.Informational, string.Format("Logging DataCollector Diagnostics in file: {0}", EqtTrace.LogFile))); + (this.requestHandler as DataCollectionRequestHandler)?.SendDataCollectionMessage(new DataCollectionMessageEventArgs(TestMessageLevel.Informational, string.Format("Logging DataCollector Diagnostics in file: {0}", EqtTrace.LogFile))); } // Start processing async in a different task diff --git a/src/testhost.x86/DefaultEngineInvoker.cs b/src/testhost.x86/DefaultEngineInvoker.cs index 87796c9882..24f8c5be5d 100644 --- a/src/testhost.x86/DefaultEngineInvoker.cs +++ b/src/testhost.x86/DefaultEngineInvoker.cs @@ -231,7 +231,13 @@ private static void InitializeEqtTrace(IDictionary argsDictionar if (argsDictionary.TryGetValue(LogFileArgument, out string logFile)) { var traceLevelInt = CommandLineArgumentsHelper.GetIntArgFromDict(argsDictionary, TraceLevelArgument); - EqtTrace.InitializeTrace(logFile, (PlatformTraceLevel)traceLevelInt); + + // In case traceLevelInt is not defined in PlatfromTraceLevel, default it to verbose. + var traceLevel = Enum.IsDefined(typeof(PlatformTraceLevel), traceLevelInt) ? + (PlatformTraceLevel)traceLevelInt : + PlatformTraceLevel.Verbose; + + EqtTrace.InitializeTrace(logFile, traceLevel); } else { diff --git a/src/vstest.console/Processors/EnableBlameArgumentProcessor.cs b/src/vstest.console/Processors/EnableBlameArgumentProcessor.cs index 32a42ad4e3..2720b79421 100644 --- a/src/vstest.console/Processors/EnableBlameArgumentProcessor.cs +++ b/src/vstest.console/Processors/EnableBlameArgumentProcessor.cs @@ -15,6 +15,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.Processors using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions; using Microsoft.VisualStudio.TestPlatform.Utilities; + using Microsoft.VisualStudio.TestPlatform.CommandLine.Processors.Utilities; internal class EnableBlameArgumentProcessor : IArgumentProcessor { @@ -148,7 +149,7 @@ public void Initialize(string argument) } // Add Blame Logger - EnableLoggerArgumentExecutor.AddLoggerToRunSettings(BlameFriendlyName, this.runSettingsManager); + LoggerUtilities.AddLoggerToRunSettings(BlameFriendlyName, null, this.runSettingsManager); // Add Blame Data Collector CollectArgumentExecutor.AddDataCollectorToRunSettings(BlameFriendlyName, this.runSettingsManager); diff --git a/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs b/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs index 8eb6220cc7..4b4d14d64e 100644 --- a/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs +++ b/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs @@ -7,6 +7,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.Processors using System.Collections.Generic; using System.IO; using System.Linq; + using Microsoft.VisualStudio.TestPlatform.CommandLine.Processors.Utilities; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.Utilities; using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; @@ -136,7 +137,7 @@ public void Initialize(string argument) } // Get diag argument list. - var diagArgumentList = GetDiagArgumentList(argument); + var diagArgumentList = ArgumemtProcessorUtilities.GetArgumentList(argument, ArgumemtProcessorUtilities.SemiColonArgumentSeperator, CommandLineResources.EnableDiagUsage); // Get diag file path. // Note: Even though semi colon is valid file path, we are not respecting the file name having semi-colon [As we are separating arguments based on semi colon]. @@ -145,7 +146,7 @@ public void Initialize(string argument) // Get diag parameters. var diagParameterArgs = diagArgumentList.Skip(1); - var diagParameters = GetDiagParameters(diagParameterArgs); + var diagParameters = ArgumemtProcessorUtilities.GetArgumentParameters(diagParameterArgs, ArgumemtProcessorUtilities.EqualNameValueSeperator, CommandLineResources.EnableDiagUsage); // Initialize diag logging. InitializeDiagLogging(diagFilePath, diagParameters); @@ -161,53 +162,6 @@ public ArgumentProcessorResult Execute() return ArgumentProcessorResult.Success; } - /// - /// Get diag parameters. - /// - /// Diag parameter args. - /// Diag parameters dictionary. - private Dictionary GetDiagParameters(IEnumerable diagParameterArgs) - { - var nameValueSeperator = new char[] { '=' }; - var parameters = new Dictionary(StringComparer.OrdinalIgnoreCase); - - // Get parameters from parameterNameValuePairs. - // Throw error in case of invalid name value pairs. - foreach (string diagParameterArg in diagParameterArgs) - { - var nameValuePair = diagParameterArg?.Split(nameValueSeperator, StringSplitOptions.RemoveEmptyEntries); - if (nameValuePair.Length == 2) - { - parameters[nameValuePair[0]] = nameValuePair[1]; - } - else - { - throw new CommandLineException(CommandLineResources.EnableDiagUsage); - } - } - - return parameters; - } - - /// - /// Get diag argument list. - /// - /// Argument. - /// Diag argument list. - private string[] GetDiagArgumentList(string argument) - { - var argumentSeperator = new char[] { ';' }; - var diagArgumentList = argument?.Split(argumentSeperator, StringSplitOptions.RemoveEmptyEntries); - - // Throw error in case of invalid diag argument. - if (diagArgumentList == null || diagArgumentList.Length <= 0) - { - throw new CommandLineException(CommandLineResources.EnableDiagUsage); - } - - return diagArgumentList; - } - /// /// Initialize diag loggin. /// diff --git a/src/vstest.console/Processors/EnableLoggerArgumentProcessor.cs b/src/vstest.console/Processors/EnableLoggerArgumentProcessor.cs index 117b098c15..6ff8ce4c15 100644 --- a/src/vstest.console/Processors/EnableLoggerArgumentProcessor.cs +++ b/src/vstest.console/Processors/EnableLoggerArgumentProcessor.cs @@ -7,6 +7,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.Processors using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Globalization; + using System.Linq; using System.Xml; using Microsoft.VisualStudio.TestPlatform.CommandLine.Processors.Utilities; @@ -143,100 +144,30 @@ public EnableLoggerArgumentExecutor(IRunSettingsProvider runSettingsManager) /// Argument that was provided with the command. public void Initialize(string argument) { - AddLoggerToRunSettings(argument, runSettingsManager); - } - - /// - /// Add logger to runsettings. - /// - /// - /// - public static void AddLoggerToRunSettings(string loggerArgument, IRunSettingsProvider runSettingsManager) - { - if (string.IsNullOrWhiteSpace(loggerArgument)) - { - HandleInvalidArgument(loggerArgument); - } + string exceptionMessage = string.Format(CultureInfo.CurrentUICulture, CommandLineResources.LoggerUriInvalid, argument); - var settings = runSettingsManager.ActiveRunSettings?.SettingsXml; - if (settings == null) + // Throw error in case logger argument null or empty. + if (string.IsNullOrWhiteSpace(argument)) { - runSettingsManager.AddDefaultRunSettings(); - settings = runSettingsManager.ActiveRunSettings?.SettingsXml; + throw new CommandLineException(exceptionMessage); } - var loggerRunSettings = XmlRunSettingsUtilities.GetLoggerRunSettings(settings) ?? new LoggerRunSettings(); - string loggerIdentifier = null; - Dictionary parameters = null; - var parseSucceeded = LoggerUtilities.TryParseLoggerArgument(loggerArgument, out loggerIdentifier, out parameters); + // Get logger argument list. + var loggerArgumentList = ArgumemtProcessorUtilities.GetArgumentList(argument, ArgumemtProcessorUtilities.SemiColonArgumentSeperator, exceptionMessage); - if (parseSucceeded) + // Get logger identifier. + var loggerIdentifier = loggerArgumentList[0]; + if (loggerIdentifier.Contains("=")) { - var logger = default(LoggerSettings); - - try - { - // Logger as uri in command line. - var loggerUri = new Uri(loggerIdentifier); - logger = new LoggerSettings - { - Uri = loggerUri, - IsEnabled = true - }; - } - catch (UriFormatException) - { - // Logger as friendlyName in command line. - logger = new LoggerSettings - { - FriendlyName = loggerIdentifier, - IsEnabled = true - }; - } - - // Converting logger console params to Configuration element - if (parameters != null && parameters.Count > 0) - { - var XmlDocument = new XmlDocument(); - var outerNode = XmlDocument.CreateElement("Configuration"); - foreach (KeyValuePair entry in parameters) - { - var node = XmlDocument.CreateElement(entry.Key); - node.InnerText = entry.Value; - outerNode.AppendChild(node); - } - - logger.Configuration = outerNode; - } - - // Remove existing logger. - var existingLoggerIndex = loggerRunSettings.GetExistingLoggerIndex(logger); - if (existingLoggerIndex >= 0) - { - loggerRunSettings.LoggerSettingsList.RemoveAt(existingLoggerIndex); - } - - loggerRunSettings.LoggerSettingsList.Add(logger); - } - else - { - HandleInvalidArgument(loggerArgument); + throw new CommandLineException(exceptionMessage); } - runSettingsManager.UpdateRunSettingsNodeInnerXml(Constants.LoggerRunSettingsName, loggerRunSettings.ToXml().InnerXml); - } + // Get logger parameters + var loggerParameterArgs = loggerArgumentList.Skip(1); + var loggerParameters = ArgumemtProcessorUtilities.GetArgumentParameters(loggerParameterArgs, ArgumemtProcessorUtilities.EqualNameValueSeperator, exceptionMessage); - /// - /// Throws an exception indicating that the argument is invalid. - /// - /// Argument which is invalid. - private static void HandleInvalidArgument(string argument) - { - throw new CommandLineException( - string.Format( - CultureInfo.CurrentUICulture, - CommandLineResources.LoggerUriInvalid, - argument)); + // Add logger to run settings. + LoggerUtilities.AddLoggerToRunSettings(loggerIdentifier, loggerParameters, runSettingsManager); } /// diff --git a/src/vstest.console/Processors/Utilities/ArgumemtProcessorUtilities.cs b/src/vstest.console/Processors/Utilities/ArgumemtProcessorUtilities.cs new file mode 100644 index 0000000000..7291054c36 --- /dev/null +++ b/src/vstest.console/Processors/Utilities/ArgumemtProcessorUtilities.cs @@ -0,0 +1,62 @@ +// 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.Utilities +{ + using System; + using System.Collections.Generic; + + internal class ArgumemtProcessorUtilities + { + public static readonly char[] SemiColonArgumentSeperator = { ';' }; + public static readonly char[] EqualNameValueSeperator = { '=' }; + + /// + /// Get argument list from raw argument usign argument separator. + /// + /// Raw argument. + /// Argument separator. + /// Exception Message. + /// Argument list. + public static string[] GetArgumentList(string rawArgument, char[] argumentSeparator, string exceptionMessage) + { + var argumentList = rawArgument?.Split(argumentSeparator, StringSplitOptions.RemoveEmptyEntries); + + // Throw error in case of invalid argument. + if (argumentList == null || argumentList.Length <= 0) + { + throw new CommandLineException(exceptionMessage); + } + + return argumentList; + } + + /// + /// Get argument parameters. + /// + /// Parameter args. + /// Parameters dictionary. + public static Dictionary GetArgumentParameters(IEnumerable parameterArgs, char[] nameValueSeparator, string exceptionMessage) + { + var parameters = new Dictionary(StringComparer.OrdinalIgnoreCase); + + // Get parameters from parameterNameValuePairs. + // Throw error in case of invalid name value pairs. + foreach (string parameterArg in parameterArgs) + { + var nameValuePair = parameterArg?.Split(nameValueSeparator, StringSplitOptions.RemoveEmptyEntries); + if (nameValuePair.Length == 2) + { + parameters[nameValuePair[0]] = nameValuePair[1]; + } + else + { + throw new CommandLineException(exceptionMessage); + } + } + + return parameters; + } + } +} diff --git a/src/vstest.console/Processors/Utilities/LoggerUtilities.cs b/src/vstest.console/Processors/Utilities/LoggerUtilities.cs index 5ab4a4e8bc..fd778c32d2 100644 --- a/src/vstest.console/Processors/Utilities/LoggerUtilities.cs +++ b/src/vstest.console/Processors/Utilities/LoggerUtilities.cs @@ -5,59 +5,79 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.Processors.Utilities { using System; + using System.Xml; using System.Collections.Generic; - using System.Collections.ObjectModel; - using ObjectModel; - using ObjectModel.Logging; + using Microsoft.VisualStudio.TestPlatform.Common.Interfaces; + using Microsoft.VisualStudio.TestPlatform.Common.Utilities; + using Microsoft.VisualStudio.TestPlatform.ObjectModel; + using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities; internal class LoggerUtilities { /// - /// Parses the parameters passed as name values pairs along with the logger argument. + /// Add logger to run settings. /// - /// Logger argument - /// Receives logger Uri or friendly name. - /// Receives parse name value pairs. - /// True is successful, false otherwise. - public static bool TryParseLoggerArgument(string argument, out string loggerIdentifier, out Dictionary parameters) + /// Logger Identifier. + /// Logger parameters. + /// Run settings manager. + public static void AddLoggerToRunSettings(string loggerIdentifier, Dictionary loggerParameters, IRunSettingsProvider runSettingsManager) { - loggerIdentifier = null; - parameters = null; - - var parseSucceeded = true; - char[] ArgumentSeperator = new char[] { ';' }; - char[] NameValueSeperator = new char[] { '=' }; + // Creating default run settings if required. + var settings = runSettingsManager.ActiveRunSettings?.SettingsXml; + if (settings == null) + { + runSettingsManager.AddDefaultRunSettings(); + settings = runSettingsManager.ActiveRunSettings?.SettingsXml; + } - var argumentParts = argument.Split(ArgumentSeperator, StringSplitOptions.RemoveEmptyEntries); + var logger = default(LoggerSettings); + var loggerRunSettings = XmlRunSettingsUtilities.GetLoggerRunSettings(settings) ?? new LoggerRunSettings(); - if (argumentParts.Length > 0 && !argumentParts[0].Contains("=")) + try + { + // Logger as uri in command line. + var loggerUri = new Uri(loggerIdentifier); + logger = new LoggerSettings + { + Uri = loggerUri, + IsEnabled = true + }; + } + catch (UriFormatException) { - loggerIdentifier = argumentParts[0]; + // Logger as friendlyName in command line. + logger = new LoggerSettings + { + FriendlyName = loggerIdentifier, + IsEnabled = true + }; + } - if (argumentParts.Length > 1) + // Converting logger console params to Configuration element + if (loggerParameters != null && loggerParameters.Count > 0) + { + var XmlDocument = new XmlDocument(); + var outerNode = XmlDocument.CreateElement("Configuration"); + foreach (KeyValuePair entry in loggerParameters) { - parameters = new Dictionary(StringComparer.OrdinalIgnoreCase); - for (int index = 1; index < argumentParts.Length; ++index) - { - string[] nameValuePair = argumentParts[index].Split(NameValueSeperator, StringSplitOptions.RemoveEmptyEntries); - if (nameValuePair.Length == 2) - { - parameters[nameValuePair[0]] = nameValuePair[1]; - } - else - { - parseSucceeded = false; - break; - } - } + var node = XmlDocument.CreateElement(entry.Key); + node.InnerText = entry.Value; + outerNode.AppendChild(node); } + + logger.Configuration = outerNode; } - else + + // Remove existing logger. + var existingLoggerIndex = loggerRunSettings.GetExistingLoggerIndex(logger); + if (existingLoggerIndex >= 0) { - parseSucceeded = false; + loggerRunSettings.LoggerSettingsList.RemoveAt(existingLoggerIndex); } - return parseSucceeded; + loggerRunSettings.LoggerSettingsList.Add(logger); + + runSettingsManager.UpdateRunSettingsNodeInnerXml(Constants.LoggerRunSettingsName, loggerRunSettings.ToXml().InnerXml); } } } diff --git a/test/Microsoft.TestPlatform.ObjectModel.UnitTests/Hosting/TestRunnerConnectionInfoExtensionsTests.cs b/test/Microsoft.TestPlatform.ObjectModel.UnitTests/Hosting/TestRunnerConnectionInfoExtensionsTests.cs index 333b995bec..a2fa14f682 100644 --- a/test/Microsoft.TestPlatform.ObjectModel.UnitTests/Hosting/TestRunnerConnectionInfoExtensionsTests.cs +++ b/test/Microsoft.TestPlatform.ObjectModel.UnitTests/Hosting/TestRunnerConnectionInfoExtensionsTests.cs @@ -52,7 +52,7 @@ public void ToCommandLineOptionsShouldIncludeParentProcessId() } [TestMethod] - public void ToCommandLineOptionsShouldIncludeDiagnosticsOptionIfEnabled() + public void ToCommandLineOptionsShouldNotIncludeDiagnosticsOptionIfNotEnabled() { var connectionInfo = default(TestRunnerConnectionInfo); @@ -62,13 +62,13 @@ public void ToCommandLineOptionsShouldIncludeDiagnosticsOptionIfEnabled() } [TestMethod] - public void ToCommandLineOptionsShouldNotIncludeDiagnosticsOptionIfNotEnabled() + public void ToCommandLineOptionsShouldIncludeDiagnosticsOptionIfEnabled() { - var connectionInfo = new TestRunnerConnectionInfo { LogFile = "log.txt" }; + var connectionInfo = new TestRunnerConnectionInfo { LogFile = "log.txt", TraceLevel = 3 }; var options = connectionInfo.ToCommandLineOptions(); - StringAssert.EndsWith(options, "--diag log.txt"); + StringAssert.EndsWith(options, "--diag log.txt --tracelevel 3"); } } #pragma warning restore SA1600 diff --git a/test/datacollector.UnitTests/DataCollectorMainTests.cs b/test/datacollector.UnitTests/DataCollectorMainTests.cs index 5933c8d047..c25f3031ab 100644 --- a/test/datacollector.UnitTests/DataCollectorMainTests.cs +++ b/test/datacollector.UnitTests/DataCollectorMainTests.cs @@ -5,34 +5,25 @@ namespace Microsoft.VisualStudio.TestPlatform.Common.DataCollector.UnitTests { using System; using System.Diagnostics; - using System.Globalization; + using CommunicationUtilities.DataCollection.Interfaces; using CoreUtilities.Helpers; - using Microsoft.VisualStudio.TestPlatform.Common.DataCollector.Interfaces; - using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities; - using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.DataCollection; - using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Interfaces; - using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestTools.UnitTesting; - using Moq; using PlatformAbstractions.Interfaces; using TestPlatform.DataCollector; - using CommunicationUtilitiesResources = Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Resources.Resources; - using CoreUtilitiesConstants = Microsoft.VisualStudio.TestPlatform.CoreUtilities.Constants; - [TestClass] public class DataCollectorMainTests { - private readonly string[] args = {"--port", "1025", "--parentprocessid", "100", "--diag", "abc.txt", "--tracelevel", "3" }; + private readonly string[] args = {"--port", "1025", "--parentprocessid", "100", "--diag", "abc.txt", "--tracelevel", "3" }; + private readonly string[] argsWithEmptyDiagArg = { "--port", "1025", "--parentprocessid", "100", "--diag", "", "--tracelevel", "3" }; + private readonly string[] argsWithInvalidTraceLevel = { "--port", "1025", "--parentprocessid", "100", "--diag", "abc.txt", "--tracelevel", "5" }; private static readonly string TimoutErrorMessage = "datacollector process failed to connect to vstest.console process after 90 seconds. This may occur due to machine slowness, please set environment variable VSTEST_CONNECTION_TIMEOUT to increase timeout."; private Mock mockProcessHelper; - private Mock mockMessageSink; - private Mock mockCommunicationManager; private Mock mockEnvironment; private Mock mockDataCollectionRequestHandler; private DataCollectorMain dataCollectorMain; @@ -40,8 +31,6 @@ public class DataCollectorMainTests public DataCollectorMainTests() { this.mockProcessHelper = new Mock(); - this.mockMessageSink = new Mock(); - this.mockCommunicationManager = new Mock(); this.mockEnvironment = new Mock(); this.mockDataCollectionRequestHandler = new Mock(); this.dataCollectorMain = new DataCollectorMain(this.mockProcessHelper.Object, this.mockEnvironment.Object, this.mockDataCollectionRequestHandler.Object); @@ -71,7 +60,39 @@ public void RunShouldTimeoutBasedDefaulValueIfEnvVariableNotSet() } [TestMethod] - public void RunShouldInitializeTraceWithCorrectTraceLevel() + public void RunShouldInitializeTraceWithTraceLevelOffIfDiagArgIsEmpty() + { + // Setting EqtTrace.TraceLevel to a value other than info. +#if NET451 + EqtTrace.TraceLevel = TraceLevel.Verbose; +#else + EqtTrace.TraceLevel = PlatformTraceLevel.Verbose; +#endif + // Action + this.dataCollectorMain.Run(argsWithEmptyDiagArg); // Passing tracelevel as info and diag file path is empty. + + // Verify + Assert.AreEqual(PlatformTraceLevel.Off, EqtTrace.TraceLevel); + } + + [TestMethod] + public void RunShouldInitializeTraceWithVerboseTraceLevelIfInvalidTraceLevelPassed() + { + // Setting EqtTrace.TraceLevel to a value other than info. +#if NET451 + EqtTrace.TraceLevel = TraceLevel.Info; +#else + EqtTrace.TraceLevel = PlatformTraceLevel.Info; +#endif + // Action + this.dataCollectorMain.Run(argsWithInvalidTraceLevel); + + // Verify + Assert.AreEqual(PlatformTraceLevel.Verbose, EqtTrace.TraceLevel); + } + + [TestMethod] + public void RunShouldInitializeTraceWithCorrectVerboseTraceLevel() { // Setting EqtTrace.TraceLevel to a value other than info. #if NET451 @@ -80,14 +101,7 @@ public void RunShouldInitializeTraceWithCorrectTraceLevel() EqtTrace.TraceLevel = PlatformTraceLevel.Verbose; #endif // Action - try - { - this.dataCollectorMain.Run(args); // Passing tracelevel as info from args. - } - catch (Exception) - { - // Ignore exceptions as they are coming because of trying to type cast mock interface into different object. - } + this.dataCollectorMain.Run(args); // Trace level is set as info in args. // Verify Assert.AreEqual(PlatformTraceLevel.Info, EqtTrace.TraceLevel); diff --git a/test/testhost.UnitTests/DefaultEngineInvokerTests.cs b/test/testhost.UnitTests/DefaultEngineInvokerTests.cs index 293f0d3eda..16ed30475f 100644 --- a/test/testhost.UnitTests/DefaultEngineInvokerTests.cs +++ b/test/testhost.UnitTests/DefaultEngineInvokerTests.cs @@ -109,7 +109,30 @@ public void InvokeShouldInitializeTraceWithCorrectTraceLevel() this.engineInvoker.Invoke(argsDictionary); // Verify - Assert.AreEqual(PlatformTraceLevel.Info, EqtTrace.TraceLevel); + Assert.AreEqual(TraceLevel.Info, (TraceLevel)EqtTrace.TraceLevel); + } + + [TestMethod] + public void InvokeShouldInitializeTraceWithVerboseTraceLevelIfInvalidTraceLevelPassed() + { + // Setting EqtTrace.TraceLevel to a value other than info. +#if NET451 + EqtTrace.TraceLevel = TraceLevel.Warning; +#else + EqtTrace.TraceLevel = PlatformTraceLevel.Warning; +#endif + + try + { + argsDictionary["--tracelevel"] = "5"; // int value which is not defined in TraceLevel. + this.engineInvoker.Invoke(argsDictionary); + } + finally{ + argsDictionary["--tracelevel"] = "3"; // Setting to default value of 3. + } + + // Verify + Assert.AreEqual(TraceLevel.Verbose, (TraceLevel)EqtTrace.TraceLevel); } } } diff --git a/test/vstest.console.UnitTests/Processors/EnableDiagArgumentProcessorTests.cs b/test/vstest.console.UnitTests/Processors/EnableDiagArgumentProcessorTests.cs index 09a5d817ad..195145fdda 100644 --- a/test/vstest.console.UnitTests/Processors/EnableDiagArgumentProcessorTests.cs +++ b/test/vstest.console.UnitTests/Processors/EnableDiagArgumentProcessorTests.cs @@ -138,7 +138,7 @@ public void EnableDiagArgumentProcessorExecutorShouldInitializeTraceWithCorrectT this.diagProcessor.Executor.Value.Initialize(argument); - Assert.AreEqual(PlatformTraceLevel.Info, EqtTrace.TraceLevel); + Assert.AreEqual(TraceLevel.Info, (TraceLevel)EqtTrace.TraceLevel); Assert.IsTrue(EqtTrace.LogFile.Contains("abc.txt")); } diff --git a/test/vstest.console.UnitTests/Processors/Utilities/ArgumentProcessorUtilitiesTests.cs b/test/vstest.console.UnitTests/Processors/Utilities/ArgumentProcessorUtilitiesTests.cs new file mode 100644 index 0000000000..db5f0d9335 --- /dev/null +++ b/test/vstest.console.UnitTests/Processors/Utilities/ArgumentProcessorUtilitiesTests.cs @@ -0,0 +1,40 @@ +// 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.UnitTests.Processors.Utilities +{ + using Microsoft.VisualStudio.TestPlatform.CommandLine.Processors.Utilities; + using System; + using System.Linq; + using TestTools.UnitTesting; + + [TestClass] + public class ArgumentProcessorUtilitiesTests + { + [TestMethod] + [DataRow("")] + [DataRow(" ")] + [DataRow(";;;;")] + public void GetArgumentListShouldThrowErrorOnInvalidArgument(string argument) + { + try + { + ArgumemtProcessorUtilities.GetArgumentList(argument, ArgumemtProcessorUtilities.SemiColonArgumentSeperator, "exception in argument."); + } + catch (Exception e) + { + Assert.IsTrue(e.GetType().Equals(typeof(CommandLineException))); + Assert.IsTrue(e.Message.Contains("exception in argument.")); + } + } + + [TestMethod] + [DataRow("abc.txt;tracelevel=info;newkey=newvalue")] + [DataRow(";;;abc.txt;;;tracelevel=info;;;newkey=newvalue;;;;")] + public void GetArgumentListShouldReturnCorrectArgumentList(string argument) + { + var argumentList = ArgumemtProcessorUtilities.GetArgumentList(argument, ArgumemtProcessorUtilities.SemiColonArgumentSeperator, "exception in argument."); + argumentList.SequenceEqual(new string[] { "abc.txt", "tracelevel=info", "newkey=newvalue" }); + } + } +} \ No newline at end of file From 090621eba34647d4f80413552d97ec5c34bd09d6 Mon Sep 17 00:00:00 2001 From: abhishkk Date: Tue, 10 Jul 2018 15:49:49 +0530 Subject: [PATCH 07/10] UT fix --- test/datacollector.UnitTests/DataCollectorMainTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/datacollector.UnitTests/DataCollectorMainTests.cs b/test/datacollector.UnitTests/DataCollectorMainTests.cs index c25f3031ab..9a6a0f5661 100644 --- a/test/datacollector.UnitTests/DataCollectorMainTests.cs +++ b/test/datacollector.UnitTests/DataCollectorMainTests.cs @@ -72,7 +72,7 @@ public void RunShouldInitializeTraceWithTraceLevelOffIfDiagArgIsEmpty() this.dataCollectorMain.Run(argsWithEmptyDiagArg); // Passing tracelevel as info and diag file path is empty. // Verify - Assert.AreEqual(PlatformTraceLevel.Off, EqtTrace.TraceLevel); + Assert.AreEqual(TraceLevel.Off, (TraceLevel)EqtTrace.TraceLevel); } [TestMethod] @@ -88,7 +88,7 @@ public void RunShouldInitializeTraceWithVerboseTraceLevelIfInvalidTraceLevelPass this.dataCollectorMain.Run(argsWithInvalidTraceLevel); // Verify - Assert.AreEqual(PlatformTraceLevel.Verbose, EqtTrace.TraceLevel); + Assert.AreEqual(TraceLevel.Verbose, (TraceLevel)EqtTrace.TraceLevel); } [TestMethod] @@ -104,7 +104,7 @@ public void RunShouldInitializeTraceWithCorrectVerboseTraceLevel() this.dataCollectorMain.Run(args); // Trace level is set as info in args. // Verify - Assert.AreEqual(PlatformTraceLevel.Info, EqtTrace.TraceLevel); + Assert.AreEqual(TraceLevel.Info, (TraceLevel)EqtTrace.TraceLevel); } [TestMethod] From b5939f668b2e0e525210bf0eb5fec101f7b8a7bd Mon Sep 17 00:00:00 2001 From: abhishkk Date: Tue, 31 Jul 2018 16:19:24 +0530 Subject: [PATCH 08/10] PR comments fix --- src/datacollector/DataCollectorMain.cs | 1 + .../EnableBlameArgumentProcessor.cs | 178 ++++++++++++------ .../Processors/EnableDiagArgumentProcessor.cs | 11 +- .../EnableLoggerArgumentProcessor.cs | 4 +- ...ities.cs => ArgumentProcessorUtilities.cs} | 19 +- .../Resources/Resources.Designer.cs | 55 ++++-- src/vstest.console/Resources/Resources.resx | 13 +- .../Resources/xlf/Resources.cs.xlf | 25 ++- .../Resources/xlf/Resources.de.xlf | 25 ++- .../Resources/xlf/Resources.es.xlf | 25 ++- .../Resources/xlf/Resources.fr.xlf | 25 ++- .../Resources/xlf/Resources.it.xlf | 25 ++- .../Resources/xlf/Resources.ja.xlf | 25 ++- .../Resources/xlf/Resources.ko.xlf | 25 ++- .../Resources/xlf/Resources.pl.xlf | 25 ++- .../Resources/xlf/Resources.pt-BR.xlf | 25 ++- .../Resources/xlf/Resources.ru.xlf | 25 ++- .../Resources/xlf/Resources.tr.xlf | 25 ++- .../Resources/xlf/Resources.xlf | 25 ++- .../Resources/xlf/Resources.zh-Hans.xlf | 25 ++- .../Resources/xlf/Resources.zh-Hant.xlf | 25 ++- .../EnableBlameArgumentProcessorTests.cs | 2 +- .../EnableDiagArgumentProcessorTests.cs | 42 +++-- .../EnableLoggersArgumentProcessorTests.cs | 36 ++-- .../ArgumentProcessorUtilitiesTests.cs | 31 ++- 25 files changed, 553 insertions(+), 189 deletions(-) rename src/vstest.console/Processors/Utilities/{ArgumemtProcessorUtilities.cs => ArgumentProcessorUtilities.cs} (79%) diff --git a/src/datacollector/DataCollectorMain.cs b/src/datacollector/DataCollectorMain.cs index 7201c0d761..cadc0350c0 100644 --- a/src/datacollector/DataCollectorMain.cs +++ b/src/datacollector/DataCollectorMain.cs @@ -77,6 +77,7 @@ public void Run(string[] args) (PlatformTraceLevel)traceLevelInt : PlatformTraceLevel.Verbose; + EqtTrace.Warning("DataCollectorMain.Run: Invalid trace level: {0}, defaulting to vebose tracelevel.", traceLevelInt); EqtTrace.InitializeTrace(logFile, traceLevel); } else diff --git a/src/vstest.console/Processors/EnableBlameArgumentProcessor.cs b/src/vstest.console/Processors/EnableBlameArgumentProcessor.cs index 98dd39a9bb..e98557c82c 100644 --- a/src/vstest.console/Processors/EnableBlameArgumentProcessor.cs +++ b/src/vstest.console/Processors/EnableBlameArgumentProcessor.cs @@ -6,6 +6,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.Processors using System; using System.Collections.Generic; using System.Globalization; + using System.Linq; using System.Xml; using Microsoft.VisualStudio.TestPlatform.CommandLine.Processors.Utilities; @@ -17,7 +18,6 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.Processors using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions; using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; using Microsoft.VisualStudio.TestPlatform.Utilities; - using Microsoft.VisualStudio.TestPlatform.CommandLine.Processors.Utilities; using CommandLineResources = Microsoft.VisualStudio.TestPlatform.CommandLine.Resources.Resources; @@ -136,83 +136,86 @@ internal EnableBlameArgumentExecutor(IRunSettingsProvider runSettingsManager, IE /// Argument that was provided with the command. public void Initialize(string argument) { - bool isDumpEnabled = false; - - var parseSucceeded = LoggerUtilities.TryParseLoggerArgument(argument, out string loggerIdentifier, out Dictionary parameters); + var enableDump = false; + var exceptionMessage = string.Format(CultureInfo.CurrentUICulture, CommandLineResources.InvalidBlameArgument, argument); + Dictionary collectDumpParameters = null; - if (!string.IsNullOrWhiteSpace(argument) && !parseSucceeded) + if (!string.IsNullOrWhiteSpace(argument)) { - throw new CommandLineException(string.Format(CultureInfo.CurrentUICulture, CommandLineResources.BlameInvalidFormat, argument)); - } + // Get blame argument list. + var blameArgumentList = ArgumentProcessorUtilities.GetArgumentList(argument, ArgumentProcessorUtilities.SemiColonArgumentSeparator, exceptionMessage); - if (loggerIdentifier != null && loggerIdentifier.Equals(Constants.BlameCollectDumpKey, StringComparison.OrdinalIgnoreCase)) - { - if (this.environment.OperatingSystem == PlatformOperatingSystem.Windows && - this.environment.Architecture != PlatformArchitecture.ARM64 && - this.environment.Architecture != PlatformArchitecture.ARM) - { - isDumpEnabled = true; - } - else - { - Output.Warning(false, CommandLineResources.BlameCollectDumpNotSupportedForPlatform); - } - } - else - { - Output.Warning(false, string.Format(CultureInfo.CurrentUICulture, CommandLineResources.BlameIncorrectOption, loggerIdentifier)); + // Get collect dump key. + var collectDumpKey = blameArgumentList[0]; + bool isCollectDumpKeyValid = ValidateCollectDumpKey(collectDumpKey); + + // Check if dump should be enabled or not. + enableDump = isCollectDumpKeyValid && IsDumpCollectionSupported(); + + // Get collect dump parameters. + var collectDumpParameterArgs = blameArgumentList.Skip(1); + collectDumpParameters = ArgumentProcessorUtilities.GetArgumentParameters(collectDumpParameterArgs, ArgumentProcessorUtilities.EqualNameValueSeparator, exceptionMessage); } + // Initialize blame. + InitializeBlame(enableDump, collectDumpParameters); + } + + /// + /// Executes the argument processor. + /// + /// The . + public ArgumentProcessorResult Execute() + { + // Nothing to do since we updated the logger and data collector list in initialize + return ArgumentProcessorResult.Success; + } + + /// + /// Initialize blame. + /// + /// Enable dump. + /// Blame parameters. + private void InitializeBlame(bool enableDump, Dictionary collectDumpParameters) + { // Add Blame Logger LoggerUtilities.AddLoggerToRunSettings(BlameFriendlyName, null, this.runSettingsManager); // Add Blame Data Collector CollectArgumentExecutor.AddDataCollectorToRunSettings(BlameFriendlyName, this.runSettingsManager); - // Get results directory from RunSettingsManager - var runSettings = this.runSettingsManager.ActiveRunSettings; - string resultsDirectory = null; - if (runSettings != null) - { - try - { - RunConfiguration runConfiguration = XmlRunSettingsUtilities.GetRunConfigurationNode(runSettings.SettingsXml); - resultsDirectory = RunSettingsUtilities.GetTestResultsDirectory(runConfiguration); - } - catch (SettingsException se) - { - if (EqtTrace.IsErrorEnabled) - { - EqtTrace.Error("EnableBlameArgumentProcessor: Unable to get the test results directory: Error {0}", se); - } - } - } - // Add configuration element - var settings = runSettings?.SettingsXml; - if (settings == null) + // Add default run settings if required. + if (this.runSettingsManager.ActiveRunSettings?.SettingsXml == null) { - runSettingsManager.AddDefaultRunSettings(); - settings = runSettings?.SettingsXml; + this.runSettingsManager.AddDefaultRunSettings(); ; } + var settings = this.runSettingsManager.ActiveRunSettings?.SettingsXml; + + // Get results directory from RunSettingsManager + var resultsDirectory = GetResultsDirectory(settings); + // Get data collection run settings. Create if not present. var dataCollectionRunSettings = XmlRunSettingsUtilities.GetDataCollectionRunSettings(settings); if (dataCollectionRunSettings == null) { dataCollectionRunSettings = new DataCollectionRunSettings(); } + // Create blame configuration element. var XmlDocument = new XmlDocument(); var outernode = XmlDocument.CreateElement("Configuration"); var node = XmlDocument.CreateElement("ResultsDirectory"); outernode.AppendChild(node); node.InnerText = resultsDirectory; - if (isDumpEnabled) + // Add collect dump node in configuration element. + if (enableDump) { - AddCollectDumpNode(parameters, XmlDocument, outernode); + AddCollectDumpNode(collectDumpParameters, XmlDocument, outernode); } + // Add blame configuration element to blame collector. foreach (var item in dataCollectionRunSettings.DataCollectorSettingsList) { if (item.FriendlyName.Equals(BlameFriendlyName)) @@ -221,9 +224,78 @@ public void Initialize(string argument) } } + // Update run settings. runSettingsManager.UpdateRunSettingsNodeInnerXml(Constants.DataCollectionRunSettingsName, dataCollectionRunSettings.ToXml().InnerXml); } + /// + /// Get results directory. + /// + /// Settings xml. + /// Results directory. + private string GetResultsDirectory(string settings) + { + string resultsDirectory = null; + if (settings != null) + { + try + { + RunConfiguration runConfiguration = XmlRunSettingsUtilities.GetRunConfigurationNode(settings); + resultsDirectory = RunSettingsUtilities.GetTestResultsDirectory(runConfiguration); + } + catch (SettingsException se) + { + if (EqtTrace.IsErrorEnabled) + { + EqtTrace.Error("EnableBlameArgumentProcessor: Unable to get the test results directory: Error {0}", se); + } + } + } + + return resultsDirectory; + } + + /// + /// Checks if dump collection is supported. + /// + /// Dump collection supported flag. + private bool IsDumpCollectionSupported() + { + var dumpCollectionSupported = this.environment.OperatingSystem == PlatformOperatingSystem.Windows && + this.environment.Architecture != PlatformArchitecture.ARM64 && + this.environment.Architecture != PlatformArchitecture.ARM; + + if (!dumpCollectionSupported) + { + Output.Warning(false, CommandLineResources.BlameCollectDumpNotSupportedForPlatform); + } + + return dumpCollectionSupported; + } + + /// + /// Check if collect dump key is valid. + /// + /// Collect dump key. + /// Flag for collect dump key valid or not. + private bool ValidateCollectDumpKey(string collectDumpKey) + { + var isCollectDumpKeyValid = collectDumpKey != null && collectDumpKey.Equals(Constants.BlameCollectDumpKey, StringComparison.OrdinalIgnoreCase); + + if (!isCollectDumpKeyValid) + { + Output.Warning(false, string.Format(CultureInfo.CurrentUICulture, CommandLineResources.BlameIncorrectOption, collectDumpKey)); + } + + return isCollectDumpKeyValid; + } + + /// + /// Adds collect dump node in outer node. + /// + /// Parameters. + /// Xml document. + /// Outer node. private void AddCollectDumpNode(Dictionary parameters, XmlDocument XmlDocument, XmlElement outernode) { var dumpNode = XmlDocument.CreateElement(Constants.BlameCollectDumpKey); @@ -239,16 +311,6 @@ private void AddCollectDumpNode(Dictionary parameters, XmlDocume outernode.AppendChild(dumpNode); } - /// - /// Executes the argument processor. - /// - /// The . - public ArgumentProcessorResult Execute() - { - // Nothing to do since we updated the logger and data collector list in initialize - return ArgumentProcessorResult.Success; - } - #endregion } } diff --git a/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs b/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs index 4b4d14d64e..e4a47f270c 100644 --- a/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs +++ b/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs @@ -5,6 +5,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.Processors { using System; using System.Collections.Generic; + using System.Globalization; using System.IO; using System.Linq; using Microsoft.VisualStudio.TestPlatform.CommandLine.Processors.Utilities; @@ -130,14 +131,16 @@ public EnableDiagArgumentExecutor(IFileHelper fileHelper) /// Argument that was provided with the command. public void Initialize(string argument) { + string exceptionMessage = string.Format(CultureInfo.CurrentUICulture, CommandLineResources.InvalidDiagArgument, argument); + // Throw error if argument is null or empty. if (string.IsNullOrWhiteSpace(argument)) { - throw new CommandLineException(CommandLineResources.EnableDiagUsage); + throw new CommandLineException(exceptionMessage); } // Get diag argument list. - var diagArgumentList = ArgumemtProcessorUtilities.GetArgumentList(argument, ArgumemtProcessorUtilities.SemiColonArgumentSeperator, CommandLineResources.EnableDiagUsage); + var diagArgumentList = ArgumentProcessorUtilities.GetArgumentList(argument, ArgumentProcessorUtilities.SemiColonArgumentSeparator, exceptionMessage); // Get diag file path. // Note: Even though semi colon is valid file path, we are not respecting the file name having semi-colon [As we are separating arguments based on semi colon]. @@ -146,7 +149,7 @@ public void Initialize(string argument) // Get diag parameters. var diagParameterArgs = diagArgumentList.Skip(1); - var diagParameters = ArgumemtProcessorUtilities.GetArgumentParameters(diagParameterArgs, ArgumemtProcessorUtilities.EqualNameValueSeperator, CommandLineResources.EnableDiagUsage); + var diagParameters = ArgumentProcessorUtilities.GetArgumentParameters(diagParameterArgs, ArgumentProcessorUtilities.EqualNameValueSeparator, exceptionMessage); // Initialize diag logging. InitializeDiagLogging(diagFilePath, diagParameters); @@ -221,7 +224,7 @@ private string GetDiagFilePath(string diagFilePathArgument) var fileExtension = Path.GetExtension(diagFilePathArgument); if (string.IsNullOrWhiteSpace(fileExtension)) { - throw new CommandLineException(CommandLineResources.EnableDiagUsage); + throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, CommandLineResources.InvalidDiagFilePath, diagFilePathArgument)); } // Create base directory for diag file path (if doesn't exist) diff --git a/src/vstest.console/Processors/EnableLoggerArgumentProcessor.cs b/src/vstest.console/Processors/EnableLoggerArgumentProcessor.cs index 6ff8ce4c15..2b56f96a1e 100644 --- a/src/vstest.console/Processors/EnableLoggerArgumentProcessor.cs +++ b/src/vstest.console/Processors/EnableLoggerArgumentProcessor.cs @@ -153,7 +153,7 @@ public void Initialize(string argument) } // Get logger argument list. - var loggerArgumentList = ArgumemtProcessorUtilities.GetArgumentList(argument, ArgumemtProcessorUtilities.SemiColonArgumentSeperator, exceptionMessage); + var loggerArgumentList = ArgumentProcessorUtilities.GetArgumentList(argument, ArgumentProcessorUtilities.SemiColonArgumentSeparator, exceptionMessage); // Get logger identifier. var loggerIdentifier = loggerArgumentList[0]; @@ -164,7 +164,7 @@ public void Initialize(string argument) // Get logger parameters var loggerParameterArgs = loggerArgumentList.Skip(1); - var loggerParameters = ArgumemtProcessorUtilities.GetArgumentParameters(loggerParameterArgs, ArgumemtProcessorUtilities.EqualNameValueSeperator, exceptionMessage); + var loggerParameters = ArgumentProcessorUtilities.GetArgumentParameters(loggerParameterArgs, ArgumentProcessorUtilities.EqualNameValueSeparator, exceptionMessage); // Add logger to run settings. LoggerUtilities.AddLoggerToRunSettings(loggerIdentifier, loggerParameters, runSettingsManager); diff --git a/src/vstest.console/Processors/Utilities/ArgumemtProcessorUtilities.cs b/src/vstest.console/Processors/Utilities/ArgumentProcessorUtilities.cs similarity index 79% rename from src/vstest.console/Processors/Utilities/ArgumemtProcessorUtilities.cs rename to src/vstest.console/Processors/Utilities/ArgumentProcessorUtilities.cs index 7291054c36..83b7c0328b 100644 --- a/src/vstest.console/Processors/Utilities/ArgumemtProcessorUtilities.cs +++ b/src/vstest.console/Processors/Utilities/ArgumentProcessorUtilities.cs @@ -6,11 +6,13 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.Processors.Utilities { using System; using System.Collections.Generic; + using System.Globalization; + using CommandLineResources = Microsoft.VisualStudio.TestPlatform.CommandLine.Resources.Resources; - internal class ArgumemtProcessorUtilities + internal class ArgumentProcessorUtilities { - public static readonly char[] SemiColonArgumentSeperator = { ';' }; - public static readonly char[] EqualNameValueSeperator = { '=' }; + public static readonly char[] SemiColonArgumentSeparator = { ';' }; + public static readonly char[] EqualNameValueSeparator = { '=' }; /// /// Get argument list from raw argument usign argument separator. @@ -36,6 +38,8 @@ public static string[] GetArgumentList(string rawArgument, char[] argumentSepara /// Get argument parameters. /// /// Parameter args. + /// Name value separator. + /// Exception message. /// Parameters dictionary. public static Dictionary GetArgumentParameters(IEnumerable parameterArgs, char[] nameValueSeparator, string exceptionMessage) { @@ -46,14 +50,13 @@ public static Dictionary GetArgumentParameters(IEnumerable - /// The blame option specified '{0}' is not a valid format. Please correct it and retry.. - /// - public static string BlameInvalidFormat - { - get - { - return ResourceManager.GetString("BlameInvalidFormat", resourceCulture); - } - } - /// /// Looks up a localized string similar to --BuildBasePath|/BuildBasePath:<BuildBasePath> /// The directory containing the temporary outputs.. @@ -771,6 +760,17 @@ public static string InvalidBatchSize } } + /// + /// Looks up a localized string similar to Blame argument '{0}' is not valid.. + /// + internal static string InvalidBlameArgument + { + get + { + return ResourceManager.GetString("InvalidBlameArgument", resourceCulture); + } + } + /// /// Looks up a localized string similar to The given configuration is invalid.. /// @@ -782,6 +782,28 @@ public static string InvalidConfiguration } } + /// + /// Looks up a localized string similar to Diag argument '{0}' is not valid.. + /// + internal static string InvalidDiagArgument + { + get + { + return ResourceManager.GetString("InvalidDiagArgument", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Diag file path '{0}' is not valid.. + /// + internal static string InvalidDiagFilePath + { + get + { + return ResourceManager.GetString("InvalidDiagFilePath", resourceCulture); + } + } + /// /// Looks up a localized string similar to Argument {0} is not expected in the 'EnableCodeCoverage' command. Specify the command without the argument (Example: vstest.console.exe myTests.dll /EnableCodeCoverage) and try again.. /// @@ -815,6 +837,17 @@ public static string InvalidInIsolationCommand } } + /// + /// Looks up a localized string similar to Logger argument '{0}' is not valid.. + /// + internal static string InvalidLoggerArgument + { + get + { + return ResourceManager.GetString("InvalidLoggerArgument", resourceCulture); + } + } + /// /// Looks up a localized string similar to Argument {0} is not expected in the 'Parallel' command. Specify the command without the argument (Example: vstest.console.exe myTests.dll /Parallel) and try again.. /// diff --git a/src/vstest.console/Resources/Resources.resx b/src/vstest.console/Resources/Resources.resx index 58ef14a000..056cbc3aed 100644 --- a/src/vstest.console/Resources/Resources.resx +++ b/src/vstest.console/Resources/Resources.resx @@ -703,7 +703,16 @@ The blame parameter specified with blame, {0} is invalid. Ignoring this parameter. - - The blame option specified '{0}' is not a valid format. Please correct it and retry. + + Diag file path '{0}' is not valid. + + + Blame argument '{0}' is not valid. + + + Diag argument '{0}' is not valid. + + + Logger argument '{0}' is not valid. \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.cs.xlf b/src/vstest.console/Resources/xlf/Resources.cs.xlf index f32ae71581..e2ad288d94 100644 --- a/src/vstest.console/Resources/xlf/Resources.cs.xlf +++ b/src/vstest.console/Resources/xlf/Resources.cs.xlf @@ -1593,16 +1593,31 @@ Možnost CollectDump pro Blame není pro tuto platformu podporovaná. - - The blame option specified '{0}' is not a valid format. Please correct it and retry. - The blame option specified '{0}' is not valid. This will be ignored. - - The blame parameter specified with blame, {0} is invalid. Ignoring this parameter. The option specified with blame, {0} is invalid. This will be ignored. + + Diag file path '{0}' is not valid. + Diag file path '{0}' is not valid. + + + + Blame argument '{0}' is not valid. + Blame argument '{0}' in invalid. + + + + Diag argument '{0}' is not valid. + Diag argument '{0}' is invalid. + + + + Logger argument '{0}' is not valid. + Logger argument '{0}' is invalid. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.de.xlf b/src/vstest.console/Resources/xlf/Resources.de.xlf index 98c2c4832d..c9e4788bb3 100644 --- a/src/vstest.console/Resources/xlf/Resources.de.xlf +++ b/src/vstest.console/Resources/xlf/Resources.de.xlf @@ -1593,16 +1593,31 @@ Die CollectDump-Option für Blame wird für diese Plattform nicht unterstützt. - - The blame option specified '{0}' is not a valid format. Please correct it and retry. - The blame option specified '{0}' is not valid. This will be ignored. - - The blame parameter specified with blame, {0} is invalid. Ignoring this parameter. The option specified with blame, {0} is invalid. This will be ignored. + + Diag file path '{0}' is not valid. + Diag file path '{0}' is not valid. + + + + Blame argument '{0}' is not valid. + Blame argument '{0}' in invalid. + + + + Diag argument '{0}' is not valid. + Diag argument '{0}' is invalid. + + + + Logger argument '{0}' is not valid. + Logger argument '{0}' is invalid. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.es.xlf b/src/vstest.console/Resources/xlf/Resources.es.xlf index a87f65bdff..ae9a42fe2e 100644 --- a/src/vstest.console/Resources/xlf/Resources.es.xlf +++ b/src/vstest.console/Resources/xlf/Resources.es.xlf @@ -1598,16 +1598,31 @@ No se admite la opción CollectDump para Blame en esta plataforma. - - The blame option specified '{0}' is not a valid format. Please correct it and retry. - The blame option specified '{0}' is not valid. This will be ignored. - - The blame parameter specified with blame, {0} is invalid. Ignoring this parameter. The option specified with blame, {0} is invalid. This will be ignored. + + Diag file path '{0}' is not valid. + Diag file path '{0}' is not valid. + + + + Blame argument '{0}' is not valid. + Blame argument '{0}' in invalid. + + + + Diag argument '{0}' is not valid. + Diag argument '{0}' is invalid. + + + + Logger argument '{0}' is not valid. + Logger argument '{0}' is invalid. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.fr.xlf b/src/vstest.console/Resources/xlf/Resources.fr.xlf index 9bc11c9fd9..bbfbfe9a51 100644 --- a/src/vstest.console/Resources/xlf/Resources.fr.xlf +++ b/src/vstest.console/Resources/xlf/Resources.fr.xlf @@ -1593,16 +1593,31 @@ L'option CollectDump pour Blame n'est pas prise en charge pour cette plateforme. - - The blame option specified '{0}' is not a valid format. Please correct it and retry. - The blame option specified '{0}' is not valid. This will be ignored. - - The blame parameter specified with blame, {0} is invalid. Ignoring this parameter. The option specified with blame, {0} is invalid. This will be ignored. + + Diag file path '{0}' is not valid. + Diag file path '{0}' is not valid. + + + + Blame argument '{0}' is not valid. + Blame argument '{0}' in invalid. + + + + Diag argument '{0}' is not valid. + Diag argument '{0}' is invalid. + + + + Logger argument '{0}' is not valid. + Logger argument '{0}' is invalid. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.it.xlf b/src/vstest.console/Resources/xlf/Resources.it.xlf index d9bffd96ce..8bd8b05cc4 100644 --- a/src/vstest.console/Resources/xlf/Resources.it.xlf +++ b/src/vstest.console/Resources/xlf/Resources.it.xlf @@ -1593,16 +1593,31 @@ L'opzione CollectDump per Blame non è supportata per questa piattaforma. - - The blame option specified '{0}' is not a valid format. Please correct it and retry. - The blame option specified '{0}' is not valid. This will be ignored. - - The blame parameter specified with blame, {0} is invalid. Ignoring this parameter. The option specified with blame, {0} is invalid. This will be ignored. + + Diag file path '{0}' is not valid. + Diag file path '{0}' is not valid. + + + + Blame argument '{0}' is not valid. + Blame argument '{0}' in invalid. + + + + Diag argument '{0}' is not valid. + Diag argument '{0}' is invalid. + + + + Logger argument '{0}' is not valid. + Logger argument '{0}' is invalid. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.ja.xlf b/src/vstest.console/Resources/xlf/Resources.ja.xlf index 47a27cf8cc..202cb5a5db 100644 --- a/src/vstest.console/Resources/xlf/Resources.ja.xlf +++ b/src/vstest.console/Resources/xlf/Resources.ja.xlf @@ -1593,16 +1593,31 @@ このプラットフォームでは、Blame の CollectDump オプションはサポートされていません。 - - The blame option specified '{0}' is not a valid format. Please correct it and retry. - The blame option specified '{0}' is not valid. This will be ignored. - - The blame parameter specified with blame, {0} is invalid. Ignoring this parameter. The option specified with blame, {0} is invalid. This will be ignored. + + Diag file path '{0}' is not valid. + Diag file path '{0}' is not valid. + + + + Blame argument '{0}' is not valid. + Blame argument '{0}' in invalid. + + + + Diag argument '{0}' is not valid. + Diag argument '{0}' is invalid. + + + + Logger argument '{0}' is not valid. + Logger argument '{0}' is invalid. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.ko.xlf b/src/vstest.console/Resources/xlf/Resources.ko.xlf index ababfe6f0c..0635cb99d6 100644 --- a/src/vstest.console/Resources/xlf/Resources.ko.xlf +++ b/src/vstest.console/Resources/xlf/Resources.ko.xlf @@ -1593,16 +1593,31 @@ Blame에 대한 CollectDump 옵션이 이 플랫폼에서 지원되지 않습니다. - - The blame option specified '{0}' is not a valid format. Please correct it and retry. - The blame option specified '{0}' is not valid. This will be ignored. - - The blame parameter specified with blame, {0} is invalid. Ignoring this parameter. The option specified with blame, {0} is invalid. This will be ignored. + + Diag file path '{0}' is not valid. + Diag file path '{0}' is not valid. + + + + Blame argument '{0}' is not valid. + Blame argument '{0}' in invalid. + + + + Diag argument '{0}' is not valid. + Diag argument '{0}' is invalid. + + + + Logger argument '{0}' is not valid. + Logger argument '{0}' is invalid. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.pl.xlf b/src/vstest.console/Resources/xlf/Resources.pl.xlf index 961a516eb6..c7ed345188 100644 --- a/src/vstest.console/Resources/xlf/Resources.pl.xlf +++ b/src/vstest.console/Resources/xlf/Resources.pl.xlf @@ -1591,16 +1591,31 @@ Opcja CollectDump dla narzędzia Blame nie jest obsługiwana na tej platformie. - - The blame option specified '{0}' is not a valid format. Please correct it and retry. - The blame option specified '{0}' is not valid. This will be ignored. - - The blame parameter specified with blame, {0} is invalid. Ignoring this parameter. The option specified with blame, {0} is invalid. This will be ignored. + + Diag file path '{0}' is not valid. + Diag file path '{0}' is not valid. + + + + Blame argument '{0}' is not valid. + Blame argument '{0}' in invalid. + + + + Diag argument '{0}' is not valid. + Diag argument '{0}' is invalid. + + + + Logger argument '{0}' is not valid. + Logger argument '{0}' is invalid. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.pt-BR.xlf b/src/vstest.console/Resources/xlf/Resources.pt-BR.xlf index a429cb3854..88861206fd 100644 --- a/src/vstest.console/Resources/xlf/Resources.pt-BR.xlf +++ b/src/vstest.console/Resources/xlf/Resources.pt-BR.xlf @@ -1591,16 +1591,31 @@ A opção CollectDump para Blame não é compatível com esta plataforma. - - The blame option specified '{0}' is not a valid format. Please correct it and retry. - The blame option specified '{0}' is not valid. This will be ignored. - - The blame parameter specified with blame, {0} is invalid. Ignoring this parameter. The option specified with blame, {0} is invalid. This will be ignored. + + Diag file path '{0}' is not valid. + Diag file path '{0}' is not valid. + + + + Blame argument '{0}' is not valid. + Blame argument '{0}' in invalid. + + + + Diag argument '{0}' is not valid. + Diag argument '{0}' is invalid. + + + + Logger argument '{0}' is not valid. + Logger argument '{0}' is invalid. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.ru.xlf b/src/vstest.console/Resources/xlf/Resources.ru.xlf index 36b0d75c31..05a7e43fd0 100644 --- a/src/vstest.console/Resources/xlf/Resources.ru.xlf +++ b/src/vstest.console/Resources/xlf/Resources.ru.xlf @@ -1593,16 +1593,31 @@ Параметр CollectDump для Blame не поддерживается на этой платформе. - - The blame option specified '{0}' is not a valid format. Please correct it and retry. - The blame option specified '{0}' is not valid. This will be ignored. - - The blame parameter specified with blame, {0} is invalid. Ignoring this parameter. The option specified with blame, {0} is invalid. This will be ignored. + + Diag file path '{0}' is not valid. + Diag file path '{0}' is not valid. + + + + Blame argument '{0}' is not valid. + Blame argument '{0}' in invalid. + + + + Diag argument '{0}' is not valid. + Diag argument '{0}' is invalid. + + + + Logger argument '{0}' is not valid. + Logger argument '{0}' is invalid. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.tr.xlf b/src/vstest.console/Resources/xlf/Resources.tr.xlf index 370ca03fa9..e879af328d 100644 --- a/src/vstest.console/Resources/xlf/Resources.tr.xlf +++ b/src/vstest.console/Resources/xlf/Resources.tr.xlf @@ -1593,16 +1593,31 @@ Blame için CollectDump seçeneği bu platformda desteklenmez. - - The blame option specified '{0}' is not a valid format. Please correct it and retry. - The blame option specified '{0}' is not valid. This will be ignored. - - The blame parameter specified with blame, {0} is invalid. Ignoring this parameter. The option specified with blame, {0} is invalid. This will be ignored. + + Diag file path '{0}' is not valid. + Diag file path '{0}' is not valid. + + + + Blame argument '{0}' is not valid. + Blame argument '{0}' in invalid. + + + + Diag argument '{0}' is not valid. + Diag argument '{0}' is invalid. + + + + Logger argument '{0}' is not valid. + Logger argument '{0}' is invalid. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.xlf b/src/vstest.console/Resources/xlf/Resources.xlf index 16067f72b9..9fa5b7c1c9 100644 --- a/src/vstest.console/Resources/xlf/Resources.xlf +++ b/src/vstest.console/Resources/xlf/Resources.xlf @@ -789,16 +789,31 @@ CollectDump option for Blame is not supported for this platform. - - The blame option specified '{0}' is not a valid format. Please correct it and retry. - The blame option specified '{0}' is not valid. This will be ignored. - - The blame parameter specified with blame, {0} is invalid. Ignoring this parameter. The option specified with blame, {0} is invalid. This will be ignored. + + Diag file path '{0}' is not valid. + Diag file path '{0}' is not valid. + + + + Blame argument '{0}' is not valid. + Blame argument '{0}' in invalid. + + + + Diag argument '{0}' is not valid. + Diag argument '{0}' is invalid. + + + + Logger argument '{0}' is not valid. + Logger argument '{0}' is invalid. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.zh-Hans.xlf b/src/vstest.console/Resources/xlf/Resources.zh-Hans.xlf index 7043cbf215..1dd12f337b 100644 --- a/src/vstest.console/Resources/xlf/Resources.zh-Hans.xlf +++ b/src/vstest.console/Resources/xlf/Resources.zh-Hans.xlf @@ -1593,16 +1593,31 @@ 此平台不支持用于追责的 CollectDump 选项。 - - The blame option specified '{0}' is not a valid format. Please correct it and retry. - The blame option specified '{0}' is not valid. This will be ignored. - - The blame parameter specified with blame, {0} is invalid. Ignoring this parameter. The option specified with blame, {0} is invalid. This will be ignored. + + Diag file path '{0}' is not valid. + Diag file path '{0}' is not valid. + + + + Blame argument '{0}' is not valid. + Blame argument '{0}' in invalid. + + + + Diag argument '{0}' is not valid. + Diag argument '{0}' is invalid. + + + + Logger argument '{0}' is not valid. + Logger argument '{0}' is invalid. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.zh-Hant.xlf b/src/vstest.console/Resources/xlf/Resources.zh-Hant.xlf index e57012077e..4158898d47 100644 --- a/src/vstest.console/Resources/xlf/Resources.zh-Hant.xlf +++ b/src/vstest.console/Resources/xlf/Resources.zh-Hant.xlf @@ -1593,16 +1593,31 @@ 對此平台不支援 Blame 的 CollectDump 選項。 - - The blame option specified '{0}' is not a valid format. Please correct it and retry. - The blame option specified '{0}' is not valid. This will be ignored. - - The blame parameter specified with blame, {0} is invalid. Ignoring this parameter. The option specified with blame, {0} is invalid. This will be ignored. + + Diag file path '{0}' is not valid. + Diag file path '{0}' is not valid. + + + + Blame argument '{0}' is not valid. + Blame argument '{0}' in invalid. + + + + Diag argument '{0}' is not valid. + Diag argument '{0}' is invalid. + + + + Logger argument '{0}' is not valid. + Logger argument '{0}' is invalid. + + \ No newline at end of file diff --git a/test/vstest.console.UnitTests/Processors/EnableBlameArgumentProcessorTests.cs b/test/vstest.console.UnitTests/Processors/EnableBlameArgumentProcessorTests.cs index 66c12096cf..99904578d8 100644 --- a/test/vstest.console.UnitTests/Processors/EnableBlameArgumentProcessorTests.cs +++ b/test/vstest.console.UnitTests/Processors/EnableBlameArgumentProcessorTests.cs @@ -159,7 +159,7 @@ public void InitializeShouldThrowIfInvalidParameterFormatIsSpecifiedForCollectDu .Returns(PlatformArchitecture.X64); this.executor.Initialize(invalidString); - this.mockOutput.Verify(x => x.WriteLine(string.Format(CultureInfo.CurrentUICulture, CommandLineResources.BlameInvalidFormat, invalidString), OutputLevel.Warning)); + this.mockOutput.Verify(x => x.WriteLine(string.Format(CultureInfo.CurrentUICulture, CommandLineResources.InvalidBlameArgument, invalidString), OutputLevel.Warning)); Assert.IsNotNull(this.settingsProvider.ActiveRunSettings); Assert.AreEqual("\r\n\r\n \r\n \r\n \r\n \r\n C:\\dir\\TestResults\r\n \r\n \r\n \r\n \r\n \r\n C:\\dir\\TestResults\r\n \r\n \r\n \r\n \r\n \r\n \r\n", this.settingsProvider.ActiveRunSettings.SettingsXml); diff --git a/test/vstest.console.UnitTests/Processors/EnableDiagArgumentProcessorTests.cs b/test/vstest.console.UnitTests/Processors/EnableDiagArgumentProcessorTests.cs index 195145fdda..73c06e7d95 100644 --- a/test/vstest.console.UnitTests/Processors/EnableDiagArgumentProcessorTests.cs +++ b/test/vstest.console.UnitTests/Processors/EnableDiagArgumentProcessorTests.cs @@ -5,6 +5,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.UnitTests.Processors { using System; using System.Diagnostics; + using System.Globalization; using System.IO; using Microsoft.VisualStudio.TestPlatform.CommandLine.Processors; @@ -72,10 +73,13 @@ public void EnableDiagArgumentProcessorMetadataShouldProvideAppropriateCapabilit } [TestMethod] - public void EnableDiagArgumentProcessorExecutorThrowsIfFileNameIsNullOrEmpty() + [DataRow(null)] + [DataRow(" ")] + [DataRow("")] + public void EnableDiagArgumentProcessorExecutorThrowsIfDiagArgumentIsNullOrEmpty(string argument) { - Assert.ThrowsException(() => this.diagProcessor.Executor.Value.Initialize(null)); - Assert.ThrowsException(() => this.diagProcessor.Executor.Value.Initialize(string.Empty)); + string exceptionMessage = string.Format(CultureInfo.CurrentUICulture, CommandLineResources.InvalidDiagArgument, argument); + EnableDiagArgumentProcessorExecutorShouldThrowIfInvalidArgument(argument, exceptionMessage); } [TestMethod] @@ -87,20 +91,23 @@ public void EnableDiagArgumentProcessorExecutorDoesNotThrowsIfFileDotOpenThrow() } [TestMethod] - public void EnableDiagArgumentProcessorExecutorShouldThrowIfAPathIsProvided() + [DataRow("abs;dfsdc.txt;verbosity=normal", "abs")] // ; in file path is not supported + [DataRow("\"abst;dfsdc.txt\";verbosity=normal", "abst")] // Even though in escaped double quotes, semi colon is not supported in file path + [DataRow("foo", "foo")] + public void EnableDiagArgumentProcessorExecutorShouldThrowIfDirectoryPathIsProvided(string argument, string filePath) { - Assert.ThrowsException(() => this.diagProcessor.Executor.Value.Initialize("foo")); + var exceptionMessage = string.Format(CultureInfo.CurrentCulture, CommandLineResources.InvalidDiagFilePath, filePath); + + EnableDiagArgumentProcessorExecutorShouldThrowIfInvalidArgument(argument, exceptionMessage); } [TestMethod] - [DataRow("")] - [DataRow(" ")] - [DataRow("abs;dfsdc.txt;verbosity=normal")] // ; in file path is not supported - [DataRow("abc.txt;verbosity=normal=verbose")] // Multiple '=' in parameters - [DataRow("\"abs;dfsdc.txt\";verbosity=normal")] // Even though in escaped double quotes, semi colon is not supported in file path + [DataRow("abc.txt;verbosity=normal=verbose")] // Multiple '=' in parameter + [DataRow("abc.txt;verbosity;key1=value1")] // No '=' in parameter public void EnableDiagArgumentProcessorExecutorShouldThrowIfInvalidArgument(string argument) { - Assert.ThrowsException(() => this.diagProcessor.Executor.Value.Initialize(argument)); + string exceptionMessage = string.Format(CultureInfo.CurrentCulture, CommandLineResources.InvalidDiagArgument, argument); + EnableDiagArgumentProcessorExecutorShouldThrowIfInvalidArgument(argument, exceptionMessage); } [TestMethod] @@ -182,5 +189,18 @@ public TestableEnableDiagArgumentProcessor(IFileHelper fileHelper) { } } + + private void EnableDiagArgumentProcessorExecutorShouldThrowIfInvalidArgument(string argument, string exceptionMessage) + { + try + { + this.diagProcessor.Executor.Value.Initialize(argument); + } + catch (Exception e) + { + Assert.IsTrue(e.GetType().Equals(typeof(CommandLineException))); + Assert.IsTrue(e.Message.Contains(exceptionMessage)); + } + } } } \ No newline at end of file diff --git a/test/vstest.console.UnitTests/Processors/EnableLoggersArgumentProcessorTests.cs b/test/vstest.console.UnitTests/Processors/EnableLoggersArgumentProcessorTests.cs index 7d3b980856..ef0d759097 100644 --- a/test/vstest.console.UnitTests/Processors/EnableLoggersArgumentProcessorTests.cs +++ b/test/vstest.console.UnitTests/Processors/EnableLoggersArgumentProcessorTests.cs @@ -3,15 +3,14 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.UnitTests.Processors { + using System; + using System.Globalization; + using Microsoft.VisualStudio.TestPlatform.CommandLine.Processors; - using Microsoft.VisualStudio.TestPlatform.Common.Logging; + using Microsoft.VisualStudio.TestPlatform.Common; using Microsoft.VisualStudio.TestTools.UnitTesting; - using vstest.console.UnitTests.TestDoubles; - using System.Linq; - using Microsoft.VisualStudio.TestPlatform.Common; - using Moq; - using System; + using CommandLineResources = Microsoft.VisualStudio.TestPlatform.CommandLine.Resources.Resources; [TestClass] public class EnableLoggersArgumentProcessorTests @@ -57,23 +56,22 @@ public void CapabilitiesShouldAppropriateProperties() } [TestMethod] - public void ExecutorInitializeWithNullOrEmptyArgumentsShouldThrowException() + [DataRow(" ")] + [DataRow(null)] + [DataRow("TestLoggerExtension;==;;;Collection=http://localhost:8080/tfs/DefaultCollection;TeamProject=MyProject;BuildName=DailyBuild_20121130.1")] + public void ExectorInitializeShouldThrowExceptionIfInvalidArgumentIsPassed(string argument) { var executor = new EnableLoggerArgumentExecutor(RunSettingsManager.Instance); - Assert.ThrowsException(() => + try { - executor.Initialize(null); - }); - } - - [TestMethod] - public void ExectorInitializeShouldThrowExceptionIfInvalidArgumentIsPassed() - { - var executor = new EnableLoggerArgumentExecutor(RunSettingsManager.Instance); - Assert.ThrowsException(() => + executor.Initialize(argument); + } + catch (Exception e) { - executor.Initialize("TestLoggerExtension;==;;;Collection=http://localhost:8080/tfs/DefaultCollection;TeamProject=MyProject;BuildName=DailyBuild_20121130.1"); - }); + string exceptionMessage = string.Format(CultureInfo.CurrentUICulture, CommandLineResources.LoggerUriInvalid, argument); + Assert.IsTrue(e.GetType().Equals(typeof(CommandLineException))); + Assert.IsTrue(e.Message.Contains(exceptionMessage)); + } } [TestMethod] diff --git a/test/vstest.console.UnitTests/Processors/Utilities/ArgumentProcessorUtilitiesTests.cs b/test/vstest.console.UnitTests/Processors/Utilities/ArgumentProcessorUtilitiesTests.cs index db5f0d9335..c966df482d 100644 --- a/test/vstest.console.UnitTests/Processors/Utilities/ArgumentProcessorUtilitiesTests.cs +++ b/test/vstest.console.UnitTests/Processors/Utilities/ArgumentProcessorUtilitiesTests.cs @@ -5,6 +5,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.UnitTests.Processors.U { using Microsoft.VisualStudio.TestPlatform.CommandLine.Processors.Utilities; using System; + using System.Collections.Generic; using System.Linq; using TestTools.UnitTesting; @@ -19,12 +20,12 @@ public void GetArgumentListShouldThrowErrorOnInvalidArgument(string argument) { try { - ArgumemtProcessorUtilities.GetArgumentList(argument, ArgumemtProcessorUtilities.SemiColonArgumentSeperator, "exception in argument."); + ArgumentProcessorUtilities.GetArgumentList(argument, ArgumentProcessorUtilities.SemiColonArgumentSeparator, "test exception."); } catch (Exception e) { Assert.IsTrue(e.GetType().Equals(typeof(CommandLineException))); - Assert.IsTrue(e.Message.Contains("exception in argument.")); + Assert.IsTrue(e.Message.Contains("test exception.")); } } @@ -33,8 +34,32 @@ public void GetArgumentListShouldThrowErrorOnInvalidArgument(string argument) [DataRow(";;;abc.txt;;;tracelevel=info;;;newkey=newvalue;;;;")] public void GetArgumentListShouldReturnCorrectArgumentList(string argument) { - var argumentList = ArgumemtProcessorUtilities.GetArgumentList(argument, ArgumemtProcessorUtilities.SemiColonArgumentSeperator, "exception in argument."); + var argumentList = ArgumentProcessorUtilities.GetArgumentList(argument, ArgumentProcessorUtilities.SemiColonArgumentSeparator, "test exception."); argumentList.SequenceEqual(new string[] { "abc.txt", "tracelevel=info", "newkey=newvalue" }); } + + [TestMethod] + [DataRow(new string[] { "key1=value1", "invalidPair", "key2=value2"})] + public void GetArgumentParametersShouldThrowErrorOnInvalidParameters(string[] parameterArgs) + { + try + { + ArgumentProcessorUtilities.GetArgumentParameters(parameterArgs, ArgumentProcessorUtilities.EqualNameValueSeparator, "test exception."); + } + catch (Exception e) + { + Assert.IsTrue(e.GetType().Equals(typeof(CommandLineException))); + Assert.IsTrue(e.Message.Contains("test exception.")); + } + } + + [TestMethod] + public void GetArgumentParametersShouldReturnCorrectParameterDictionary() + { + var parameterDict = ArgumentProcessorUtilities.GetArgumentParameters(new string[] { "key1=value1", "key2=value2", "key3=value3" }, ArgumentProcessorUtilities.EqualNameValueSeparator, "test exception."); + + var expectedDict = new Dictionary { { "key1", "value1"}, { "key2", "value2"}, { "key3", "value3"} }; + CollectionAssert.AreEqual(parameterDict.OrderBy(kv => kv.Key).ToList(), expectedDict.OrderBy(kv => kv.Key).ToList()); + } } } \ No newline at end of file From 47aa5b301729295957d3a1ec1fc73da538ac7e18 Mon Sep 17 00:00:00 2001 From: abhishkk Date: Tue, 31 Jul 2018 17:37:27 +0530 Subject: [PATCH 09/10] removing platform abstractions dependency from translation layer --- .../ConsoleParameters.cs | 8 +++++--- ...oft.TestPlatform.VsTestConsole.TranslationLayer.csproj | 5 ++++- .../VsTestConsoleProcessManager.cs | 2 +- test/TranslationLayer.UnitTests/ConsoleParametersTests.cs | 6 +++--- .../VsTestConsoleWrapperTests.cs | 4 ++-- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/ConsoleParameters.cs b/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/ConsoleParameters.cs index efd9783c5b..3fc17b4bda 100644 --- a/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/ConsoleParameters.cs +++ b/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/ConsoleParameters.cs @@ -3,12 +3,14 @@ namespace Microsoft.TestPlatform.VsTestConsole.TranslationLayer { + using System; + using System.Diagnostics; + using System.IO; + using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Extensions; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; - using System; - using System.IO; /// /// Class which defines additional specifiable parameters for vstest.console.exe @@ -38,7 +40,7 @@ public ConsoleParameters(IFileHelper fileHelper) /// /// Trace level for logs. /// - public PlatformTraceLevel TraceLevel { get; set; } = PlatformTraceLevel.Verbose; + public TraceLevel TraceLevel { get; set; } = TraceLevel.Verbose; /// /// Full path for the log file diff --git a/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/Microsoft.TestPlatform.VsTestConsole.TranslationLayer.csproj b/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/Microsoft.TestPlatform.VsTestConsole.TranslationLayer.csproj index 5195d5883b..1139b62a48 100644 --- a/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/Microsoft.TestPlatform.VsTestConsole.TranslationLayer.csproj +++ b/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/Microsoft.TestPlatform.VsTestConsole.TranslationLayer.csproj @@ -22,7 +22,7 @@ - + 4.1.1 @@ -37,6 +37,9 @@ 4.1.0 + + + 4.0.0 diff --git a/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs b/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs index e8e7cf82e9..dca45aac6e 100644 --- a/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs +++ b/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs @@ -134,7 +134,7 @@ private string[] BuildArguments(ConsoleParameters parameters) if(!string.IsNullOrEmpty(parameters.LogFilePath)) { - // Extra args: --diag|/diag: + // Extra args: --diag|/diag:;tracelevel= args.Add(string.Format(CultureInfo.InvariantCulture, DIAG_ARGUMENT, parameters.LogFilePath, parameters.TraceLevel)); } diff --git a/test/TranslationLayer.UnitTests/ConsoleParametersTests.cs b/test/TranslationLayer.UnitTests/ConsoleParametersTests.cs index 5e4a8a8bce..a299d5c925 100644 --- a/test/TranslationLayer.UnitTests/ConsoleParametersTests.cs +++ b/test/TranslationLayer.UnitTests/ConsoleParametersTests.cs @@ -3,12 +3,12 @@ namespace Microsoft.TestPlatform.VsTestConsole.TranslationLayer.UnitTests { + using System.Diagnostics; + using Microsoft.TestPlatform.VsTestConsole.TranslationLayer; - using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; using Microsoft.VisualStudio.TestTools.UnitTesting; - using Moq; [TestClass] @@ -33,7 +33,7 @@ public void LogFilePathShouldEnsureDoubleQuote() public void TraceLevelShouldHaveVerboseAsDefaultValue() { var consoleParameters = new ConsoleParameters(new FileHelper()); - Assert.AreEqual(consoleParameters.TraceLevel, PlatformTraceLevel.Verbose); + Assert.AreEqual(consoleParameters.TraceLevel, TraceLevel.Verbose); } } } diff --git a/test/TranslationLayer.UnitTests/VsTestConsoleWrapperTests.cs b/test/TranslationLayer.UnitTests/VsTestConsoleWrapperTests.cs index 0ad3f00317..1c7f158755 100644 --- a/test/TranslationLayer.UnitTests/VsTestConsoleWrapperTests.cs +++ b/test/TranslationLayer.UnitTests/VsTestConsoleWrapperTests.cs @@ -5,7 +5,7 @@ namespace Microsoft.TestPlatform.VsTestConsole.TranslationLayer.UnitTests { using System; using System.Collections.Generic; - + using System.Diagnostics; using Microsoft.TestPlatform.VsTestConsole.TranslationLayer.Interfaces; using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Tracing.Interfaces; using Microsoft.VisualStudio.TestPlatform.ObjectModel; @@ -63,7 +63,7 @@ public void StartSessionShouldStartVsTestConsoleWithCorrectArguments() Assert.AreEqual(expectedParentProcessId, this.consoleParameters.ParentProcessId, "Parent process Id must be set"); Assert.AreEqual(inputPort, this.consoleParameters.PortNumber, "Port number must be set"); - Assert.AreEqual(PlatformTraceLevel.Verbose, this.consoleParameters.TraceLevel, "Default value of trace level should be verbose."); + Assert.AreEqual(TraceLevel.Verbose, this.consoleParameters.TraceLevel, "Default value of trace level should be verbose."); this.mockProcessManager.Verify(pm => pm.StartProcess(this.consoleParameters), Times.Once); } From 68490bbb50c3f284b402f90df6bbe7878dc32d43 Mon Sep 17 00:00:00 2001 From: abhishkk Date: Wed, 1 Aug 2018 14:32:42 +0530 Subject: [PATCH 10/10] PR comments --- .../Tracing/EqtTrace.cs | 2 +- src/datacollector/DataCollectorMain.cs | 13 +++++++++---- .../Processors/EnableDiagArgumentProcessor.cs | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Tracing/EqtTrace.cs b/src/Microsoft.TestPlatform.CoreUtilities/Tracing/EqtTrace.cs index 0f0cb2fe3f..c946f142d5 100644 --- a/src/Microsoft.TestPlatform.CoreUtilities/Tracing/EqtTrace.cs +++ b/src/Microsoft.TestPlatform.CoreUtilities/Tracing/EqtTrace.cs @@ -153,7 +153,7 @@ public static bool InitializeVerboseTrace(string customLogFile) /// Initializes the tracing with custom log file and trace level. /// Overrides if any trace is set before. /// - /// Customr log file for trace messages. + /// Custom log file for trace messages. /// Trace level. /// Trace initialized flag. public static bool InitializeTrace(string customLogFile, PlatformTraceLevel traceLevel) diff --git a/src/datacollector/DataCollectorMain.cs b/src/datacollector/DataCollectorMain.cs index cadc0350c0..7e61df298b 100644 --- a/src/datacollector/DataCollectorMain.cs +++ b/src/datacollector/DataCollectorMain.cs @@ -71,14 +71,19 @@ public void Run(string[] args) if (argsDictionary.TryGetValue(LogFileArgument, out logFile)) { var traceLevelInt = CommandLineArgumentsHelper.GetIntArgFromDict(argsDictionary, TraceLevelArgument); + var isTraceLevelArgValid = Enum.IsDefined(typeof(PlatformTraceLevel), traceLevelInt); // In case traceLevelInt is not defined in PlatfromTraceLevel, default it to verbose. - var traceLevel = Enum.IsDefined(typeof(PlatformTraceLevel), traceLevelInt) ? - (PlatformTraceLevel)traceLevelInt : - PlatformTraceLevel.Verbose; + var traceLevel = isTraceLevelArgValid ? (PlatformTraceLevel)traceLevelInt : PlatformTraceLevel.Verbose; - EqtTrace.Warning("DataCollectorMain.Run: Invalid trace level: {0}, defaulting to vebose tracelevel.", traceLevelInt); + // Initialize trace. EqtTrace.InitializeTrace(logFile, traceLevel); + + // Log warning in case tracelevel passed in arg is invalid + if (!isTraceLevelArgValid) + { + EqtTrace.Warning("DataCollectorMain.Run: Invalid trace level: {0}, defaulting to verbose tracelevel.", traceLevelInt); + } } else { diff --git a/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs b/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs index e4a47f270c..2656c0105c 100644 --- a/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs +++ b/src/vstest.console/Processors/EnableDiagArgumentProcessor.cs @@ -166,7 +166,7 @@ public ArgumentProcessorResult Execute() } /// - /// Initialize diag loggin. + /// Initialize diag logging. /// /// Diag file path. /// Diag parameters