diff --git a/src/Microsoft.DotNet.XUnitConsoleRunner/src/ConsoleRunner.cs b/src/Microsoft.DotNet.XUnitConsoleRunner/src/ConsoleRunner.cs index b7ebf62d0c2..5c99447c242 100644 --- a/src/Microsoft.DotNet.XUnitConsoleRunner/src/ConsoleRunner.cs +++ b/src/Microsoft.DotNet.XUnitConsoleRunner/src/ConsoleRunner.cs @@ -28,6 +28,14 @@ public ConsoleRunner(object consoleLock) public int EntryPoint(string[] args) { +#if WINDOWS_UWP + // Handle RemoteExecutor + if (args.Length > 0 && args[0] == "remote") + { + return RemoteExecutor.Execute(args.Skip(1).ToArray()); + } +#endif + commandLine = CommandLine.Parse(args); try @@ -169,9 +177,8 @@ List GetAvailableRunnerReporters() void PrintHeader() { var platform = System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription; - var versionAttribute = typeof(ConsoleRunner).GetTypeInfo().Assembly.GetCustomAttribute(); - Console.WriteLine($"xUnit.net Console Runner v{versionAttribute.InformationalVersion} ({IntPtr.Size * 8}-bit {platform})"); + Console.WriteLine($"Microsoft.DotNet.XUnitConsoleRunner v2.5.0 ({IntPtr.Size * 8}-bit {platform})"); } void PrintUsage(IReadOnlyList reporters) diff --git a/src/Microsoft.DotNet.XUnitConsoleRunner/src/Microsoft.DotNet.XUnitConsoleRunner.csproj b/src/Microsoft.DotNet.XUnitConsoleRunner/src/Microsoft.DotNet.XUnitConsoleRunner.csproj index 9d61aeb9800..3f188cd8319 100644 --- a/src/Microsoft.DotNet.XUnitConsoleRunner/src/Microsoft.DotNet.XUnitConsoleRunner.csproj +++ b/src/Microsoft.DotNet.XUnitConsoleRunner/src/Microsoft.DotNet.XUnitConsoleRunner.csproj @@ -6,7 +6,7 @@ true Exe Xunit.ConsoleClient - netcoreapp2.0 + netcoreapp2.0 true 2.5.0 latest diff --git a/src/Microsoft.DotNet.XUnitRunnerUap/src/RemoteExecutor.cs b/src/Microsoft.DotNet.XUnitConsoleRunner/src/RemoteExecutor.cs similarity index 90% rename from src/Microsoft.DotNet.XUnitRunnerUap/src/RemoteExecutor.cs rename to src/Microsoft.DotNet.XUnitConsoleRunner/src/RemoteExecutor.cs index 8ce6c0a1158..e47d337c157 100644 --- a/src/Microsoft.DotNet.XUnitRunnerUap/src/RemoteExecutor.cs +++ b/src/Microsoft.DotNet.XUnitConsoleRunner/src/RemoteExecutor.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if WINDOWS_UWP + using System; using System.IO; using System.Reflection; @@ -10,7 +12,7 @@ using System.Runtime.ExceptionServices; using System.Runtime.InteropServices; -namespace Microsoft.DotNet.XUnitRunnerUap +namespace Xunit.ConsoleClient { /// /// Provides an entry point in a new process that will load a specified method and invoke it. @@ -113,22 +115,6 @@ public static int Execute(string[] args) return exitCode; } - private static MethodInfo GetMethod(this Type type, string methodName) - { - Type t = type; - while (t != null) - { - TypeInfo ti = t.GetTypeInfo(); - MethodInfo mi = ti.GetDeclaredMethod(methodName); - if (mi != null) - { - return mi; - } - t = ti.BaseType; - } - return null; - } - private static T[] Subarray(this T[] arr, int offset, int count) { var newArr = new T[count]; @@ -137,3 +123,5 @@ private static T[] Subarray(this T[] arr, int offset, int count) } } } + +#endif diff --git a/src/Microsoft.DotNet.XUnitConsoleRunner/src/Utility/ConsoleRunnerLogger.cs b/src/Microsoft.DotNet.XUnitConsoleRunner/src/Utility/ConsoleRunnerLogger.cs new file mode 100644 index 00000000000..935269ef8a5 --- /dev/null +++ b/src/Microsoft.DotNet.XUnitConsoleRunner/src/Utility/ConsoleRunnerLogger.cs @@ -0,0 +1,84 @@ +#if WINDOWS_UWP + +using System; + +namespace Xunit.ConsoleClient +{ + /// + /// An implementation of which logs messages + /// to and . + /// + public class ConsoleRunnerLogger : IRunnerLogger + { + readonly object lockObject; + readonly bool useColors; + + /// + /// Initializes a new instance of the class. + /// + /// A flag to indicate whether colors should be used when + /// logging messages. + public ConsoleRunnerLogger(bool useColors) : this(useColors, new object()) { } + + /// + /// Initializes a new instance of the class. + /// + /// A flag to indicate whether colors should be used when + /// logging messages. + /// The lock object used to prevent console clashes. + public ConsoleRunnerLogger(bool useColors, object lockObject) + { + this.useColors = useColors; + this.lockObject = lockObject; + } + + /// + public object LockObject => lockObject; + + /// + public void LogError(StackFrameInfo stackFrame, string message) + { + using (SetColor(ConsoleColor.Red)) + lock (LockObject) + Console.Error.WriteLine(message); + } + + /// + public void LogImportantMessage(StackFrameInfo stackFrame, string message) + { + using (SetColor(ConsoleColor.Gray)) + lock (LockObject) + Console.WriteLine(message); + } + + /// + public void LogMessage(StackFrameInfo stackFrame, string message) + { + using (SetColor(ConsoleColor.DarkGray)) + lock (LockObject) + Console.WriteLine(message); + } + + /// + public void LogWarning(StackFrameInfo stackFrame, string message) + { + using (SetColor(ConsoleColor.Yellow)) + lock (LockObject) + Console.WriteLine(message); + } + + IDisposable SetColor(ConsoleColor color) + => useColors ? new ColorRestorer(color) : null; + + class ColorRestorer : IDisposable + { + public ColorRestorer(ConsoleColor color) + => ConsoleHelper.SetForegroundColor(color); + + public void Dispose() + => ConsoleHelper.ResetColor(); + } + } +} + +#endif diff --git a/src/Microsoft.DotNet.XUnitConsoleRunner/src/Utility/TransformFactory.cs b/src/Microsoft.DotNet.XUnitConsoleRunner/src/Utility/TransformFactory.cs index a939e499cdb..7a54089729f 100644 --- a/src/Microsoft.DotNet.XUnitConsoleRunner/src/Utility/TransformFactory.cs +++ b/src/Microsoft.DotNet.XUnitConsoleRunner/src/Utility/TransformFactory.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/AssemblyHelper.cs b/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/AssemblyHelper.cs index 329034bee64..1c7893b3cbf 100644 --- a/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/AssemblyHelper.cs +++ b/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/AssemblyHelper.cs @@ -1,5 +1,3 @@ -#if NETCOREAPP - using System; using System.IO; using System.Reflection; @@ -103,5 +101,3 @@ public static IDisposable SubscribeResolveForAssembly(Type typeInAssembly, IMess => new AssemblyHelper(typeInAssembly.GetTypeInfo().Assembly.Location, internalDiagnosticsMessageSink); } } - -#endif diff --git a/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/AssemblyHelper.uap.cs b/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/AssemblyHelper.uap.cs index 83accd435b4..150074f5977 100644 --- a/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/AssemblyHelper.uap.cs +++ b/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/AssemblyHelper.uap.cs @@ -1,4 +1,4 @@ -#if WINDOWS_UAP +#if WINDOWS_UWP using System; using Xunit.Abstractions; diff --git a/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/DependencyContextAssemblyCache.cs b/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/DependencyContextAssemblyCache.cs index 552844d3fbe..bc6d6068c2d 100644 --- a/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/DependencyContextAssemblyCache.cs +++ b/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/DependencyContextAssemblyCache.cs @@ -1,5 +1,3 @@ -#if NETCOREAPP - using System; using System.Collections.Generic; using System.IO; @@ -295,5 +293,3 @@ public string ResolveUnmanagedLibrary(string unmanagedLibraryName) } } } - -#endif diff --git a/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/Microsoft.DotNet.PlatformAbstractions/ApplicationEnvironment.cs b/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/Microsoft.DotNet.PlatformAbstractions/ApplicationEnvironment.cs index 7239a36cf61..74ed0624652 100644 --- a/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/Microsoft.DotNet.PlatformAbstractions/ApplicationEnvironment.cs +++ b/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/Microsoft.DotNet.PlatformAbstractions/ApplicationEnvironment.cs @@ -1,8 +1,6 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -#if NETCOREAPP - using System; using System.IO; @@ -19,5 +17,3 @@ private static string GetApplicationBasePath() } } } - -#endif diff --git a/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/Microsoft.Extensions.DependencyModel/DependencyContext.cs b/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/Microsoft.Extensions.DependencyModel/DependencyContext.cs index 69aff6dbff8..83b34ac3da7 100644 --- a/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/Microsoft.Extensions.DependencyModel/DependencyContext.cs +++ b/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/Microsoft.Extensions.DependencyModel/DependencyContext.cs @@ -1,8 +1,6 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -#if NETCOREAPP - using System; using System.Collections.Generic; using System.Linq; @@ -106,5 +104,3 @@ public int GetHashCode(T obj) } } } - -#endif diff --git a/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs b/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs index 104a12da2df..051cedbb192 100644 --- a/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs +++ b/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs @@ -1,8 +1,6 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -#if NETCOREAPP - using System; using System.Collections.Generic; using System.IO; @@ -525,5 +523,3 @@ private struct LibraryStub } } } - -#endif diff --git a/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/Microsoft.Extensions.DependencyModel/DependencyContextLoader.cs b/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/Microsoft.Extensions.DependencyModel/DependencyContextLoader.cs index 57249dc7e92..d2ff1cccfc7 100644 --- a/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/Microsoft.Extensions.DependencyModel/DependencyContextLoader.cs +++ b/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/Microsoft.Extensions.DependencyModel/DependencyContextLoader.cs @@ -1,8 +1,6 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -#if NETCOREAPP - using System; using System.Collections.Generic; using System.Diagnostics; @@ -128,5 +126,3 @@ private DependencyContext LoadAssemblyContext(Assembly assembly, IDependencyCont } } } - -#endif diff --git a/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/Microsoft.Extensions.DependencyModel/IDependencyContextReader.cs b/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/Microsoft.Extensions.DependencyModel/IDependencyContextReader.cs index 0a189a0b65e..2d5662eb382 100644 --- a/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/Microsoft.Extensions.DependencyModel/IDependencyContextReader.cs +++ b/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/Microsoft.Extensions.DependencyModel/IDependencyContextReader.cs @@ -1,5 +1,3 @@ -#if NETCOREAPP - using System; using System.IO; @@ -10,5 +8,3 @@ internal interface IDependencyContextReader: IDisposable DependencyContext Read(Stream stream); } } - -#endif diff --git a/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/XunitPackageCompilationAssemblyResolver.cs b/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/XunitPackageCompilationAssemblyResolver.cs index 01d4fe378b0..32974a0c190 100644 --- a/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/XunitPackageCompilationAssemblyResolver.cs +++ b/src/Microsoft.DotNet.XUnitConsoleRunner/src/common/AssemblyResolution/XunitPackageCompilationAssemblyResolver.cs @@ -1,5 +1,3 @@ -#if NETCOREAPP - // Adapted from https://github.com/dotnet/core-setup/blob/652b680dff6b1afb9cd26cc3c2e883a664c209fd/src/managed/Microsoft.Extensions.DependencyModel/Resolution/PackageCompilationAssemblyResolver.cs using System; @@ -101,5 +99,3 @@ bool TryResolveFromPackagePath(CompilationLibrary library, string basePath, out } } } - -#endif diff --git a/src/Microsoft.DotNet.XUnitRunnerUap/src/CommandLine.cs b/src/Microsoft.DotNet.XUnitRunnerUap/src/CommandLine.cs deleted file mode 100644 index cb363b7c34c..00000000000 --- a/src/Microsoft.DotNet.XUnitRunnerUap/src/CommandLine.cs +++ /dev/null @@ -1,323 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; -using System.IO; -using Xunit; - -namespace Microsoft.DotNet.XUnitRunnerUap -{ - internal class CommandLine - { - public enum ParallelismOption - { - none, - collections, - assemblies, - all - } - - private readonly Stack arguments = new Stack(); - - private CommandLine(string[] args, Predicate fileExists = null) - { - if (fileExists == null) - fileExists = File.Exists; - - for (var i = args.Length - 1; i >= 0; i--) - arguments.Push(args[i]); - - Project = Parse(fileExists); - } - - public bool Debug { get; protected set; } - - public bool DiagnosticMessages { get; protected set; } - - public bool FailSkips { get; protected set; } - - public int? MaxParallelThreads { get; set; } - - public bool NoColor { get; protected set; } - - public bool NoLogo { get; protected set; } - - public XunitProject Project { get; protected set; } - - public bool? ParallelizeAssemblies { get; protected set; } - - public bool? ParallelizeTestCollections { get; set; } - - public bool Serialize { get; protected set; } - - public bool Verbose { get; protected set; } - - public bool Wait { get; protected set; } - - public static CommandLine Parse(params string[] args) - { - return new CommandLine(args); - } - - protected virtual string GetFullPath(string fileName) - { - return Path.GetFullPath(fileName); - } - - XunitProject GetProjectFile(List> assemblies) - { - var result = new XunitProject(); - - foreach (var assembly in assemblies) - result.Add(new XunitProjectAssembly - { - AssemblyFilename = GetFullPath(assembly.Item1), - ConfigFilename = assembly.Item2 != null ? GetFullPath(assembly.Item2) : null, - }); - - return result; - } - - static void GuardNoOptionValue(KeyValuePair option) - { - if (option.Value != null) - throw new ArgumentException($"error: unknown command line option: {option.Value}"); - } - - static bool IsConfigFile(string fileName) - { - return fileName.EndsWith(".config", StringComparison.OrdinalIgnoreCase) - || fileName.EndsWith(".json", StringComparison.OrdinalIgnoreCase); - } - - protected XunitProject Parse(Predicate fileExists) - { - var assemblies = new List>(); - - while (arguments.Count > 0) - { - if (arguments.Peek().StartsWith("-", StringComparison.Ordinal)) - break; - - var assemblyFile = arguments.Pop(); - - string configFile = null; - if (arguments.Count > 0) - { - var value = arguments.Peek(); - if (!value.StartsWith("-", StringComparison.Ordinal) && IsConfigFile(value)) - { - configFile = arguments.Pop(); - if (!fileExists(configFile)) - throw new ArgumentException($"config file not found: {configFile}"); - } - } - - assemblies.Add(Tuple.Create(assemblyFile, configFile)); - } - - if (assemblies.Count == 0) - throw new ArgumentException("must specify at least one assembly"); - - var project = GetProjectFile(assemblies); - - while (arguments.Count > 0) - { - var option = PopOption(arguments); - var optionName = option.Key.ToLowerInvariant(); - - if (!optionName.StartsWith("-", StringComparison.Ordinal)) - throw new ArgumentException($"unknown command line option: {option.Key}"); - - optionName = optionName.Substring(1); - - if (optionName == "nologo") - { - GuardNoOptionValue(option); - NoLogo = true; - } - else if (optionName == "failskips") - { - GuardNoOptionValue(option); - FailSkips = true; - } - else if (optionName == "nocolor") - { - GuardNoOptionValue(option); - NoColor = true; - } - else if (optionName == "debug") - { - GuardNoOptionValue(option); - Debug = true; - } - else if (optionName == "serialize") - { - GuardNoOptionValue(option); - Serialize = true; - } - else if (optionName == "verbose") - { - GuardNoOptionValue(option); - Verbose = true; - } - else if (optionName == "wait") - { - GuardNoOptionValue(option); - Wait = true; - } - else if (optionName == "diagnostics") - { - GuardNoOptionValue(option); - DiagnosticMessages = true; - } - else if (optionName == "maxthreads") - { - if (option.Value == null) - throw new ArgumentException("missing argument for -maxthreads"); - - switch (option.Value) - { - case "default": - MaxParallelThreads = 0; - break; - - case "unlimited": - MaxParallelThreads = -1; - break; - - default: - int threadValue; - if (!int.TryParse(option.Value, out threadValue) || threadValue < 1) - throw new ArgumentException("incorrect argument value for -maxthreads (must be 'default', 'unlimited', or a positive number)"); - - MaxParallelThreads = threadValue; - break; - } - } - else if (optionName == "parallel") - { - if (option.Value == null) - throw new ArgumentException("missing argument for -parallel"); - - ParallelismOption parallelismOption; - if (!Enum.TryParse(option.Value, out parallelismOption)) - throw new ArgumentException("incorrect argument value for -parallel"); - - switch (parallelismOption) - { - case ParallelismOption.all: - ParallelizeAssemblies = true; - ParallelizeTestCollections = true; - break; - - case ParallelismOption.assemblies: - ParallelizeAssemblies = true; - ParallelizeTestCollections = false; - break; - - case ParallelismOption.collections: - ParallelizeAssemblies = false; - ParallelizeTestCollections = true; - break; - - default: - ParallelizeAssemblies = false; - ParallelizeTestCollections = false; - break; - } - } - else if (optionName == "trait") - { - if (option.Value == null) - throw new ArgumentException("missing argument for -trait"); - - var pieces = option.Value.Split('='); - if (pieces.Length != 2 || string.IsNullOrEmpty(pieces[0]) || string.IsNullOrEmpty(pieces[1])) - throw new ArgumentException("incorrect argument format for -trait (should be \"name=value\")"); - - var name = pieces[0]; - var value = pieces[1]; - project.Filters.IncludedTraits.Add(name, value); - } - else if (optionName == "notrait") - { - if (option.Value == null) - throw new ArgumentException("missing argument for -notrait"); - - var pieces = option.Value.Split('='); - if (pieces.Length != 2 || string.IsNullOrEmpty(pieces[0]) || string.IsNullOrEmpty(pieces[1])) - throw new ArgumentException("incorrect argument format for -notrait (should be \"name=value\")"); - - var name = pieces[0]; - var value = pieces[1]; - project.Filters.ExcludedTraits.Add(name, value); - } - else if (optionName == "class") - { - if (option.Value == null) - throw new ArgumentException("missing argument for -class"); - - project.Filters.IncludedClasses.Add(option.Value); - } - else if (optionName == "noclass") - { - if (option.Value == null) - throw new ArgumentException("missing argument for -noclass"); - - project.Filters.ExcludedClasses.Add(option.Value); - } - else if (optionName == "method") - { - if (option.Value == null) - throw new ArgumentException("missing argument for -method"); - - project.Filters.IncludedMethods.Add(option.Value); - } - else if (optionName == "nomethod") - { - if (option.Value == null) - throw new ArgumentException("missing argument for -nomethod"); - - project.Filters.ExcludedMethods.Add(option.Value); - } - else if (optionName == "namespace") - { - if (option.Value == null) - throw new ArgumentException("missing argument for -namespace"); - - project.Filters.IncludedNamespaces.Add(option.Value); - } - else if (optionName == "nonamespace") - { - if (option.Value == null) - throw new ArgumentException("missing argument for -nonamespace"); - - project.Filters.ExcludedNamespaces.Add(option.Value); - } - else if (optionName == "xml") - { - if (option.Value == null) - throw new ArgumentException($"missing filename for {option.Key}"); - - project.Output.Add(optionName, option.Value); - } - } - - return project; - } - - static KeyValuePair PopOption(Stack arguments) - { - var option = arguments.Pop(); - string value = null; - - if (arguments.Count > 0 && !arguments.Peek().StartsWith("-", StringComparison.Ordinal)) - value = arguments.Pop(); - - return new KeyValuePair(option, value); - } - } -} diff --git a/src/Microsoft.DotNet.XUnitRunnerUap/src/DictionaryExtensions.cs b/src/Microsoft.DotNet.XUnitRunnerUap/src/DictionaryExtensions.cs deleted file mode 100644 index ebfdd06f581..00000000000 --- a/src/Microsoft.DotNet.XUnitRunnerUap/src/DictionaryExtensions.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; - -namespace Microsoft.DotNet.XUnitRunnerUap -{ - internal static class DictionaryExtensions - { - public static void Add(this IDictionary> dictionary, TKey key, TValue value) - { - dictionary.GetOrAdd(key).Add(value); - } - - public static TValue GetOrAdd(this IDictionary dictionary, TKey key) - where TValue : new() - { - return dictionary.GetOrAdd(key, () => new TValue()); - } - - public static TValue GetOrAdd(this IDictionary dictionary, TKey key, Func newValue) - { - if (!dictionary.TryGetValue(key, out TValue result)) - { - result = newValue(); - dictionary[key] = result; - } - - return result; - } - } -} diff --git a/src/Microsoft.DotNet.XUnitRunnerUap/src/Microsoft.DotNet.XUnitRunnerUap.csproj b/src/Microsoft.DotNet.XUnitRunnerUap/src/Microsoft.DotNet.XUnitRunnerUap.csproj index f8a680dac51..96cc3969a33 100644 --- a/src/Microsoft.DotNet.XUnitRunnerUap/src/Microsoft.DotNet.XUnitRunnerUap.csproj +++ b/src/Microsoft.DotNet.XUnitRunnerUap/src/Microsoft.DotNet.XUnitRunnerUap.csproj @@ -1,4 +1,4 @@ - + @@ -125,12 +125,46 @@ PackageReference - - - + + CommandLine.cs + + + ConsoleRunner.cs + + + ParallelismOption.cs + + + Program.cs + + + RemoteExecutor.cs + + + Sinks\DiagnosticMessageSink.cs + + + Utility\Transform.cs + + + Utility\TransformFactory.cs + + + Utility\ConsoleRunnerLogger.cs + + + common\ConsoleHelper.cs + + + common\DictionaryExtensions.cs + + + common\Json.cs + + + common\AssemblyResolution\AssemblyHelper.uap.cs + - - @@ -138,6 +172,18 @@ + + HTML.xslt + + + JUnitXml.xslt + + + NUnitXml.xslt + + + xUnit1.xslt + @@ -150,7 +196,7 @@ - 6.2.0-Preview1-26502-02 + 6.2.0-preview1-26926-04 2.4.1-pre.build.4059 @@ -166,4 +212,4 @@ 14.0 - \ No newline at end of file + diff --git a/src/Microsoft.DotNet.XUnitRunnerUap/src/Program.cs b/src/Microsoft.DotNet.XUnitRunnerUap/src/Program.cs deleted file mode 100644 index 6c0ada7b0af..00000000000 --- a/src/Microsoft.DotNet.XUnitRunnerUap/src/Program.cs +++ /dev/null @@ -1,240 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Concurrent; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Threading.Tasks; -using System.Xml.Linq; -using Windows.Storage; -using Xunit; - -namespace Microsoft.DotNet.XUnitRunnerUap -{ - class Program - { - volatile static bool cancel = false; - - static int Main(string[] args) - { - // Handle RemoteExecutor - if (args.Length > 0 && args[0] == "remote") - { - return RemoteExecutor.Execute(args.Skip(1).ToArray()); - } - - if (args.Length == 0 || args[0] == "-?" || args[0] == "/?" || args[0] == "-h" || args[0] == "--help") - { - PrintHeader(); - PrintUsage(); - return 2; - } - - var commandLine = CommandLine.Parse(args); - - Console.CancelKeyPress += (sender, e) => - { - if (!cancel) - { - Console.WriteLine("Canceling... (Press Ctrl+C again to terminate)"); - cancel = true; - e.Cancel = true; - } - }; - - if (commandLine.Debug) - { - Debugger.Launch(); - } - - if (!commandLine.NoLogo) - PrintHeader(); - - var completionMessages = new ConcurrentDictionary(); - var assembliesElement = new XElement("assemblies"); - - int errorCount = 0; - int failCount = 0; - - foreach (var assembly in commandLine.Project.Assemblies) - { - if (cancel) - { - break; - } - - assembly.Configuration.PreEnumerateTheories = false; - assembly.Configuration.DiagnosticMessages |= commandLine.DiagnosticMessages; - assembly.Configuration.AppDomain = AppDomainSupport.Denied; - var discoveryOptions = TestFrameworkOptions.ForDiscovery(assembly.Configuration); - var executionOptions = TestFrameworkOptions.ForExecution(assembly.Configuration); - executionOptions.SetDisableParallelization(true); - - try - { - using (var xunit = new XunitFrontController(AppDomainSupport.Denied, assembly.AssemblyFilename, assembly.ConfigFilename, assembly.Configuration.ShadowCopyOrDefault)) - using (var discoveryVisitor = new TestDiscoveryVisitor()) - { - string assemblyName = Path.GetFileNameWithoutExtension(assembly.AssemblyFilename); - // Discover & filter the tests - Console.WriteLine($"Discovering: {assemblyName}"); - xunit.Find(false, discoveryVisitor, discoveryOptions); - discoveryVisitor.Finished.WaitOne(); - - var testCasesDiscovered = discoveryVisitor.TestCases.Count; - var filteredTestCases = discoveryVisitor.TestCases.Where(commandLine.Project.Filters.Filter).ToList(); - var testCasesToRun = filteredTestCases.Count; - - Console.WriteLine($"Discovered: {assemblyName}"); - - // Run the filtered tests - if (testCasesToRun == 0) - { - Console.WriteLine($"Info: {assemblyName} has no tests to run"); - } - else - { - if (commandLine.Serialize) - { - filteredTestCases = filteredTestCases.Select(xunit.Serialize).Select(xunit.Deserialize).ToList(); - } - - var assemblyElement = new XElement("assembly"); - - StandardUapVisitor resultsVisitor = new StandardUapVisitor(assemblyElement, () => cancel, completionMessages, commandLine.Verbose, commandLine.FailSkips); - - xunit.RunTests(filteredTestCases, resultsVisitor, executionOptions); - - resultsVisitor.Finished.WaitOne(); - - assembliesElement.Add(assemblyElement); - - // Set counters to determine the error code later. - errorCount += resultsVisitor.ExecutionSummary.Errors; - failCount += resultsVisitor.ExecutionSummary.Failed; - - Console.WriteLine($"{Path.GetFileNameWithoutExtension(assembly.AssemblyFilename)} Total: {resultsVisitor.ExecutionSummary.Total}, Errors: {resultsVisitor.ExecutionSummary.Errors}, Failed: {resultsVisitor.ExecutionSummary.Failed}, Skipped: {resultsVisitor.ExecutionSummary.Skipped}, Time: {resultsVisitor.ExecutionSummary.Time}"); - } - } - } - catch (Exception ex) - { - assembliesElement = new XElement("error"); - assembliesElement.Add(ex); - - if (!commandLine.NoColor) - Console.ForegroundColor = ConsoleColor.Red; - - Console.WriteLine($"error: {ex.Message}"); - - if (commandLine.DiagnosticMessages) - { - if (!commandLine.NoColor) - Console.ForegroundColor = ConsoleColor.DarkGray; - - Console.WriteLine(ex.StackTrace); - } - } - finally - { - if (!commandLine.NoColor) - Console.ResetColor(); - - WriteResults(Path.GetFileName(assembly.AssemblyFilename), assembliesElement).GetAwaiter().GetResult(); - } - } - - if (cancel) - return -1073741510; // 0xC000013A: The application terminated as a result of a CTRL+C - - if (commandLine.Wait) - { - Console.WriteLine(); - Console.Write("Press any key to continue..."); - Console.ReadKey(); - Console.WriteLine(); - } - - if (errorCount > 0 || failCount > 0) - return 1; - - return 0; - } - - static async Task WriteResults(string test, XElement data) - { - StorageFolder folder = await KnownFolders.DocumentsLibrary.CreateFolderAsync("TestResults", CreationCollisionOption.OpenIfExists); - StorageFile file = await folder.CreateFileAsync(test + ".xml", CreationCollisionOption.ReplaceExisting); - - using (var stream = await file.OpenStreamForWriteAsync()) - { - data.Save(stream); - stream.Flush(); - } - } - - private static void PrintHeader() - { - var platform = System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription; - var versionAttribute = typeof(Program).Assembly.GetCustomAttribute(); - - Console.WriteLine($"xUnit.net Console Runner v1.0.25 ({IntPtr.Size * 8}-bit {platform})"); - } - - private static void PrintUsage() - { - var executableName = "XUnitRunnerUap"; - - Console.WriteLine("Copyright (C) .NET Foundation."); - Console.WriteLine(); - Console.WriteLine($"usage: {executableName} [options]"); - Console.WriteLine(); - Console.WriteLine("Valid options:"); - Console.WriteLine(" -nologo : do not show the copyright message"); - Console.WriteLine(" -nocolor : do not output results with colors"); - Console.WriteLine(" -failskips : convert skipped tests into failures"); - Console.WriteLine(" -parallel option : set parallelization based on option"); - Console.WriteLine(" : none - turn off all parallelization"); - Console.WriteLine(" : collections - only parallelize collections"); - Console.WriteLine(" : assemblies - only parallelize assemblies"); - Console.WriteLine(" : all - parallelize assemblies & collections"); - Console.WriteLine(" -maxthreads count : maximum thread count for collection parallelization"); - Console.WriteLine(" : default - run with default (1 thread per CPU thread)"); - Console.WriteLine(" : unlimited - run with unbounded thread count"); - Console.WriteLine(" : (number) - limit task thread pool size to 'count'"); - Console.WriteLine(" -wait : wait for input after completion"); - Console.WriteLine(" -diagnostics : enable diagnostics messages for all test assemblies"); - Console.WriteLine(" -debug : launch the debugger to debug the tests"); - Console.WriteLine(" -serialize : serialize all test cases (for diagnostic purposes only)"); - Console.WriteLine(" -verbose : enable verbose messages (track start and finish time)"); - Console.WriteLine(" -trait \"name=value\" : only run tests with matching name/value traits"); - Console.WriteLine(" : if specified more than once, acts as an OR operation"); - Console.WriteLine(" -notrait \"name=value\" : do not run tests with matching name/value traits"); - Console.WriteLine(" : if specified more than once, acts as an AND operation"); - Console.WriteLine(" -method \"name\" : run a given test method (can be fully specified or use a wildcard;"); - Console.WriteLine(" : i.e., 'MyNamespace.MyClass.MyTestMethod' or '*.MyTestMethod')"); - Console.WriteLine(" : if specified more than once, acts as an OR operation"); - Console.WriteLine(" -nomethod \"name\" : do not run a given test method (can be fully specified or use a wildcard;"); - Console.WriteLine(" : i.e., 'MyNamespace.MyClass.MyTestMethod' or '*.MyTestMethod')"); - Console.WriteLine(" : if specified more than once, acts as an AND operation"); - Console.WriteLine(" -class \"name\" : run all methods in a given test class (should be fully"); - Console.WriteLine(" : specified; i.e., 'MyNamespace.MyClass')"); - Console.WriteLine(" : if specified more than once, acts as an OR operation"); - Console.WriteLine(" -noclass \"name\" : do not run any methods in a given test class (should be fully"); - Console.WriteLine(" : specified; i.e., 'MyNamespace.MyClass')"); - Console.WriteLine(" : if specified more than once, acts as an AND operation"); - Console.WriteLine(" -namespace \"name\" : run all methods in a given namespace (i.e.,"); - Console.WriteLine(" : 'MyNamespace.MySubNamespace')"); - Console.WriteLine(" : if specified more than once, acts as an OR operation"); - Console.WriteLine(" -nonamespace \"name\" : do not run any methods in a given namespace (i.e.,"); - Console.WriteLine(" : 'MyNamespace.MySubNamespace')"); - Console.WriteLine(" : if specified more than once, acts as an AND operation"); - Console.WriteLine(" -xml \"name\" : The xml test results file name"); - Console.WriteLine(); - } - } -} diff --git a/src/Microsoft.DotNet.XUnitRunnerUap/src/StandardUapVisitor.cs b/src/Microsoft.DotNet.XUnitRunnerUap/src/StandardUapVisitor.cs deleted file mode 100644 index 5af2dd709eb..00000000000 --- a/src/Microsoft.DotNet.XUnitRunnerUap/src/StandardUapVisitor.cs +++ /dev/null @@ -1,187 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Concurrent; -using System.IO; -using System.Xml.Linq; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.DotNet.XUnitRunnerUap -{ - internal class StandardUapVisitor : XmlTestExecutionVisitor - { - private string _assemblyName; - private readonly ConcurrentDictionary _completionMessages; - private readonly bool _verbose; - private readonly bool _failSkips; - - public StandardUapVisitor(XElement assemblyElement, Func cancelThunk, - ConcurrentDictionary completionMessages, bool verbose, bool failSkips) - : base(assemblyElement, cancelThunk) - { - _completionMessages = completionMessages; - _verbose = verbose; - _failSkips = failSkips; - } - - public ExecutionSummary ExecutionSummary - { - get - { - if (_completionMessages.TryGetValue(_assemblyName, out ExecutionSummary summary)) - { - return summary; - } - - return new ExecutionSummary(); - } - } - - protected override bool Visit(ITestAssemblyStarting assemblyStarting) - { - _assemblyName = Path.GetFileNameWithoutExtension(assemblyStarting.TestAssembly.Assembly.AssemblyPath); - - Console.WriteLine($"Starting: {_assemblyName}"); - - return base.Visit(assemblyStarting); - } - - protected override bool Visit(ITestAssemblyFinished assemblyFinished) - { - // Base class does computation of results, so call it first. - var result = base.Visit(assemblyFinished); - - Console.WriteLine($"Finished: {_assemblyName}"); - - _completionMessages.TryAdd(_assemblyName, new ExecutionSummary - { - Total = assemblyFinished.TestsRun, - Failed = !_failSkips ? assemblyFinished.TestsFailed : assemblyFinished.TestsFailed + assemblyFinished.TestsSkipped, - Skipped = !_failSkips ? assemblyFinished.TestsSkipped : 0, - Time = assemblyFinished.ExecutionTime, - Errors = Errors - }); - - return result; - } - - protected override bool Visit(ITestFailed testFailed) - { - Console.WriteLine($" {XmlEscape(testFailed.Test.DisplayName)} [FAIL]"); - Console.WriteLine($" {ExceptionUtility.CombineMessages(testFailed).Replace(Environment.NewLine, Environment.NewLine + " ")}"); - - WriteStackTrace(ExceptionUtility.CombineStackTraces(testFailed)); - - return base.Visit(testFailed); - } - - protected override bool Visit(ITestPassed testPassed) - { - return base.Visit(testPassed); - } - - protected override bool Visit(ITestSkipped testSkipped) - { - if (_failSkips) - { - return Visit(new TestFailed(testSkipped.Test, 0M, "", new[] { "FAIL_SKIP" }, new[] { testSkipped.Reason }, new[] { "" }, new[] { -1 })); - } - - Console.WriteLine($" {XmlEscape(testSkipped.Test.DisplayName)} [SKIP]"); - Console.WriteLine($" {XmlEscape(testSkipped.Reason)}"); - - return base.Visit(testSkipped); - } - - protected override bool Visit(ITestStarting testStarting) - { - if (_verbose) - { - Console.WriteLine($" {XmlEscape(testStarting.Test.DisplayName)} [STARTING]"); - } - return base.Visit(testStarting); - } - - protected override bool Visit(ITestFinished testFinished) - { - if (_verbose) - { - Console.WriteLine($" {XmlEscape(testFinished.Test.DisplayName)} [FINISHED] Time: {testFinished.ExecutionTime}s"); - } - return base.Visit(testFinished); - } - - protected override bool Visit(IErrorMessage error) - { - WriteError("FATAL", error); - - return base.Visit(error); - } - - protected override bool Visit(ITestAssemblyCleanupFailure cleanupFailure) - { - WriteError($"Test Assembly Cleanup Failure ({cleanupFailure.TestAssembly.Assembly.AssemblyPath})", cleanupFailure); - - return base.Visit(cleanupFailure); - } - - protected override bool Visit(ITestCaseCleanupFailure cleanupFailure) - { - WriteError($"Test Case Cleanup Failure ({cleanupFailure.TestCase.DisplayName})", cleanupFailure); - - return base.Visit(cleanupFailure); - } - - protected override bool Visit(ITestClassCleanupFailure cleanupFailure) - { - WriteError($"Test Class Cleanup Failure ({cleanupFailure.TestClass.Class.Name})", cleanupFailure); - - return base.Visit(cleanupFailure); - } - - protected override bool Visit(ITestCollectionCleanupFailure cleanupFailure) - { - WriteError($"Test Collection Cleanup Failure ({cleanupFailure.TestCollection.DisplayName})", cleanupFailure); - - return base.Visit(cleanupFailure); - } - - protected override bool Visit(ITestCleanupFailure cleanupFailure) - { - WriteError($"Test Cleanup Failure ({cleanupFailure.Test.DisplayName})", cleanupFailure); - - return base.Visit(cleanupFailure); - } - - protected override bool Visit(ITestMethodCleanupFailure cleanupFailure) - { - WriteError($"Test Method Cleanup Failure ({cleanupFailure.TestMethod.Method.Name})", cleanupFailure); - - return base.Visit(cleanupFailure); - } - - protected void WriteError(string failureName, IFailureInformation failureInfo) - { - Console.WriteLine($" [{failureName}] {XmlEscape(failureInfo.ExceptionTypes[0])}"); - Console.WriteLine($" {XmlEscape(ExceptionUtility.CombineMessages(failureInfo))}"); - - WriteStackTrace(ExceptionUtility.CombineStackTraces(failureInfo)); - } - - void WriteStackTrace(string stackTrace) - { - if (string.IsNullOrWhiteSpace(stackTrace)) - return; - - Console.WriteLine(" Stack Trace:"); - - foreach (var stackFrame in stackTrace.Split(new[] { Environment.NewLine }, StringSplitOptions.None)) - { - Console.WriteLine($" {StackFrameTransformer.TransformFrame(stackFrame, Directory.GetCurrentDirectory())}"); - } - } - } -}