From bcd3aa190d93e98cf1f7be95a44956b23b652a16 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sat, 15 Dec 2018 09:53:21 +0100 Subject: [PATCH 01/81] added support for asynchronous package loading (#243) --- .../source.extension.vsixmanifest | 7 +- .../AsyncPackageRegistrationAttribute.cs | 192 ++++++++++++++++++ .../AsyncPackage/ExtensionMethods.cs | 48 +++++ .../AsyncPackage/ProvideAutoLoadAttribute.cs | 118 +++++++++++ .../VsPackage.GTA/VsPackage.GTA.csproj | 103 ++++++---- .../VsPackage.GTA/packages.config | 19 +- .../GoogleTestExtensionOptionsPage.cs | 73 +++++-- 7 files changed, 493 insertions(+), 67 deletions(-) create mode 100644 GoogleTestAdapter/VsPackage.GTA/AsyncPackage/AsyncPackageRegistrationAttribute.cs create mode 100644 GoogleTestAdapter/VsPackage.GTA/AsyncPackage/ExtensionMethods.cs create mode 100644 GoogleTestAdapter/VsPackage.GTA/AsyncPackage/ProvideAutoLoadAttribute.cs diff --git a/GoogleTestAdapter/Packaging.GTA/source.extension.vsixmanifest b/GoogleTestAdapter/Packaging.GTA/source.extension.vsixmanifest index f24a83495..d26420a88 100644 --- a/GoogleTestAdapter/Packaging.GTA/source.extension.vsixmanifest +++ b/GoogleTestAdapter/Packaging.GTA/source.extension.vsixmanifest @@ -11,10 +11,9 @@ Unit Test, C++, Google Test, GoogleTest, GTest, Test Explorer, Testing - - - - + + + diff --git a/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/AsyncPackageRegistrationAttribute.cs b/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/AsyncPackageRegistrationAttribute.cs new file mode 100644 index 000000000..f5b0b9a80 --- /dev/null +++ b/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/AsyncPackageRegistrationAttribute.cs @@ -0,0 +1,192 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.VisualStudio.AsyncPackageHelpers { + + using System; + using System.Globalization; + using System.IO; + using System.ComponentModel; + using System.ComponentModel.Design; + using Microsoft.VisualStudio.Shell; + using Microsoft.VisualStudio.Shell.Interop; + + /// + /// This attribute is defined on a package to get it to be registered. It + /// is internal because packages are meant to be registered, so it is + /// implicit just by having a package in the assembly. + /// + [AttributeUsage(AttributeTargets.Class, Inherited=true, AllowMultiple=false)] + public sealed class AsyncPackageRegistrationAttribute : RegistrationAttribute + { + private RegistrationMethod registrationMethod = RegistrationMethod.Default; + private bool useManagedResources = false; + private bool allowsBackgroundLoad = false; + private string satellitePath = null; + + /// + /// Select between specifying the Codebase entry or the Assembly entry in the registry. + /// This can be overriden during registration + /// + public RegistrationMethod RegisterUsing + { + get + { + return registrationMethod; + } + set + { + registrationMethod = value; + } + } + + /// + /// For managed resources, there should not be a native ui dll registered. + /// + public bool UseManagedResourcesOnly + { + get { return useManagedResources; } + set { useManagedResources = value; } + } + + /// + /// Package is safe to load on a background thread. + /// + public bool AllowsBackgroundLoading + { + get { return allowsBackgroundLoad; } + set { allowsBackgroundLoad = value; } + } + + /// + /// To specify a resource dll located in a different location then the default, + /// set this property. This can be useful if your package is installed in the GAC. + /// If this is not set, the directory where the package is located will be use. + /// + /// Note that the dll should be located at the following path: + /// SatellitePath\lcid\PackageDllNameUI.dll + /// + public string SatellitePath + { + get { return satellitePath; } + set { satellitePath = value; } + } + + private string RegKeyName(RegistrationContext context) + { + return String.Format(CultureInfo.InvariantCulture, "Packages\\{0}", context.ComponentType.GUID.ToString("B")); + } + + /// + /// Called to register this attribute with the given context. The context + /// contains the location where the registration information should be placed. + /// it also contains such as the type being registered, and path information. + /// + /// This method is called both for registration and unregistration. The difference is + /// that unregistering just uses a hive that reverses the changes applied to it. + /// + /// + /// Contains the location where the registration information should be placed. + /// It also contains other information such as the type being registered + /// and path of the assembly. + /// + public override void Register(RegistrationContext context) { + Type t = context.ComponentType; + + Key packageKey = null; + try + { + packageKey = context.CreateKey(RegKeyName(context)); + + //use a friendly description if it exists. + DescriptionAttribute attr = TypeDescriptor.GetAttributes(t)[typeof(DescriptionAttribute)] as DescriptionAttribute; + if (attr != null && !String.IsNullOrEmpty(attr.Description)) { + packageKey.SetValue(string.Empty, attr.Description); + } + else { + packageKey.SetValue(string.Empty, t.Name); + } + + packageKey.SetValue("InprocServer32", context.InprocServerPath); + packageKey.SetValue("Class", t.FullName); + + // If specified on the command line, let the command line option override + if (context.RegistrationMethod != RegistrationMethod.Default) + { + registrationMethod = context.RegistrationMethod; + } + + // Select registration method + switch (registrationMethod) + { + case RegistrationMethod.Assembly: + case RegistrationMethod.Default: + packageKey.SetValue("Assembly", t.Assembly.FullName); + break; + + case RegistrationMethod.CodeBase: + packageKey.SetValue("CodeBase", context.CodeBase); + break; + } + + Key childKey = null; + if (!useManagedResources) + { + try + { + childKey = packageKey.CreateSubkey("SatelliteDll"); + + // Register the satellite dll + string satelliteDllPath; + if (SatellitePath != null) + { + // Use provided path + satelliteDllPath = context.EscapePath(SatellitePath); + } + else + { + // Default to package path + satelliteDllPath = context.ComponentPath; + } + childKey.SetValue("Path", satelliteDllPath); + childKey.SetValue("DllName", String.Format(CultureInfo.InvariantCulture, "{0}UI.dll", Path.GetFileNameWithoutExtension(t.Assembly.ManifestModule.Name))); + } + finally + { + if (childKey != null) + childKey.Close(); + } + } + + if (allowsBackgroundLoad) + { + packageKey.SetValue("AllowsBackgroundLoad", true); + } + + if (typeof(IVsPackageDynamicToolOwner).IsAssignableFrom(context.ComponentType) || + typeof(IVsPackageDynamicToolOwnerEx).IsAssignableFrom(context.ComponentType)) + { + packageKey.SetValue("SupportsDynamicToolOwner", Microsoft.VisualStudio.PlatformUI.Boxes.BooleanTrue); + } + } + finally + { + if (packageKey != null) + packageKey.Close(); + } + } + + /// + /// Unregister this package. + /// + /// + public override void Unregister(RegistrationContext context) + { + context.RemoveKey(RegKeyName(context)); + } + + } +} diff --git a/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/ExtensionMethods.cs b/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/ExtensionMethods.cs new file mode 100644 index 000000000..1fc1376f8 --- /dev/null +++ b/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/ExtensionMethods.cs @@ -0,0 +1,48 @@ +using System; +using System.Runtime.InteropServices; +using Microsoft.VisualStudio.Shell.Interop; +using System.Threading.Tasks; +using Microsoft.VisualStudio.Shell; + +namespace Microsoft.VisualStudio.AsyncPackageHelpers +{ + public static class ExtensionMethods + { + /// + /// Helper method to use async/await with IAsyncServiceProvider implementation + /// + /// IAsyncServciceProvider instance + /// Type of the Visual Studio service requested + /// Service object as type of T + public static async Task GetServiceAsync(this IAsyncServiceProvider asyncServiceProvider, Type serviceType) where T : class + { + T returnValue = null; + + await ThreadHelper.JoinableTaskFactory.RunAsync(async () => + { + object serviceInstance = null; + Guid serviceTypeGuid = serviceType.GUID; + serviceInstance = await asyncServiceProvider.QueryServiceAsync(ref serviceTypeGuid); + + // We have to make sure we are on main UI thread before trying to cast as underlying implementation + // can be an STA COM object and doing a cast would require calling QueryInterface/AddRef marshaling + // to main thread via COM. + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + returnValue = serviceInstance as T; + }); + + return returnValue; + } + + /// + /// Gets if async package is supported in the current instance of Visual Studio + /// + /// an IServiceProvider instance, usually a Package instance + /// true if async packages are supported + public static bool IsAsyncPackageSupported(this IServiceProvider serviceProvider) + { + IAsyncServiceProvider asyncServiceProvider = serviceProvider.GetService(typeof(SAsyncServiceProvider)) as IAsyncServiceProvider; + return asyncServiceProvider != null; + } + } +} \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/ProvideAutoLoadAttribute.cs b/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/ProvideAutoLoadAttribute.cs new file mode 100644 index 000000000..cf0f3103a --- /dev/null +++ b/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/ProvideAutoLoadAttribute.cs @@ -0,0 +1,118 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation, All rights reserved. +// This code sample is provided "AS IS" without warranty of any kind, +// it is not recommended for use in a production environment. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.VisualStudio.AsyncPackageHelpers +{ + + using System; + using System.Globalization; + using Microsoft.VisualStudio.Shell; + + [Flags] + public enum PackageAutoLoadFlags + { + /// + /// Indicates no special auto-load behavior. This is the default flag value if not specified. + /// + None = 0x0, + + /// + /// When set package will not auto load in newer Visual Studio versions with rule based UI contexts + /// + SkipWhenUIContextRulesActive = 0x1, + + /// + /// When set, if the associated package is marked as allowing background loads (via the ), + /// then the package will be loaded asynchronously, in the background, when the associated UI context is triggered. + /// + BackgroundLoad = 0x2 + } + + /// + /// This attribute registers the package as an extender. The GUID passed in determines + /// what is being extended. The attributes on a package do not control the behavior of + /// the package, but they can be used by registration tools to register the proper + /// information with Visual Studio. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] + public sealed class ProvideAutoLoadAttribute : RegistrationAttribute + { + + private Guid loadGuid = Guid.Empty; + + /// + /// Specify that the package should get loaded when this context is active. + /// + /// Context which should trigger the loading of your package. + public ProvideAutoLoadAttribute(string cmdUiContextGuid) : this(cmdUiContextGuid, PackageAutoLoadFlags.None) + { + } + + /// + /// Specify that the package should get loaded when this context is active. + /// + /// Context which should trigger the loading of your package. + public ProvideAutoLoadAttribute(string cmdUiContextGuid, PackageAutoLoadFlags flags = PackageAutoLoadFlags.None) + { + loadGuid = new Guid(cmdUiContextGuid); + Flags = flags; + } + + /// + /// Context Guid which triggers the loading of the package. + /// + public Guid LoadGuid + { + get + { + return loadGuid; + } + } + + /// + /// Specifies the options for package auto load entry + /// + public PackageAutoLoadFlags Flags + { + get; + private set; + } + + /// + /// The reg key name of this AutoLoad. + /// + private string RegKeyName + { + get + { + return string.Format(CultureInfo.InvariantCulture, "AutoLoadPackages\\{0}", loadGuid.ToString("B")); + } + } + + /// + /// Called to register this attribute with the given context. The context + /// contains the location where the registration information should be placed. + /// it also contains such as the type being registered, and path information. + /// + public override void Register(RegistrationContext context) + { + using (Key childKey = context.CreateKey(RegKeyName)) + { + childKey.SetValue(context.ComponentType.GUID.ToString("B"), (int)Flags); + } + } + + /// + /// Unregister this AutoLoad specification. + /// + public override void Unregister(RegistrationContext context) + { + context.RemoveValue(RegKeyName, context.ComponentType.GUID.ToString("B")); + } + } +} diff --git a/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj b/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj index 7f90071d2..6113bd5a3 100644 --- a/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj +++ b/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj @@ -69,6 +69,9 @@ False + + + Component @@ -247,82 +250,92 @@ + + $(NuGetPackages)CommonMark.NET.0.15.1\lib\net45\CommonMark.dll + + ..\..\NuGetPackages\VSSDK.DTE.7.0.4\lib\net20\envdte.dll False - $(NuGetPackages)VSSDK.DTE.7.0.4\lib\net20\envdte.dll - True + False + ..\..\NuGetPackages\VSSDK.DTE.10.10.0.4\lib\net20\envdte100.dll False - $(NuGetPackages)VSSDK.DTE.10.10.0.4\lib\net20\envdte100.dll - True + False + ..\..\NuGetPackages\VSSDK.DTE.8.8.0.4\lib\net20\envdte80.dll False - $(NuGetPackages)VSSDK.DTE.8.8.0.4\lib\net20\envdte80.dll - True + False + ..\..\NuGetPackages\VSSDK.DTE.9.9.0.4\lib\net20\envdte90.dll False - $(NuGetPackages)VSSDK.DTE.9.9.0.4\lib\net20\envdte90.dll - True + False + ..\..\NuGetPackages\VSSDK.DTE.9.9.0.4\lib\net20\envdte90a.dll False - $(NuGetPackages)VSSDK.DTE.9.9.0.4\lib\net20\envdte90a.dll - True - - - $(NuGetPackages)CommonMark.NET.0.15.1\lib\net45\CommonMark.dll + False - - $(NuGetPackages)VSSDK.ComponentModelHost.11.0.4\lib\net45\Microsoft.VisualStudio.ComponentModelHost.dll + + ..\..\NuGetPackages\VSSDK.ComponentModelHost.12.0.4\lib\net45\Microsoft.VisualStudio.ComponentModelHost.dll False - $(NuGetPackages)VSSDK.GraphModel.11.0.4\lib\net45\Microsoft.VisualStudio.GraphModel.dll + ..\..\NuGetPackages\VSSDK.GraphModel.11.0.4\lib\net45\Microsoft.VisualStudio.GraphModel.dll False - $(NuGetPackages)VSSDK.OLE.Interop.7.0.4\lib\net20\Microsoft.VisualStudio.OLE.Interop.dll - True + ..\..\NuGetPackages\VSSDK.OLE.Interop.7.0.4\lib\net20\Microsoft.VisualStudio.OLE.Interop.dll False - - $(NuGetPackages)VSSDK.Shell.11.11.0.0\lib\net45\Microsoft.VisualStudio.Shell.11.0.dll - True + + ..\..\NuGetPackages\VSSDK.Shell.12.12.0.4\lib\net45\Microsoft.VisualStudio.Shell.12.0.dll + False - $(NuGetPackages)VSSDK.Shell.Immutable.10.10.0.4\lib\net40\Microsoft.VisualStudio.Shell.Immutable.10.0.dll - True + ..\..\NuGetPackages\VSSDK.Shell.Immutable.10.10.0.4\lib\net40\Microsoft.VisualStudio.Shell.Immutable.10.0.dll False - $(NuGetPackages)VSSDK.Shell.Immutable.11.11.0.4\lib\net45\Microsoft.VisualStudio.Shell.Immutable.11.0.dll - True + ..\..\NuGetPackages\VSSDK.Shell.Immutable.11.11.0.4\lib\net45\Microsoft.VisualStudio.Shell.Immutable.11.0.dll + False + + + ..\..\NuGetPackages\VSSDK.Shell.Immutable.12.12.0.4\lib\net45\Microsoft.VisualStudio.Shell.Immutable.12.0.dll False - $(NuGetPackages)VSSDK.Shell.Interop.7.0.4\lib\net20\Microsoft.VisualStudio.Shell.Interop.dll - True + ..\..\NuGetPackages\VSSDK.Shell.Interop.7.0.4\lib\net20\Microsoft.VisualStudio.Shell.Interop.dll False - $(NuGetPackages)VSSDK.Shell.Interop.10.10.0.0\lib\net20\Microsoft.VisualStudio.Shell.Interop.10.0.dll + ..\..\NuGetPackages\VSSDK.Shell.Interop.10.10.0.4\lib\net20\Microsoft.VisualStudio.Shell.Interop.10.0.dll + False False - $(NuGetPackages)VSSDK.Shell.Interop.11.11.0.0\lib\net20\Microsoft.VisualStudio.Shell.Interop.11.0.dll + ..\..\NuGetPackages\VSSDK.Shell.Interop.11.11.0.4\lib\net20\Microsoft.VisualStudio.Shell.Interop.11.0.dll + False False + + ..\..\NuGetPackages\VSSDK.Shell.Interop.12.12.0.4\lib\net20\Microsoft.VisualStudio.Shell.Interop.12.0.dll + False + False + + + True + - $(NuGetPackages)VSSDK.Shell.Interop.10.10.0.0\lib\net20\Microsoft.VisualStudio.Shell.Interop.8.0.dll + ..\..\NuGetPackages\VSSDK.Shell.Interop.8.8.0.4\lib\net20\Microsoft.VisualStudio.Shell.Interop.8.0.dll False - $(NuGetPackages)VSSDK.Shell.Interop.10.10.0.0\lib\net20\Microsoft.VisualStudio.Shell.Interop.9.0.dll + ..\..\NuGetPackages\VSSDK.Shell.Interop.9.9.0.4\lib\net20\Microsoft.VisualStudio.Shell.Interop.9.0.dll False @@ -334,29 +347,33 @@ True - $(NuGetPackages)VSSDK.TextManager.Interop.7.0.4\lib\net20\Microsoft.VisualStudio.TextManager.Interop.dll - True + ..\..\NuGetPackages\VSSDK.TextManager.Interop.7.0.4\lib\net20\Microsoft.VisualStudio.TextManager.Interop.dll False + ..\..\NuGetPackages\VSSDK.TextManager.Interop.10.10.0.4\lib\net20\Microsoft.VisualStudio.TextManager.Interop.10.0.dll False - $(NuGetPackages)VSSDK.TextManager.Interop.10.10.0.4\lib\net20\Microsoft.VisualStudio.TextManager.Interop.10.0.dll - True + False - $(NuGetPackages)VSSDK.TextManager.Interop.8.8.0.4\lib\net20\Microsoft.VisualStudio.TextManager.Interop.8.0.dll - True + ..\..\NuGetPackages\VSSDK.TextManager.Interop.8.8.0.4\lib\net20\Microsoft.VisualStudio.TextManager.Interop.8.0.dll + False False - $(NuGetPackages)VSSDK.TextManager.Interop.9.9.0.4\lib\net20\Microsoft.VisualStudio.TextManager.Interop.9.0.dll - True + ..\..\NuGetPackages\VSSDK.TextManager.Interop.9.9.0.4\lib\net20\Microsoft.VisualStudio.TextManager.Interop.9.0.dll + False + + + ..\..\NuGetPackages\VSSDK.Threading.12.0.4\lib\net45\Microsoft.VisualStudio.Threading.dll False + + + ..\..\NuGetPackages\VSSDK.DTE.7.0.4\lib\net20\stdole.dll False - $(NuGetPackages)VSSDK.DTE.7.0.4\lib\net20\stdole.dll - True + False @@ -364,8 +381,12 @@ + + + + diff --git a/GoogleTestAdapter/VsPackage.GTA/packages.config b/GoogleTestAdapter/VsPackage.GTA/packages.config index 5e0560398..cb463d7a3 100644 --- a/GoogleTestAdapter/VsPackage.GTA/packages.config +++ b/GoogleTestAdapter/VsPackage.GTA/packages.config @@ -5,29 +5,34 @@ - - + + - + - - + + - - + + + + + + + \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs index 52bbfe0ed..324174654 100644 --- a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs @@ -17,10 +17,13 @@ using System.Runtime.InteropServices; using System.ServiceModel; using EnvDTE; +using Microsoft.VisualStudio.AsyncPackageHelpers; namespace GoogleTestAdapter.VsPackage { + [AsyncPackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)] + [Microsoft.VisualStudio.AsyncPackageHelpers.ProvideAutoLoad(VSConstants.UICONTEXT.NoSolution_string, PackageAutoLoadFlags.BackgroundLoad)] [PackageRegistration(UseManagedResourcesOnly = true)] [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)] // Info on this package for Help/About [Guid(PackageGuidString)] @@ -28,9 +31,9 @@ namespace GoogleTestAdapter.VsPackage [ProvideOptionPage(typeof(GeneralOptionsDialogPage), OptionsCategoryName, SettingsWrapper.PageGeneralName, 0, 0, true)] [ProvideOptionPage(typeof(ParallelizationOptionsDialogPage), OptionsCategoryName, SettingsWrapper.PageParallelizationName, 0, 0, true)] [ProvideOptionPage(typeof(GoogleTestOptionsDialogPage), OptionsCategoryName, SettingsWrapper.PageGoogleTestName, 0, 0, true)] - [ProvideAutoLoad(UIContextGuids.SolutionExists)] + [Microsoft.VisualStudio.Shell.ProvideAutoLoad(UIContextGuids.SolutionExists)] [ProvideMenuResource("Menus.ctmenu", 1)] - public sealed partial class GoogleTestExtensionOptionsPage : Package, IGoogleTestExtensionOptionsPage, IDisposable + public sealed partial class GoogleTestExtensionOptionsPage : Package, IGoogleTestExtensionOptionsPage, IAsyncLoadablePackageInitialize, IDisposable { private const string PackageGuidString = "e7c90fcb-0943-4908-9ae8-3b6a9d22ec9e"; @@ -45,30 +48,74 @@ public sealed partial class GoogleTestExtensionOptionsPage : Package, IGoogleTes // ReSharper disable once NotAccessedField.Local private DebuggerAttacherServiceHost _debuggerAttacherServiceHost; + private bool _isAsyncLoadSupported; + protected override void Initialize() { base.Initialize(); - var componentModel = (IComponentModel)GetGlobalService(typeof(SComponentModel)); - _globalRunSettings = componentModel.GetService(); + _isAsyncLoadSupported = this.IsAsyncPackageSupported(); + if (!_isAsyncLoadSupported) + { + var componentModel = (IComponentModel) GetGlobalService(typeof(SComponentModel)); + _globalRunSettings = componentModel.GetService(); + DoInitialize(); + } + } - _generalOptions = (GeneralOptionsDialogPage)GetDialogPage(typeof(GeneralOptionsDialogPage)); - _parallelizationOptions = (ParallelizationOptionsDialogPage)GetDialogPage(typeof(ParallelizationOptionsDialogPage)); - _googleTestOptions = (GoogleTestOptionsDialogPage)GetDialogPage(typeof(GoogleTestOptionsDialogPage)); + IVsTask IAsyncLoadablePackageInitialize.Initialize(IAsyncServiceProvider serviceProvider, IProfferAsyncService profferService, + IAsyncProgressCallback progressCallback) + { + if (!_isAsyncLoadSupported) + { + throw new InvalidOperationException("Async Initialize method should not be called when async load is not supported."); + } + + return ThreadHelper.JoinableTaskFactory.RunAsync(async () => + { + var componentModel = await serviceProvider.GetServiceAsync(typeof(SComponentModel)); + _globalRunSettings = componentModel.GetService(); + + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + + DoInitialize(); + + return null; + }).AsVsTask(); + } + + private void DoInitialize() + { + InitializeOptions(); + InitializeCommands(); + InitializeDebuggerAttacherService(); + DisplayReleaseNotesIfNecessary(); + } + + private void InitializeOptions() + { + _generalOptions = (GeneralOptionsDialogPage) GetDialogPage(typeof(GeneralOptionsDialogPage)); + _parallelizationOptions = + (ParallelizationOptionsDialogPage) GetDialogPage(typeof(ParallelizationOptionsDialogPage)); + _googleTestOptions = (GoogleTestOptionsDialogPage) GetDialogPage(typeof(GoogleTestOptionsDialogPage)); _globalRunSettings.RunSettings = GetRunSettingsFromOptionPages(); _generalOptions.PropertyChanged += OptionsChanged; _parallelizationOptions.PropertyChanged += OptionsChanged; _googleTestOptions.PropertyChanged += OptionsChanged; + } + private void InitializeCommands() + { SwitchCatchExceptionsOptionCommand.Initialize(this); SwitchBreakOnFailureOptionCommand.Initialize(this); SwitchParallelExecutionOptionCommand.Initialize(this); SwitchPrintTestOutputOptionCommand.Initialize(this); + } - DisplayReleaseNotesIfNecessary(); - + private void InitializeDebuggerAttacherService() + { var logger = new ActivityLogLogger(this, () => _generalOptions.DebugMode); var debuggerAttacher = new VsDebuggerAttacher(this); _debuggerAttacherServiceHost = new DebuggerAttacherServiceHost(_debuggingNamedPipeId, debuggerAttacher, logger); @@ -104,15 +151,11 @@ protected override void Dispose(bool disposing) try { - // Cannot simply do ".?" because Code Analysis does not understand that. - if (_debuggerAttacherServiceHost != null) - { - _debuggerAttacherServiceHost.Close(); - } + _debuggerAttacherServiceHost?.Close(); } catch (CommunicationException) { - _debuggerAttacherServiceHost.Abort(); + _debuggerAttacherServiceHost?.Abort(); } } base.Dispose(disposing); From bc4b16ebf22fd9d7d38131b0a80263c1eff7dc75 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sun, 3 Feb 2019 09:39:09 +0100 Subject: [PATCH 02/81] removed code duplication of test result parsers, improved tests --- .../Core.Tests/Core.Tests.csproj | 1 - .../StandardOutputTestResultParserTests.cs | 489 --------------- ...mingStandardOutputTestResultParserTests.cs | 564 ++++++++++-------- .../Core/Runners/TestResultCollector.cs | 2 +- .../StandardOutputTestResultParser.cs | 236 +------- ...StreamingStandardOutputTestResultParser.cs | 156 ++++- .../Core/TestResults/XmlTestResultParser.cs | 2 +- 7 files changed, 476 insertions(+), 974 deletions(-) delete mode 100644 GoogleTestAdapter/Core.Tests/TestResults/StandardOutputTestResultParserTests.cs diff --git a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj index 5a26f745f..ed76511a9 100644 --- a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj +++ b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj @@ -97,7 +97,6 @@ - diff --git a/GoogleTestAdapter/Core.Tests/TestResults/StandardOutputTestResultParserTests.cs b/GoogleTestAdapter/Core.Tests/TestResults/StandardOutputTestResultParserTests.cs deleted file mode 100644 index f62145120..000000000 --- a/GoogleTestAdapter/Core.Tests/TestResults/StandardOutputTestResultParserTests.cs +++ /dev/null @@ -1,489 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using FluentAssertions; -using GoogleTestAdapter.DiaResolver; -using GoogleTestAdapter.Model; -using GoogleTestAdapter.Tests.Common; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Moq; -using static GoogleTestAdapter.Tests.Common.TestMetadata.TestCategories; - -namespace GoogleTestAdapter.TestResults -{ - [TestClass] - public class StandardOutputTestResultParserTests : TestsBase - { - private string[] ConsoleOutput1 { get; } = { - @"[==========] Running 3 tests from 1 test case.", - @"[----------] Global test environment set-up.", - @"[----------] 3 tests from TestMath", - @"[ RUN ] TestMath.AddFails", - @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp(6): error: Value of: Add(10, 10)", - @" Actual: 20", - @"Expected: 1000", - @"[ FAILED ] TestMath.AddFails (3 ms)", - @"[ RUN ] TestMath.AddPasses" - }; - - private string[] ConsoleOutput1WithInvalidDuration { get; } = { - @"[==========] Running 3 tests from 1 test case.", - @"[----------] Global test environment set-up.", - @"[----------] 3 tests from TestMath", - @"[ RUN ] TestMath.AddFails", - @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp(6): error: Value of: Add(10, 10)", - @" Actual: 20", - @"Expected: 1000", - @"[ FAILED ] TestMath.AddFails (3 s)" - }; - - private string[] ConsoleOutput1WithThousandsSeparatorInDuration { get; } = { - @"[==========] Running 3 tests from 1 test case.", - @"[----------] Global test environment set-up.", - @"[----------] 3 tests from TestMath", - @"[ RUN ] TestMath.AddFails", - @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp(6): error: Value of: Add(10, 10)", - @" Actual: 20", - @"Expected: 1000", - @"[ FAILED ] TestMath.AddFails (4,656 ms)", - }; - - private string[] ConsoleOutput2 { get; } = { - @"[ OK ] TestMath.AddPasses(0 ms)", - @"[ RUN ] TestMath.Crash", - @"unknown file: error: SEH exception with code 0xc0000005 thrown in the test body.", - }; - - private string[] ConsoleOutput3 { get; } = { - @"[ FAILED ] TestMath.Crash(9 ms)", - @"[----------] 3 tests from TestMath(26 ms total)", - @"", - @"[----------] Global test environment tear-down", - @"[==========] 3 tests from 1 test case ran. (36 ms total)", - @"[ PASSED ] 1 test.", - @"[ FAILED ] 2 tests, listed below:", - @"[ FAILED ] TestMath.AddFails", - @"[ FAILED ] TestMath.Crash", - @"", - @" 2 FAILED TESTS", - @"", - }; - - private string[] ConsoleOutputWithOutputOfExe { get; } = { - @"[==========] Running 1 tests from 1 test case.", - @"[----------] Global test environment set-up.", - @"[----------] 1 tests from TestMath", - @"[ RUN ] TestMath.AddPasses", - @"Some output produced by the exe", - @"[ OK ] TestMath.AddPasses(0 ms)", - @"[----------] 1 tests from TestMath(26 ms total)", - @"", - @"[----------] Global test environment tear-down", - @"[==========] 3 tests from 1 test case ran. (36 ms total)", - @"[ PASSED ] 1 test.", - }; - - private string[] ConsoleOutputWithPrefixingTest { get; } = { - @"[==========] Running 2 tests from 1 test case.", - @"[----------] Global test environment set-up.", - @"[----------] 2 tests from TestMath", - @"[ RUN ] Test.AB", - @"[ OK ] Test.A(0 ms)", - @"[ RUN ] Test.A", - @"[ OK ] Test.A(0 ms)", - @"[----------] 2 tests from TestMath(26 ms total)", - @"", - @"[----------] Global test environment tear-down", - @"[==========] 2 tests from 1 test case ran. (36 ms total)", - @"[ PASSED ] 2 test.", - }; - - /// - /// - /// - private string[] ConsoleOutputWithSkippedTest { get; } = @"[==========] Running 3 tests from 1 test suite. -[----------] Global test environment set-up. -[----------] 3 tests from Test -[ RUN ] Test.Succeed -[ OK ] Test.Succeed (0 ms) -[ RUN ] Test.Skip -[ SKIPPED ] Test.Skip (1 ms) -[ RUN ] Test.Fail -C:\...\test.cpp(14): error: Value of: false - Actual: false -Expected: true -[ FAILED ] Test.Fail (0 ms) -[----------] 3 tests from Test (3 ms total) - -[----------] Global test environment tear-down -[==========] 3 tests from 1 test suite ran. (6 ms total) -[ PASSED ] 1 test. -[ SKIPPED ] 1 test, listed below: -[ SKIPPED ] Test.Skip -[ FAILED ] 1 test, listed below: -[ FAILED ] Test.Fail - - 1 FAILED TEST -".Split('\n'); - - /// - /// - /// - private string[] ConsoleOutputWithSkippedTestAsLastTest { get; } = @"[==========] Running 3 tests from 1 test suite. -[----------] Global test environment set-up. -[----------] 3 tests from Test -[ RUN ] Test.Succeed -[ OK ] Test.Succeed (0 ms) -[ RUN ] Test.Fail -C:\...\test.cpp(14): error: Value of: false - Actual: false -Expected: true -[ FAILED ] Test.Fail (0 ms) -[ RUN ] Test.Skip -[ SKIPPED ] Test.Skip (1 ms) -[----------] 3 tests from Test (3 ms total) - -[----------] Global test environment tear-down -[==========] 3 tests from 1 test suite ran. (6 ms total) -[ PASSED ] 1 test. -[ SKIPPED ] 1 test, listed below: -[ SKIPPED ] Test.Skip -[ FAILED ] 1 test, listed below: -[ FAILED ] Test.Fail - - 1 FAILED TEST -".Split('\n'); - - - private List CrashesImmediately { get; set; } - private List CrashesAfterErrorMsg { get; set; } - private List Complete { get; set; } - private List WrongDurationUnit { get; set; } - private List ThousandsSeparatorInDuration { get; set; } - private List PassingTestProducesConsoleOutput { get; set; } - private List CompleteStandardOutput { get; set; } - - [TestInitialize] - public override void SetUp() - { - base.SetUp(); - - CrashesImmediately = new List(ConsoleOutput1); - - CrashesAfterErrorMsg = new List(ConsoleOutput1); - CrashesAfterErrorMsg.AddRange(ConsoleOutput2); - - Complete = new List(ConsoleOutput1); - Complete.AddRange(ConsoleOutput2); - Complete.AddRange(ConsoleOutput3); - - WrongDurationUnit = new List(ConsoleOutput1WithInvalidDuration); - - ThousandsSeparatorInDuration = new List(ConsoleOutput1WithThousandsSeparatorInDuration); - - PassingTestProducesConsoleOutput = new List(ConsoleOutputWithOutputOfExe); - - CompleteStandardOutput = new List(File.ReadAllLines(TestResources.Tests_ReleaseX64_Output, Encoding.Default)); - } - - - [TestMethod] - [TestCategory(Unit)] - public void GetTestResults_CompleteOutput_ParsedCorrectly() - { - var results = ComputeTestResults(Complete); - - results.Should().HaveCount(3); - - results[0].TestCase.FullyQualifiedName.Should().Be("TestMath.AddFails"); - XmlTestResultParserTests.AssertTestResultIsFailure(results[0]); - results[0].ErrorMessage.Should().NotContain(StandardOutputTestResultParser.CrashText); - results[0].Duration.Should().Be(TimeSpan.FromMilliseconds(3)); - results[0].ErrorStackTrace.Should() - .Contain( - @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp"); - - results[1].TestCase.FullyQualifiedName.Should().Be("TestMath.AddPasses"); - XmlTestResultParserTests.AssertTestResultIsPassed(results[1]); - results[1].Duration.Should().Be(StandardOutputTestResultParser.ShortTestDuration); - - results[2].TestCase.FullyQualifiedName.Should().Be("TestMath.Crash"); - XmlTestResultParserTests.AssertTestResultIsFailure(results[2]); - results[2].ErrorMessage.Should().NotContain(StandardOutputTestResultParser.CrashText); - results[2].Duration.Should().Be(TimeSpan.FromMilliseconds(9)); - } - - [TestMethod] - [TestCategory(Unit)] - public void GetTestResults_OutputWithImmediateCrash_CorrectResultHasCrashText() - { - var results = ComputeTestResults(CrashesImmediately); - - results.Should().HaveCount(2); - - results[0].TestCase.FullyQualifiedName.Should().Be("TestMath.AddFails"); - XmlTestResultParserTests.AssertTestResultIsFailure(results[0]); - results[0].ErrorMessage.Should().NotContain(StandardOutputTestResultParser.CrashText); - results[0].Duration.Should().Be(TimeSpan.FromMilliseconds(3)); - results[0].ErrorStackTrace.Should().Contain(@"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp"); - - results[1].TestCase.FullyQualifiedName.Should().Be("TestMath.AddPasses"); - XmlTestResultParserTests.AssertTestResultIsFailure(results[1]); - results[1].ErrorMessage.Should().Contain(StandardOutputTestResultParser.CrashText); - results[1].ErrorMessage.Should().NotContain("Test output:"); - results[1].Duration.Should().Be(TimeSpan.FromMilliseconds(0)); - } - - [TestMethod] - [TestCategory(Unit)] - public void GetTestResults_OutputWithCrashAfterErrorMessage_CorrectResultHasCrashText() - { - var results = ComputeTestResults(CrashesAfterErrorMsg); - - results.Should().HaveCount(3); - - results[0].TestCase.FullyQualifiedName.Should().Be("TestMath.AddFails"); - XmlTestResultParserTests.AssertTestResultIsFailure(results[0]); - results[0].ErrorMessage.Should().NotContain(StandardOutputTestResultParser.CrashText); - results[0].Duration.Should().Be(TimeSpan.FromMilliseconds(3)); - results[0].ErrorStackTrace.Should().Contain(@"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp"); - - results[1].TestCase.FullyQualifiedName.Should().Be("TestMath.AddPasses"); - XmlTestResultParserTests.AssertTestResultIsPassed(results[1]); - results[1].Duration.Should().Be(StandardOutputTestResultParser.ShortTestDuration); - - results[2].TestCase.FullyQualifiedName.Should().Be("TestMath.Crash"); - XmlTestResultParserTests.AssertTestResultIsFailure(results[2]); - results[2].ErrorMessage.Should().Contain(StandardOutputTestResultParser.CrashText); - results[2].ErrorMessage.Should().Contain("Test output:"); - results[2].ErrorMessage.Should().Contain("unknown file: error: SEH exception with code 0xc0000005 thrown in the test body."); - results[2].Duration.Should().Be(TimeSpan.FromMilliseconds(0)); - } - - [TestMethod] - [TestCategory(Unit)] - public void GetTestResults_OutputWithInvalidDurationUnit_DefaultDurationIsUsedAndWarningIsProduced() - { - var results = ComputeTestResults(WrongDurationUnit); - - results.Should().ContainSingle(); - results[0].TestCase.FullyQualifiedName.Should().Be("TestMath.AddFails"); - results[0].Duration.Should().Be(TimeSpan.FromMilliseconds(1)); - results[0].ErrorStackTrace.Should().Contain(@"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp"); - - MockLogger.Verify(l => l.LogWarning( - It.Is(s => s.Contains("'[ FAILED ] TestMath.AddFails (3 s)'"))), Times.Exactly(1)); - } - - [TestMethod] - [TestCategory(Unit)] - public void GetTestResults_OutputWithThousandsSeparatorInDuration_ParsedCorrectly() - { - CultureInfo currentCulture = Thread.CurrentThread.CurrentCulture; - Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en-US"); - try - { - var results = ComputeTestResults(ThousandsSeparatorInDuration); - - results.Should().ContainSingle(); - results[0].TestCase.FullyQualifiedName.Should().Be("TestMath.AddFails"); - results[0].Duration.Should().Be(TimeSpan.FromMilliseconds(4656)); - } - finally - { - Thread.CurrentThread.CurrentCulture = currentCulture; - } - } - - [TestMethod] - [TestCategory(Unit)] - public void GetTestResults_OutputWithConsoleOutput_ConsoleOutputIsIgnored() - { - var results = ComputeTestResults(PassingTestProducesConsoleOutput); - - results.Should().ContainSingle(); - results[0].TestCase.FullyQualifiedName.Should().Be("TestMath.AddPasses"); - XmlTestResultParserTests.AssertTestResultIsPassed(results[0]); - } - - [TestMethod] - [TestCategory(Unit)] - public void GetTestResults_OutputWithPrefixingTest_BothTestsAreFound() - { - var cases = new List - { - TestDataCreator.ToTestCase("Test.AB", TestDataCreator.DummyExecutable, - @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp"), - TestDataCreator.ToTestCase("Test.A", TestDataCreator.DummyExecutable, - @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp") - }; - - var results = new StandardOutputTestResultParser(cases, ConsoleOutputWithPrefixingTest, TestEnvironment.Logger) - .GetTestResults(); - - results.Should().HaveCount(2); - results[0].TestCase.FullyQualifiedName.Should().Be("Test.AB"); - XmlTestResultParserTests.AssertTestResultIsPassed(results[0]); - results[1].TestCase.FullyQualifiedName.Should().Be("Test.A"); - XmlTestResultParserTests.AssertTestResultIsPassed(results[1]); - } - - [TestMethod] - [TestCategory(Unit)] - public void GetTestResults_OutputWithSkippedTest_AllResultsAreFound() - { - var cases = new List - { - TestDataCreator.ToTestCase("Test.Succeed", TestDataCreator.DummyExecutable, @"c:\somepath\source.cpp"), - TestDataCreator.ToTestCase("Test.Skip", TestDataCreator.DummyExecutable, @"c:\somepath\source.cpp"), - TestDataCreator.ToTestCase("Test.Fail", TestDataCreator.DummyExecutable, @"c:\somepath\source.cpp"), - }; - - var results = new StandardOutputTestResultParser(cases, ConsoleOutputWithSkippedTest, TestEnvironment.Logger).GetTestResults(); - - results.Should().HaveCount(3); - - var result = results[0]; - result.TestCase.FullyQualifiedName.Should().Be("Test.Succeed"); - XmlTestResultParserTests.AssertTestResultIsPassed(result); - - result = results[1]; - result.TestCase.FullyQualifiedName.Should().Be("Test.Skip"); - XmlTestResultParserTests.AssertTestResultIsSkipped(result); - - result = results[2]; - result.TestCase.FullyQualifiedName.Should().Be("Test.Fail"); - XmlTestResultParserTests.AssertTestResultIsFailure(result); - } - - [TestMethod] - [TestCategory(Unit)] - public void GetTestResults_OutputWithSkippedTestAsLastTest_AllResultsAreFound() - { - var cases = new List - { - TestDataCreator.ToTestCase("Test.Succeed", TestDataCreator.DummyExecutable, @"c:\somepath\source.cpp"), - TestDataCreator.ToTestCase("Test.Skip", TestDataCreator.DummyExecutable, @"c:\somepath\source.cpp"), - TestDataCreator.ToTestCase("Test.Fail", TestDataCreator.DummyExecutable, @"c:\somepath\source.cpp"), - }; - - var results = new StandardOutputTestResultParser(cases, ConsoleOutputWithSkippedTestAsLastTest, TestEnvironment.Logger).GetTestResults(); - - results.Should().HaveCount(3); - - var result = results[0]; - result.TestCase.FullyQualifiedName.Should().Be("Test.Succeed"); - XmlTestResultParserTests.AssertTestResultIsPassed(result); - - result = results[1]; - result.TestCase.FullyQualifiedName.Should().Be("Test.Fail"); - XmlTestResultParserTests.AssertTestResultIsFailure(result); - - result = results[2]; - result.TestCase.FullyQualifiedName.Should().Be("Test.Skip"); - XmlTestResultParserTests.AssertTestResultIsSkipped(result); - } - - [TestMethod] - [TestCategory(Unit)] - public void OutputHandling_OutputManyLinesWithNewlines_IsParsedCorrectly() - { - var results = GetTestResultsFromCompleteOutputFile(); - - var testResult = results.Single(tr => tr.DisplayName == "OutputHandling.Output_ManyLinesWithNewlines"); - var expectedErrorMessage = - "before test 1\nbefore test 2\nExpected: 1\nTo be equal to: 2\ntest output\nafter test 1\nafter test 2"; - testResult.ErrorMessage.Should().Be(expectedErrorMessage); - } - - [TestMethod] - [TestCategory(Unit)] - public void OutputHandling_OutputOneLineWithNewlines_IsParsedCorrectly() - { - var results = GetTestResultsFromCompleteOutputFile(); - - var testResult = results.Single(tr => tr.DisplayName == "OutputHandling.Output_OneLineWithNewlines"); - var expectedErrorMessage = - "before test\nExpected: 1\nTo be equal to: 2\ntest output\nafter test"; - testResult.ErrorMessage.Should().Be(expectedErrorMessage); - } - - [TestMethod] - [TestCategory(Unit)] - public void OutputHandling_OutputOneLine_IsParsedCorrectly() - { - var results = GetTestResultsFromCompleteOutputFile(); - - var testResult = results.Single(tr => tr.DisplayName == "OutputHandling.Output_OneLine"); - var expectedErrorMessage = - "before test\nExpected: 1\nTo be equal to: 2\ntest output\nafter test"; - testResult.ErrorMessage.Should().Be(expectedErrorMessage); - } - - [TestMethod] - [TestCategory(Unit)] - public void OutputHandling_ManyLinesWithNewlines_IsParsedCorrectly() - { - var results = GetTestResultsFromCompleteOutputFile(); - - var testResult = results.Single(tr => tr.DisplayName == "OutputHandling.ManyLinesWithNewlines"); - var expectedErrorMessage = - "before test 1\nbefore test 2\nExpected: 1\nTo be equal to: 2\nafter test 1\nafter test 2"; - testResult.ErrorMessage.Should().Be(expectedErrorMessage); - } - - [TestMethod] - [TestCategory(Unit)] - public void OutputHandling_OneLineWithNewlines_IsParsedCorrectly() - { - var results = GetTestResultsFromCompleteOutputFile(); - - var testResult = results.Single(tr => tr.DisplayName == "OutputHandling.Output_OneLineWithNewlines"); - var expectedErrorMessage = - "before test\nExpected: 1\nTo be equal to: 2\ntest output\nafter test"; - testResult.ErrorMessage.Should().Be(expectedErrorMessage); - } - - [TestMethod] - [TestCategory(Unit)] - public void OutputHandling_OneLine_IsParsedCorrectly() - { - var results = GetTestResultsFromCompleteOutputFile(); - - var testResult = results.Single(tr => tr.DisplayName == "OutputHandling.OneLine"); - var expectedErrorMessage = - "before test\nExpected: 1\nTo be equal to: 2\nafter test"; - testResult.ErrorMessage.Should().Be(expectedErrorMessage); - } - - private IList GetTestResultsFromCompleteOutputFile() - { - var testCases = new GoogleTestDiscoverer(MockLogger.Object, MockOptions.Object) - .GetTestsFromExecutable(TestResources.Tests_ReleaseX64); - return new StandardOutputTestResultParser(testCases, CompleteStandardOutput, MockLogger.Object) - .GetTestResults(); - } - - - private IList ComputeTestResults(List consoleOutput) - { - var cases = new List - { - TestDataCreator.ToTestCase("TestMath.AddFails", TestDataCreator.DummyExecutable, - @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp"), - TestDataCreator.ToTestCase("TestMath.Crash", TestDataCreator.DummyExecutable, - @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp"), - TestDataCreator.ToTestCase("TestMath.AddPasses", TestDataCreator.DummyExecutable, - @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp") - }; - var parser = new StandardOutputTestResultParser(cases, consoleOutput, TestEnvironment.Logger); - return parser.GetTestResults(); - } - - } - -} \ No newline at end of file diff --git a/GoogleTestAdapter/Core.Tests/TestResults/StreamingStandardOutputTestResultParserTests.cs b/GoogleTestAdapter/Core.Tests/TestResults/StreamingStandardOutputTestResultParserTests.cs index b2fa5ac32..c356ea0d1 100644 --- a/GoogleTestAdapter/Core.Tests/TestResults/StreamingStandardOutputTestResultParserTests.cs +++ b/GoogleTestAdapter/Core.Tests/TestResults/StreamingStandardOutputTestResultParserTests.cs @@ -17,210 +17,48 @@ namespace GoogleTestAdapter.TestResults [TestClass] public class StreamingStandardOutputTestResultParserTests : TestsBase { - private string[] ConsoleOutput1 { get; } = { - @"[==========] Running 3 tests from 1 test case.", - @"[----------] Global test environment set-up.", - @"[----------] 3 tests from TestMath", - @"[ RUN ] TestMath.AddFails", - @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp(6): error: Value of: Add(10, 10)", - @" Actual: 20", - @"Expected: 1000", - @"[ FAILED ] TestMath.AddFails (3 ms)", - @"[ RUN ] TestMath.AddPasses" - }; - - private string[] ConsoleOutput1WithInvalidDuration { get; } = { - @"[==========] Running 3 tests from 1 test case.", - @"[----------] Global test environment set-up.", - @"[----------] 3 tests from TestMath", - @"[ RUN ] TestMath.AddFails", - @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp(6): error: Value of: Add(10, 10)", - @" Actual: 20", - @"Expected: 1000", - @"[ FAILED ] TestMath.AddFails (3 s)" - }; - - private string[] ConsoleOutput1WithThousandsSeparatorInDuration { get; } = { - @"[==========] Running 3 tests from 1 test case.", - @"[----------] Global test environment set-up.", - @"[----------] 3 tests from TestMath", - @"[ RUN ] TestMath.AddFails", - @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp(6): error: Value of: Add(10, 10)", - @" Actual: 20", - @"Expected: 1000", - @"[ FAILED ] TestMath.AddFails (4,656 ms)", - }; - - private string[] ConsoleOutput2 { get; } = { - @"[ OK ] TestMath.AddPasses(0 ms)", - @"[ RUN ] TestMath.Crash", - @"unknown file: error: SEH exception with code 0xc0000005 thrown in the test body.", - }; - - private string[] ConsoleOutput2WithPrefixingOutput { get; } = { - @"DummyOutput[ OK ] TestMath.AddPasses(0 ms)", - @"[ RUN ] TestMath.Crash", - @"unknown file: error: SEH exception with code 0xc0000005 thrown in the test body.", - }; - - private string[] ConsoleOutput2WithPrefixingOutputAndFailing { get; } = { - @"DummyOutput[ FAILED ] TestMath.AddPasses(0 ms)", - @"[ RUN ] TestMath.Crash", - @"unknown file: error: SEH exception with code 0xc0000005 thrown in the test body.", - }; - - private string[] ConsoleOutput3 { get; } = { - @"[ FAILED ] TestMath.Crash(9 ms)", - @"[----------] 3 tests from TestMath(26 ms total)", - @"", - @"[----------] Global test environment tear-down", - @"[==========] 3 tests from 1 test case ran. (36 ms total)", - @"[ PASSED ] 1 test.", - @"[ FAILED ] 2 tests, listed below:", - @"[ FAILED ] TestMath.AddFails", - @"[ FAILED ] TestMath.Crash", - @"", - @" 2 FAILED TESTS", - @"", - }; - - private string[] ConsoleOutputWithOutputOfExe { get; } = { - @"[==========] Running 1 tests from 1 test case.", - @"[----------] Global test environment set-up.", - @"[----------] 1 tests from TestMath", - @"[ RUN ] TestMath.AddPasses", - @"Some output produced by the exe", - @"[ OK ] TestMath.AddPasses(0 ms)", - @"[----------] 1 tests from TestMath(26 ms total)", - @"", - @"[----------] Global test environment tear-down", - @"[==========] 3 tests from 1 test case ran. (36 ms total)", - @"[ PASSED ] 1 test.", - }; - - private string[] ConsoleOutputWithPrefixingTest { get; } = { - @"[==========] Running 2 tests from 1 test case.", - @"[----------] Global test environment set-up.", - @"[----------] 2 tests from TestMath", - @"[ RUN ] Test.AB", - @"[ OK ] Test.A(0 ms)", - @"[ RUN ] Test.A", - @"[ OK ] Test.A(0 ms)", - @"[----------] 2 tests from TestMath(26 ms total)", - @"", - @"[----------] Global test environment tear-down", - @"[==========] 2 tests from 1 test case ran. (36 ms total)", - @"[ PASSED ] 2 test.", - }; - - /// - /// - /// - private string[] ConsoleOutputWithSkippedTest { get; } = @"[==========] Running 3 tests from 1 test suite. -[----------] Global test environment set-up. -[----------] 3 tests from Test -[ RUN ] Test.Succeed -[ OK ] Test.Succeed (0 ms) -[ RUN ] Test.Skip -[ SKIPPED ] Test.Skip (1 ms) -[ RUN ] Test.Fail -C:\...\test.cpp(14): error: Value of: false - Actual: false -Expected: true -[ FAILED ] Test.Fail (0 ms) -[----------] 3 tests from Test (3 ms total) - -[----------] Global test environment tear-down -[==========] 3 tests from 1 test suite ran. (6 ms total) -[ PASSED ] 1 test. -[ SKIPPED ] 1 test, listed below: -[ SKIPPED ] Test.Skip -[ FAILED ] 1 test, listed below: -[ FAILED ] Test.Fail - - 1 FAILED TEST -".Split('\n'); - - /// - /// - /// - private string[] ConsoleOutputWithSkippedTestAsLastTest { get; } = @"[==========] Running 3 tests from 1 test suite. -[----------] Global test environment set-up. -[----------] 3 tests from Test -[ RUN ] Test.Succeed -[ OK ] Test.Succeed (0 ms) -[ RUN ] Test.Fail -C:\...\test.cpp(14): error: Value of: false - Actual: false -Expected: true -[ FAILED ] Test.Fail (0 ms) -[ RUN ] Test.Skip -[ SKIPPED ] Test.Skip (1 ms) -[----------] 3 tests from Test (3 ms total) - -[----------] Global test environment tear-down -[==========] 3 tests from 1 test suite ran. (6 ms total) -[ PASSED ] 1 test. -[ SKIPPED ] 1 test, listed below: -[ SKIPPED ] Test.Skip -[ FAILED ] 1 test, listed below: -[ FAILED ] Test.Fail - - 1 FAILED TEST -".Split('\n'); - - - private List CrashesImmediately { get; set; } - private List CrashesAfterErrorMsg { get; set; } - private List Complete { get; set; } - private List WrongDurationUnit { get; set; } - private List ThousandsSeparatorInDuration { get; set; } - private List PassingTestProducesConsoleOutput { get; set; } - private List WithPrefixingOutputPassing { get; set; } - private List WithPrefixingOutputFailing { get; set; } - private List CompleteStandardOutput { get; set; } - - [TestInitialize] - public override void SetUp() - { - base.SetUp(); - - CrashesImmediately = new List(ConsoleOutput1); - - CrashesAfterErrorMsg = new List(ConsoleOutput1); - CrashesAfterErrorMsg.AddRange(ConsoleOutput2); - - Complete = new List(ConsoleOutput1); - Complete.AddRange(ConsoleOutput2); - Complete.AddRange(ConsoleOutput3); - - WrongDurationUnit = new List(ConsoleOutput1WithInvalidDuration); - - ThousandsSeparatorInDuration = new List(ConsoleOutput1WithThousandsSeparatorInDuration); - - PassingTestProducesConsoleOutput = new List(ConsoleOutputWithOutputOfExe); - - WithPrefixingOutputFailing = new List(ConsoleOutput1); - WithPrefixingOutputFailing.AddRange(ConsoleOutput2WithPrefixingOutputAndFailing); - - WithPrefixingOutputPassing = new List(ConsoleOutput1); - WithPrefixingOutputPassing.AddRange(ConsoleOutput2WithPrefixingOutput); - - CompleteStandardOutput = new List(File.ReadAllLines(TestResources.Tests_ReleaseX64_Output, Encoding.Default)); - } - - [TestMethod] [TestCategory(Unit)] public void GetTestResults_CompleteOutput_ParsedCorrectly() { - IList results = ComputeTestResults(Complete); + string[] consoleOutput = { + @"[==========] Running 3 tests from 1 test case.", + @"[----------] Global test environment set-up.", + @"[----------] 3 tests from TestMath", + @"[ RUN ] TestMath.AddFails", + @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp(6): error: Value of: Add(10, 10)", + @" Actual: 20", + @"Expected: 1000", + @"[ FAILED ] TestMath.AddFails (3 ms)", + @"[ RUN ] TestMath.AddPasses", + @"[ OK ] TestMath.AddPasses(0 ms)", + @"[ RUN ] TestMath.Crash", + @"unknown file: error: SEH exception with code 0xc0000005 thrown in the test body.", + @"[ FAILED ] TestMath.Crash(9 ms)", + @"[----------] 3 tests from TestMath(26 ms total)", + @"", + @"[----------] Global test environment tear-down", + @"[==========] 3 tests from 1 test case ran. (36 ms total)", + @"[ PASSED ] 1 test.", + @"[ FAILED ] 2 tests, listed below:", + @"[ FAILED ] TestMath.AddFails", + @"[ FAILED ] TestMath.Crash", + @"", + @" 2 FAILED TESTS", + @"", + }; + var cases = GetTestCases(); + + var parser = new StreamingStandardOutputTestResultParser(cases, MockLogger.Object, MockFrameworkReporter.Object); + consoleOutput.ToList().ForEach(parser.ReportLine); + parser.Flush(); + IList results = parser.TestResults; results.Should().HaveCount(3); results[0].TestCase.FullyQualifiedName.Should().Be("TestMath.AddFails"); XmlTestResultParserTests.AssertTestResultIsFailure(results[0]); - results[0].ErrorMessage.Should().NotContain(StandardOutputTestResultParser.CrashText); + results[0].ErrorMessage.Should().NotContain(StreamingStandardOutputTestResultParser.CrashText); results[0].Duration.Should().Be(TimeSpan.FromMilliseconds(3)); results[0].ErrorStackTrace.Should() .Contain( @@ -228,93 +66,191 @@ public void GetTestResults_CompleteOutput_ParsedCorrectly() results[1].TestCase.FullyQualifiedName.Should().Be("TestMath.AddPasses"); XmlTestResultParserTests.AssertTestResultIsPassed(results[1]); - results[1].Duration.Should().Be(StandardOutputTestResultParser.ShortTestDuration); + results[1].Duration.Should().Be(StreamingStandardOutputTestResultParser.ShortTestDuration); results[2].TestCase.FullyQualifiedName.Should().Be("TestMath.Crash"); XmlTestResultParserTests.AssertTestResultIsFailure(results[2]); - results[2].ErrorMessage.Should().NotContain(StandardOutputTestResultParser.CrashText); + results[2].ErrorMessage.Should().NotContain(StreamingStandardOutputTestResultParser.CrashText); results[2].Duration.Should().Be(TimeSpan.FromMilliseconds(9)); + + CheckStandardOutputResultParser(cases, consoleOutput, results, parser.CrashedTestCase); } [TestMethod] [TestCategory(Unit)] public void GetTestResults_OutputWithImmediateCrash_CorrectResultHasCrashText() { - IList results = ComputeTestResults(CrashesImmediately); + string[] consoleOutput = { + @"[==========] Running 3 tests from 1 test case.", + @"[----------] Global test environment set-up.", + @"[----------] 3 tests from TestMath", + @"[ RUN ] TestMath.AddFails", + @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp(6): error: Value of: Add(10, 10)", + @" Actual: 20", + @"Expected: 1000", + @"[ FAILED ] TestMath.AddFails (3 ms)", + @"[ RUN ] TestMath.AddPasses" + }; + var cases = GetTestCases(); + + var parser = new StreamingStandardOutputTestResultParser(cases, MockLogger.Object, MockFrameworkReporter.Object); + consoleOutput.ToList().ForEach(parser.ReportLine); + parser.Flush(); + IList results = parser.TestResults; results.Should().HaveCount(2); results[0].TestCase.FullyQualifiedName.Should().Be("TestMath.AddFails"); XmlTestResultParserTests.AssertTestResultIsFailure(results[0]); - results[0].ErrorMessage.Should().NotContain(StandardOutputTestResultParser.CrashText); + results[0].ErrorMessage.Should().NotContain(StreamingStandardOutputTestResultParser.CrashText); results[0].Duration.Should().Be(TimeSpan.FromMilliseconds(3)); results[0].ErrorStackTrace.Should().Contain(@"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp"); results[1].TestCase.FullyQualifiedName.Should().Be("TestMath.AddPasses"); XmlTestResultParserTests.AssertTestResultIsFailure(results[1]); - results[1].ErrorMessage.Should().Contain(StandardOutputTestResultParser.CrashText); + results[1].ErrorMessage.Should().Contain(StreamingStandardOutputTestResultParser.CrashText); results[1].ErrorMessage.Should().NotContain("Test output:"); results[1].Duration.Should().Be(TimeSpan.FromMilliseconds(0)); + + CheckStandardOutputResultParser(cases, consoleOutput, results, parser.CrashedTestCase); } [TestMethod] [TestCategory(Unit)] public void GetTestResults_OutputWithCrashAfterErrorMessage_CorrectResultHasCrashText() { - IList results = ComputeTestResults(CrashesAfterErrorMsg); + string[] consoleOutput = { + @"[==========] Running 3 tests from 1 test case.", + @"[----------] Global test environment set-up.", + @"[----------] 3 tests from TestMath", + @"[ RUN ] TestMath.AddFails", + @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp(6): error: Value of: Add(10, 10)", + @" Actual: 20", + @"Expected: 1000", + @"[ FAILED ] TestMath.AddFails (3 ms)", + @"[ RUN ] TestMath.AddPasses", + @"[ OK ] TestMath.AddPasses(0 ms)", + @"[ RUN ] TestMath.Crash", + @"unknown file: error: SEH exception with code 0xc0000005 thrown in the test body.", + }; + var cases = GetTestCases(); + + var parser = new StreamingStandardOutputTestResultParser(cases, MockLogger.Object, MockFrameworkReporter.Object); + consoleOutput.ToList().ForEach(parser.ReportLine); + parser.Flush(); + IList results = parser.TestResults; results.Should().HaveCount(3); results[0].TestCase.FullyQualifiedName.Should().Be("TestMath.AddFails"); XmlTestResultParserTests.AssertTestResultIsFailure(results[0]); - results[0].ErrorMessage.Should().NotContain(StandardOutputTestResultParser.CrashText); + results[0].ErrorMessage.Should().NotContain(StreamingStandardOutputTestResultParser.CrashText); results[0].Duration.Should().Be(TimeSpan.FromMilliseconds(3)); results[0].ErrorStackTrace.Should().Contain(@"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp"); results[1].TestCase.FullyQualifiedName.Should().Be("TestMath.AddPasses"); XmlTestResultParserTests.AssertTestResultIsPassed(results[1]); - results[1].Duration.Should().Be(StandardOutputTestResultParser.ShortTestDuration); + results[1].Duration.Should().Be(StreamingStandardOutputTestResultParser.ShortTestDuration); results[2].TestCase.FullyQualifiedName.Should().Be("TestMath.Crash"); XmlTestResultParserTests.AssertTestResultIsFailure(results[2]); - results[2].ErrorMessage.Should().Contain(StandardOutputTestResultParser.CrashText); + results[2].ErrorMessage.Should().Contain(StreamingStandardOutputTestResultParser.CrashText); results[2].ErrorMessage.Should().Contain("Test output:"); results[2].ErrorMessage.Should().Contain("unknown file: error: SEH exception with code 0xc0000005 thrown in the test body."); results[2].Duration.Should().Be(TimeSpan.FromMilliseconds(0)); + + CheckStandardOutputResultParser(cases, consoleOutput, results, parser.CrashedTestCase); } [TestMethod] [TestCategory(Unit)] public void GetTestResults_OutputWithPrefixedPassedLine_PassingTestIsRecognized() { - IList results = ComputeTestResults(WithPrefixingOutputPassing); + string[] consoleOutput = { + @"[==========] Running 3 tests from 1 test case.", + @"[----------] Global test environment set-up.", + @"[----------] 3 tests from TestMath", + @"[ RUN ] TestMath.AddFails", + @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp(6): error: Value of: Add(10, 10)", + @" Actual: 20", + @"Expected: 1000", + @"[ FAILED ] TestMath.AddFails (3 ms)", + @"[ RUN ] TestMath.AddPasses", + @"DummyOutput[ OK ] TestMath.AddPasses(0 ms)", + @"[ RUN ] TestMath.Crash", + @"unknown file: error: SEH exception with code 0xc0000005 thrown in the test body.", + }; + var cases = GetTestCases(); + + var parser = new StreamingStandardOutputTestResultParser(cases, MockLogger.Object, MockFrameworkReporter.Object); + consoleOutput.ToList().ForEach(parser.ReportLine); + parser.Flush(); + IList results = parser.TestResults; results.Should().HaveCount(3); results[1].TestCase.FullyQualifiedName.Should().Be("TestMath.AddPasses"); XmlTestResultParserTests.AssertTestResultIsPassed(results[1]); - results[1].Duration.Should().Be(StandardOutputTestResultParser.ShortTestDuration); + results[1].Duration.Should().Be(StreamingStandardOutputTestResultParser.ShortTestDuration); + + CheckStandardOutputResultParser(cases, consoleOutput, results, parser.CrashedTestCase); } [TestMethod] [TestCategory(Unit)] public void GetTestResults_OutputWithPrefixedFailedLine_FailingTestIsRecognized() { - IList results = ComputeTestResults(WithPrefixingOutputFailing); + string[] consoleOutput = { + @"[==========] Running 3 tests from 1 test case.", + @"[----------] Global test environment set-up.", + @"[----------] 3 tests from TestMath", + @"[ RUN ] TestMath.AddFails", + @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp(6): error: Value of: Add(10, 10)", + @" Actual: 20", + @"Expected: 1000", + @"[ FAILED ] TestMath.AddFails (3 ms)", + @"[ RUN ] TestMath.AddPasses", + @"DummyOutput[ FAILED ] TestMath.AddPasses(0 ms)", + @"[ RUN ] TestMath.Crash", + @"unknown file: error: SEH exception with code 0xc0000005 thrown in the test body.", + }; + var cases = GetTestCases(); + + var parser = new StreamingStandardOutputTestResultParser(cases, MockLogger.Object, MockFrameworkReporter.Object); + consoleOutput.ToList().ForEach(parser.ReportLine); + parser.Flush(); + IList results = parser.TestResults; results.Should().HaveCount(3); results[1].TestCase.FullyQualifiedName.Should().Be("TestMath.AddPasses"); XmlTestResultParserTests.AssertTestResultIsFailure(results[1]); results[1].ErrorMessage.Should().Contain("DummyOutput"); - results[1].Duration.Should().Be(StandardOutputTestResultParser.ShortTestDuration); + results[1].Duration.Should().Be(StreamingStandardOutputTestResultParser.ShortTestDuration); + + CheckStandardOutputResultParser(cases, consoleOutput, results, parser.CrashedTestCase); } [TestMethod] [TestCategory(Unit)] public void GetTestResults_OutputWithInvalidDurationUnit_DefaultDurationIsUsedAndWarningIsProduced() { - IList results = ComputeTestResults(WrongDurationUnit); + string[] consoleOutput = { + @"[==========] Running 3 tests from 1 test case.", + @"[----------] Global test environment set-up.", + @"[----------] 3 tests from TestMath", + @"[ RUN ] TestMath.AddFails", + @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp(6): error: Value of: Add(10, 10)", + @" Actual: 20", + @"Expected: 1000", + @"[ FAILED ] TestMath.AddFails (3 s)" + }; + var cases = GetTestCases(); + + var parser = new StreamingStandardOutputTestResultParser(cases, MockLogger.Object, MockFrameworkReporter.Object); + consoleOutput.ToList().ForEach(parser.ReportLine); + parser.Flush(); + IList results = parser.TestResults; results.Should().ContainSingle(); results[0].TestCase.FullyQualifiedName.Should().Be("TestMath.AddFails"); @@ -323,6 +259,8 @@ public void GetTestResults_OutputWithInvalidDurationUnit_DefaultDurationIsUsedAn MockLogger.Verify(l => l.LogWarning( It.Is(s => s.Contains("'[ FAILED ] TestMath.AddFails (3 s)'"))), Times.Exactly(1)); + + CheckStandardOutputResultParser(cases, consoleOutput, results, parser.CrashedTestCase); } [TestMethod] @@ -333,11 +271,28 @@ public void GetTestResults_OutputWithThousandsSeparatorInDuration_ParsedCorrectl Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en-US"); try { - IList results = ComputeTestResults(ThousandsSeparatorInDuration); + string[] consoleOutput = { + @"[==========] Running 3 tests from 1 test case.", + @"[----------] Global test environment set-up.", + @"[----------] 3 tests from TestMath", + @"[ RUN ] TestMath.AddFails", + @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp(6): error: Value of: Add(10, 10)", + @" Actual: 20", + @"Expected: 1000", + @"[ FAILED ] TestMath.AddFails (4,656 ms)", + }; + var cases = GetTestCases(); + + var parser = new StreamingStandardOutputTestResultParser(cases, MockLogger.Object, MockFrameworkReporter.Object); + consoleOutput.ToList().ForEach(parser.ReportLine); + parser.Flush(); + IList results = parser.TestResults; results.Should().ContainSingle(); results[0].TestCase.FullyQualifiedName.Should().Be("TestMath.AddFails"); results[0].Duration.Should().Be(TimeSpan.FromMilliseconds(4656)); + + CheckStandardOutputResultParser(cases, consoleOutput, results, parser.CrashedTestCase); } finally { @@ -349,17 +304,52 @@ public void GetTestResults_OutputWithThousandsSeparatorInDuration_ParsedCorrectl [TestCategory(Unit)] public void GetTestResults_OutputWithConsoleOutput_ConsoleOutputIsIgnored() { - IList results = ComputeTestResults(PassingTestProducesConsoleOutput); + string[] consoleOutput = { + @"[==========] Running 1 tests from 1 test case.", + @"[----------] Global test environment set-up.", + @"[----------] 1 tests from TestMath", + @"[ RUN ] TestMath.AddPasses", + @"Some output produced by the exe", + @"[ OK ] TestMath.AddPasses(0 ms)", + @"[----------] 1 tests from TestMath(26 ms total)", + @"", + @"[----------] Global test environment tear-down", + @"[==========] 3 tests from 1 test case ran. (36 ms total)", + @"[ PASSED ] 1 test.", + }; + var cases = GetTestCases(); + + var parser = new StreamingStandardOutputTestResultParser(cases, MockLogger.Object, MockFrameworkReporter.Object); + consoleOutput.ToList().ForEach(parser.ReportLine); + parser.Flush(); + IList results = parser.TestResults; results.Should().ContainSingle(); results[0].TestCase.FullyQualifiedName.Should().Be("TestMath.AddPasses"); XmlTestResultParserTests.AssertTestResultIsPassed(results[0]); + + CheckStandardOutputResultParser(cases, consoleOutput, results, parser.CrashedTestCase); } [TestMethod] [TestCategory(Unit)] public void GetTestResults_OutputWithPrefixingTest_BothTestsAreFound() { + string[] consoleOutput = + { + @"[==========] Running 2 tests from 1 test case.", + @"[----------] Global test environment set-up.", + @"[----------] 2 tests from TestMath", + @"[ RUN ] Test.AB", + @"[ OK ] Test.A(0 ms)", + @"[ RUN ] Test.A", + @"[ OK ] Test.A(0 ms)", + @"[----------] 2 tests from TestMath(26 ms total)", + @"", + @"[----------] Global test environment tear-down", + @"[==========] 2 tests from 1 test case ran. (36 ms total)", + @"[ PASSED ] 2 test.", + }; var cases = new List { TestDataCreator.ToTestCase("Test.AB", TestDataCreator.DummyExecutable, @@ -369,7 +359,7 @@ public void GetTestResults_OutputWithPrefixingTest_BothTestsAreFound() }; var parser = new StreamingStandardOutputTestResultParser(cases, TestEnvironment.Logger, MockFrameworkReporter.Object); - ConsoleOutputWithPrefixingTest.ToList().ForEach(parser.ReportLine); + consoleOutput.ToList().ForEach(parser.ReportLine); parser.Flush(); var results = parser.TestResults; @@ -378,12 +368,38 @@ public void GetTestResults_OutputWithPrefixingTest_BothTestsAreFound() XmlTestResultParserTests.AssertTestResultIsPassed(results[0]); results[1].TestCase.FullyQualifiedName.Should().Be("Test.A"); XmlTestResultParserTests.AssertTestResultIsPassed(results[1]); + + CheckStandardOutputResultParser(cases, consoleOutput, results, parser.CrashedTestCase); } [TestMethod] [TestCategory(Unit)] public void GetTestResults_OutputWithSkippedTest_AllResultsAreFound() { + string[] consoleOutput = @"[==========] Running 3 tests from 1 test suite. +[----------] Global test environment set-up. +[----------] 3 tests from Test +[ RUN ] Test.Succeed +[ OK ] Test.Succeed (0 ms) +[ RUN ] Test.Skip +[ SKIPPED ] Test.Skip (1 ms) +[ RUN ] Test.Fail +C:\...\test.cpp(14): error: Value of: false + Actual: false +Expected: true +[ FAILED ] Test.Fail (0 ms) +[----------] 3 tests from Test (3 ms total) + +[----------] Global test environment tear-down +[==========] 3 tests from 1 test suite ran. (6 ms total) +[ PASSED ] 1 test. +[ SKIPPED ] 1 test, listed below: +[ SKIPPED ] Test.Skip +[ FAILED ] 1 test, listed below: +[ FAILED ] Test.Fail + + 1 FAILED TEST +".Split('\n'); var cases = new List { TestDataCreator.ToTestCase("Test.Succeed", TestDataCreator.DummyExecutable, @"c:\somepath\source.cpp"), @@ -392,7 +408,7 @@ public void GetTestResults_OutputWithSkippedTest_AllResultsAreFound() }; var parser = new StreamingStandardOutputTestResultParser(cases, TestEnvironment.Logger, MockFrameworkReporter.Object); - ConsoleOutputWithSkippedTest.ToList().ForEach(parser.ReportLine); + consoleOutput.ToList().ForEach(parser.ReportLine); parser.Flush(); var results = parser.TestResults; @@ -409,12 +425,38 @@ public void GetTestResults_OutputWithSkippedTest_AllResultsAreFound() result = results[2]; result.TestCase.FullyQualifiedName.Should().Be("Test.Fail"); XmlTestResultParserTests.AssertTestResultIsFailure(result); + + CheckStandardOutputResultParser(cases, consoleOutput, results, parser.CrashedTestCase); } [TestMethod] [TestCategory(Unit)] public void GetTestResults_OutputWithSkippedTestAsLastTest_AllResultsAreFound() { + string[] consoleOutput = @"[==========] Running 3 tests from 1 test suite. +[----------] Global test environment set-up. +[----------] 3 tests from Test +[ RUN ] Test.Succeed +[ OK ] Test.Succeed (0 ms) +[ RUN ] Test.Fail +C:\...\test.cpp(14): error: Value of: false + Actual: false +Expected: true +[ FAILED ] Test.Fail (0 ms) +[ RUN ] Test.Skip +[ SKIPPED ] Test.Skip (1 ms) +[----------] 3 tests from Test (3 ms total) + +[----------] Global test environment tear-down +[==========] 3 tests from 1 test suite ran. (6 ms total) +[ PASSED ] 1 test. +[ SKIPPED ] 1 test, listed below: +[ SKIPPED ] Test.Skip +[ FAILED ] 1 test, listed below: +[ FAILED ] Test.Fail + + 1 FAILED TEST +".Split('\n'); var cases = new List { TestDataCreator.ToTestCase("Test.Succeed", TestDataCreator.DummyExecutable, @"c:\somepath\source.cpp"), @@ -423,7 +465,7 @@ public void GetTestResults_OutputWithSkippedTestAsLastTest_AllResultsAreFound() }; var parser = new StreamingStandardOutputTestResultParser(cases, TestEnvironment.Logger, MockFrameworkReporter.Object); - ConsoleOutputWithSkippedTestAsLastTest.ToList().ForEach(parser.ReportLine); + consoleOutput.ToList().ForEach(parser.ReportLine); parser.Flush(); var results = parser.TestResults; @@ -440,94 +482,137 @@ public void GetTestResults_OutputWithSkippedTestAsLastTest_AllResultsAreFound() result = results[2]; result.TestCase.FullyQualifiedName.Should().Be("Test.Skip"); XmlTestResultParserTests.AssertTestResultIsSkipped(result); + + CheckStandardOutputResultParser(cases, consoleOutput, results, parser.CrashedTestCase); } [TestMethod] [TestCategory(Unit)] public void OutputHandling_OutputManyLinesWithNewlines_IsParsedCorrectly() { - var results = GetTestResultsFromCompleteOutputFile(); + var consoleOutput = File.ReadAllLines(TestResources.Tests_ReleaseX64_Output, Encoding.Default); + var testCases = new GoogleTestDiscoverer(MockLogger.Object, MockOptions.Object) + .GetTestsFromExecutable(TestResources.Tests_ReleaseX64); + + var parser = new StreamingStandardOutputTestResultParser(testCases, MockLogger.Object, MockFrameworkReporter.Object); + consoleOutput.ToList().ForEach(parser.ReportLine); + parser.Flush(); + var results = parser.TestResults; var testResult = results.Single(tr => tr.DisplayName == "OutputHandling.Output_ManyLinesWithNewlines"); var expectedErrorMessage = "before test 1\nbefore test 2\nExpected: 1\nTo be equal to: 2\ntest output\nafter test 1\nafter test 2"; testResult.ErrorMessage.Should().Be(expectedErrorMessage); + + CheckStandardOutputResultParser(testCases, consoleOutput, results, parser.CrashedTestCase); } [TestMethod] [TestCategory(Unit)] public void OutputHandling_OutputOneLineWithNewlines_IsParsedCorrectly() { - var results = GetTestResultsFromCompleteOutputFile(); + var consoleOutput = File.ReadAllLines(TestResources.Tests_ReleaseX64_Output, Encoding.Default); + var testCases = new GoogleTestDiscoverer(MockLogger.Object, MockOptions.Object) + .GetTestsFromExecutable(TestResources.Tests_ReleaseX64); + + var parser = new StreamingStandardOutputTestResultParser(testCases, MockLogger.Object, MockFrameworkReporter.Object); + consoleOutput.ToList().ForEach(parser.ReportLine); + parser.Flush(); + var results = parser.TestResults; var testResult = results.Single(tr => tr.DisplayName == "OutputHandling.Output_OneLineWithNewlines"); var expectedErrorMessage = "before test\nExpected: 1\nTo be equal to: 2\ntest output\nafter test"; testResult.ErrorMessage.Should().Be(expectedErrorMessage); + + CheckStandardOutputResultParser(testCases, consoleOutput, results, parser.CrashedTestCase); } [TestMethod] [TestCategory(Unit)] public void OutputHandling_OutputOneLine_IsParsedCorrectly() { - var results = GetTestResultsFromCompleteOutputFile(); + var consoleOutput = File.ReadAllLines(TestResources.Tests_ReleaseX64_Output, Encoding.Default); + var testCases = new GoogleTestDiscoverer(MockLogger.Object, MockOptions.Object) + .GetTestsFromExecutable(TestResources.Tests_ReleaseX64); + + var parser = new StreamingStandardOutputTestResultParser(testCases, MockLogger.Object, MockFrameworkReporter.Object); + consoleOutput.ToList().ForEach(parser.ReportLine); + parser.Flush(); + var results = parser.TestResults; var testResult = results.Single(tr => tr.DisplayName == "OutputHandling.Output_OneLine"); var expectedErrorMessage = "before test\nExpected: 1\nTo be equal to: 2\ntest output\nafter test"; testResult.ErrorMessage.Should().Be(expectedErrorMessage); + + CheckStandardOutputResultParser(testCases, consoleOutput, results, parser.CrashedTestCase); } [TestMethod] [TestCategory(Unit)] public void OutputHandling_ManyLinesWithNewlines_IsParsedCorrectly() { - var results = GetTestResultsFromCompleteOutputFile(); + var consoleOutput = File.ReadAllLines(TestResources.Tests_ReleaseX64_Output, Encoding.Default); + var testCases = new GoogleTestDiscoverer(MockLogger.Object, MockOptions.Object) + .GetTestsFromExecutable(TestResources.Tests_ReleaseX64); + + var parser = new StreamingStandardOutputTestResultParser(testCases, MockLogger.Object, MockFrameworkReporter.Object); + consoleOutput.ToList().ForEach(parser.ReportLine); + parser.Flush(); + var results = parser.TestResults; var testResult = results.Single(tr => tr.DisplayName == "OutputHandling.ManyLinesWithNewlines"); var expectedErrorMessage = "before test 1\nbefore test 2\nExpected: 1\nTo be equal to: 2\nafter test 1\nafter test 2"; testResult.ErrorMessage.Should().Be(expectedErrorMessage); + + CheckStandardOutputResultParser(testCases, consoleOutput, results, parser.CrashedTestCase); } [TestMethod] [TestCategory(Unit)] public void OutputHandling_OneLineWithNewlines_IsParsedCorrectly() { - var results = GetTestResultsFromCompleteOutputFile(); + var consoleOutput = File.ReadAllLines(TestResources.Tests_ReleaseX64_Output, Encoding.Default); + var testCases = new GoogleTestDiscoverer(MockLogger.Object, MockOptions.Object) + .GetTestsFromExecutable(TestResources.Tests_ReleaseX64); + + var parser = new StreamingStandardOutputTestResultParser(testCases, MockLogger.Object, MockFrameworkReporter.Object); + consoleOutput.ToList().ForEach(parser.ReportLine); + parser.Flush(); + var results = parser.TestResults; var testResult = results.Single(tr => tr.DisplayName == "OutputHandling.Output_OneLineWithNewlines"); var expectedErrorMessage = "before test\nExpected: 1\nTo be equal to: 2\ntest output\nafter test"; testResult.ErrorMessage.Should().Be(expectedErrorMessage); + + CheckStandardOutputResultParser(testCases, consoleOutput, results, parser.CrashedTestCase); } [TestMethod] [TestCategory(Unit)] public void OutputHandling_OneLine_IsParsedCorrectly() { - var results = GetTestResultsFromCompleteOutputFile(); - - var testResult = results.Single(tr => tr.DisplayName == "OutputHandling.OneLine"); - var expectedErrorMessage = - "before test\nExpected: 1\nTo be equal to: 2\nafter test"; - testResult.ErrorMessage.Should().Be(expectedErrorMessage); - } - - private IList GetTestResultsFromCompleteOutputFile() - { + var consoleOutput = File.ReadAllLines(TestResources.Tests_ReleaseX64_Output, Encoding.Default); var testCases = new GoogleTestDiscoverer(MockLogger.Object, MockOptions.Object) .GetTestsFromExecutable(TestResources.Tests_ReleaseX64); var parser = new StreamingStandardOutputTestResultParser(testCases, MockLogger.Object, MockFrameworkReporter.Object); - CompleteStandardOutput.ForEach(parser.ReportLine); + consoleOutput.ToList().ForEach(parser.ReportLine); parser.Flush(); + var results = parser.TestResults; - return parser.TestResults; - } + var testResult = results.Single(tr => tr.DisplayName == "OutputHandling.OneLine"); + var expectedErrorMessage = + "before test\nExpected: 1\nTo be equal to: 2\nafter test"; + testResult.ErrorMessage.Should().Be(expectedErrorMessage); + CheckStandardOutputResultParser(testCases, consoleOutput, results, parser.CrashedTestCase); + } - private IList ComputeTestResults(List consoleOutput) + private List GetTestCases() { var cases = new List { @@ -538,14 +623,17 @@ private IList ComputeTestResults(List consoleOutput) TestDataCreator.ToTestCase("TestMath.AddPasses", TestDataCreator.DummyExecutable, @"c:\users\chris\documents\visual studio 2015\projects\consoleapplication1\consoleapplication1tests\source.cpp") }; + return cases; + } - var parser = new StreamingStandardOutputTestResultParser(cases, MockLogger.Object, MockFrameworkReporter.Object); - consoleOutput.ForEach(parser.ReportLine); - parser.Flush(); + private void CheckStandardOutputResultParser(IEnumerable testCasesRun, IEnumerable consoleOutput, + IList results, TestCase crashedTestCase) + { + var parser = new StandardOutputTestResultParser(testCasesRun, consoleOutput, MockLogger.Object); - return parser.TestResults; + parser.GetTestResults().Should().BeEquivalentTo(results); + parser.CrashedTestCase.Should().Be(crashedTestCase); } - } } \ No newline at end of file diff --git a/GoogleTestAdapter/Core/Runners/TestResultCollector.cs b/GoogleTestAdapter/Core/Runners/TestResultCollector.cs index 9f4d82b5e..f88ee7641 100644 --- a/GoogleTestAdapter/Core/Runners/TestResultCollector.cs +++ b/GoogleTestAdapter/Core/Runners/TestResultCollector.cs @@ -66,7 +66,7 @@ private void CollectResultsFromXmlFile(TestCase[] testCasesRun, string testExecu private void CollectResultsFromConsoleOutput(StandardOutputTestResultParser consoleParser, List testResults) { - List consoleResults = consoleParser.GetTestResults(); + var consoleResults = consoleParser.GetTestResults(); int nrOfCollectedTestResults = 0; foreach (TestResult testResult in consoleResults.Where( tr => !testResults.Exists(tr2 => tr.TestCase.FullyQualifiedName == tr2.TestCase.FullyQualifiedName))) diff --git a/GoogleTestAdapter/Core/TestResults/StandardOutputTestResultParser.cs b/GoogleTestAdapter/Core/TestResults/StandardOutputTestResultParser.cs index 2d5ac6036..834418e58 100644 --- a/GoogleTestAdapter/Core/TestResults/StandardOutputTestResultParser.cs +++ b/GoogleTestAdapter/Core/TestResults/StandardOutputTestResultParser.cs @@ -1,246 +1,50 @@ -using System; -using System.Collections.Generic; -using System.Globalization; +using System.Collections.Generic; using System.Linq; -using System.Text.RegularExpressions; using GoogleTestAdapter.Common; +using GoogleTestAdapter.Framework; using GoogleTestAdapter.Model; namespace GoogleTestAdapter.TestResults { public class StandardOutputTestResultParser { - private const string Run = "[ RUN ]"; - public const string Failed = "[ FAILED ]"; - public const string Passed = "[ OK ]"; - public const string Skipped = "[ SKIPPED ]"; - - public const string CrashText = "!! This test has probably CRASHED !!"; - - /// - /// Google Test reports test duration in complete ms. In case of 0ms, - /// we assume the actual duration to be <0.5ms, and thus go for 0.25ms on average - /// (which also makes VS display the duration properly as "<1ms"). - /// 2500 ticks = 0.25ms - /// - public static readonly TimeSpan ShortTestDuration = TimeSpan.FromTicks(2500); - - public TestCase CrashedTestCase { get; private set; } - - private readonly List _consoleOutput; - private readonly List _testCasesRun; - private readonly ILogger _logger; - - - public StandardOutputTestResultParser(IEnumerable testCasesRun, IEnumerable consoleOutput, ILogger logger) - { - _consoleOutput = consoleOutput.ToList(); - _testCasesRun = testCasesRun.ToList(); - _logger = logger; - } - - - public List GetTestResults() + private class DummyTestFrameworkReporter : ITestFrameworkReporter { - var testResults = new List(); - int indexOfNextTestcase = FindIndexOfNextTestcase(0); - while (indexOfNextTestcase >= 0) + public void ReportTestResults(IEnumerable testResults) { - var testResult = CreateTestResult(indexOfNextTestcase); - if (testResult != null) - testResults.Add(testResult); - - indexOfNextTestcase = FindIndexOfNextTestcase(indexOfNextTestcase + 1); - } - return testResults; - } - - - private TestResult CreateTestResult(int indexOfTestcase) - { - int currentLineIndex = indexOfTestcase; - - string line = _consoleOutput[currentLineIndex++]; - string qualifiedTestname = RemovePrefix(line).Trim(); - TestCase testCase = FindTestcase(qualifiedTestname); - if (testCase == null) - { - _logger.DebugWarning($"No known test case for test result of line '{line}' - are you repeating a test run, but tests have changed in the meantime?"); - return null; - } - - if (currentLineIndex >= _consoleOutput.Count) - { - CrashedTestCase = testCase; - return CreateFailedTestResult(testCase, TimeSpan.FromMilliseconds(0), CrashText, ""); - } - - line = _consoleOutput[currentLineIndex]; - SplitLineIfNecessary(ref line, currentLineIndex); - currentLineIndex++; - - - string errorMsg = ""; - while (!(IsFailedLine(line) || IsPassedLine(line) || IsSkippedLine(line)) && currentLineIndex <= _consoleOutput.Count) - { - errorMsg += line + "\n"; - line = currentLineIndex < _consoleOutput.Count ? _consoleOutput[currentLineIndex] : ""; - SplitLineIfNecessary(ref line, currentLineIndex); - currentLineIndex++; - } - if (IsFailedLine(line)) - { - ErrorMessageParser parser = new ErrorMessageParser(errorMsg); - parser.Parse(); - return CreateFailedTestResult(testCase, ParseDuration(line), parser.ErrorMessage, parser.ErrorStackTrace); - } - if (IsPassedLine(line)) - { - return CreatePassedTestResult(testCase, ParseDuration(line)); - } - if (IsSkippedLine(line)) - { - return CreateSkippedTestResult(testCase, ParseDuration(line)); - } - - CrashedTestCase = testCase; - string message = CrashText; - message += errorMsg == "" ? "" : "\nTest output:\n\n" + errorMsg; - return CreateFailedTestResult(testCase, TimeSpan.FromMilliseconds(0), message, ""); - } - - private void SplitLineIfNecessary(ref string line, int currentLineIndex) - { - Match testEndMatch = StreamingStandardOutputTestResultParser.PrefixedLineRegex.Match(line); - if (testEndMatch.Success) - { - string restOfErrorMessage = testEndMatch.Groups[1].Value; - string testEndPart = testEndMatch.Groups[2].Value; - - _consoleOutput.RemoveAt(currentLineIndex); - _consoleOutput.Insert(currentLineIndex, testEndPart); - _consoleOutput.Insert(currentLineIndex, restOfErrorMessage); - - line = restOfErrorMessage; } - } - - private TimeSpan ParseDuration(string line) - { - return ParseDuration(line, _logger); - } - public static TimeSpan ParseDuration(string line, ILogger logger) - { - int durationInMs = 1; - try + public void ReportTestsFound(IEnumerable testCases) { - // duration is a 64-bit number (no decimals) in the user's locale - int indexOfOpeningBracket = line.LastIndexOf('('); - int lengthOfDurationPart = line.Length - indexOfOpeningBracket - 2; - string durationPart = line.Substring(indexOfOpeningBracket + 1, lengthOfDurationPart); - durationPart = durationPart.Replace("ms", "").Trim(); - durationInMs = int.Parse(durationPart, NumberStyles.Number); } - catch (Exception) - { - logger.LogWarning("Could not parse duration in line '" + line + "'"); - } - - return NormalizeDuration(TimeSpan.FromMilliseconds(durationInMs)); - } - - public static TimeSpan NormalizeDuration(TimeSpan duration) - { - return duration.TotalMilliseconds < 1 - ? ShortTestDuration - : duration; - } - - public static TestResult CreatePassedTestResult(TestCase testCase, TimeSpan duration) - { - return new TestResult(testCase) - { - ComputerName = Environment.MachineName, - DisplayName = testCase.DisplayName, - Outcome = TestOutcome.Passed, - Duration = duration - }; - } - - public static TestResult CreateSkippedTestResult(TestCase testCase, TimeSpan duration) - { - return new TestResult(testCase) - { - ComputerName = Environment.MachineName, - DisplayName = testCase.DisplayName, - Outcome = TestOutcome.Skipped, - Duration = duration - }; - } - public static TestResult CreateFailedTestResult(TestCase testCase, TimeSpan duration, string errorMessage, string errorStackTrace) - { - return new TestResult(testCase) + public void ReportTestsStarted(IEnumerable testCases) { - ComputerName = Environment.MachineName, - DisplayName = testCase.DisplayName, - Outcome = TestOutcome.Failed, - ErrorMessage = errorMessage, - ErrorStackTrace = errorStackTrace, - Duration = duration - }; - } - - private int FindIndexOfNextTestcase(int currentIndex) - { - while (currentIndex < _consoleOutput.Count) - { - string line = _consoleOutput[currentIndex]; - if (IsRunLine(line)) - { - return currentIndex; - } - currentIndex++; } - return -1; - } - - private TestCase FindTestcase(string qualifiedTestname) - { - return FindTestcase(qualifiedTestname, _testCasesRun); - } - - public static TestCase FindTestcase(string qualifiedTestname, IList testCasesRun) - { - return testCasesRun.SingleOrDefault(tc => tc.FullyQualifiedName == qualifiedTestname); } - public static bool IsRunLine(string line) - { - return line.StartsWith(Run); - } + public TestCase CrashedTestCase { get; private set; } - public static bool IsPassedLine(string line) - { - return line.StartsWith(Passed); - } + private readonly List _consoleOutput; + private readonly List _testCasesRun; + private readonly ILogger _logger; - public static bool IsFailedLine(string line) + public StandardOutputTestResultParser(IEnumerable testCasesRun, IEnumerable consoleOutput, ILogger logger) { - return line.StartsWith(Failed); + _consoleOutput = consoleOutput.ToList(); + _testCasesRun = testCasesRun.ToList(); + _logger = logger; } - public static bool IsSkippedLine(string line) + public IList GetTestResults() { - return line.StartsWith(Skipped); - } + var streamingParser = new StreamingStandardOutputTestResultParser(_testCasesRun, _logger, new DummyTestFrameworkReporter()); + _consoleOutput.ForEach(l => streamingParser.ReportLine(l)); + streamingParser.Flush(); - public static string RemovePrefix(string line) - { - return line.Substring(Run.Length); + CrashedTestCase = streamingParser.CrashedTestCase; + return streamingParser.TestResults; } - } } \ No newline at end of file diff --git a/GoogleTestAdapter/Core/TestResults/StreamingStandardOutputTestResultParser.cs b/GoogleTestAdapter/Core/TestResults/StreamingStandardOutputTestResultParser.cs index 4c45aa797..6ed27bc35 100644 --- a/GoogleTestAdapter/Core/TestResults/StreamingStandardOutputTestResultParser.cs +++ b/GoogleTestAdapter/Core/TestResults/StreamingStandardOutputTestResultParser.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Text.RegularExpressions; using GoogleTestAdapter.Common; @@ -11,7 +12,22 @@ namespace GoogleTestAdapter.TestResults { public class StreamingStandardOutputTestResultParser { - public static readonly Regex PrefixedLineRegex; + private const string Run = "[ RUN ]"; + private const string Failed = "[ FAILED ]"; + private const string Passed = "[ OK ]"; + private const string Skipped = "[ SKIPPED ]"; + + public const string CrashText = "!! This test has probably CRASHED !!"; + + /// + /// Google Test reports test duration in complete ms. In case of 0ms, + /// we assume the actual duration to be <0.5ms, and thus go for 0.25ms on average + /// (which also makes VS display the duration properly as "<1ms"). + /// 2500 ticks = 0.25ms + /// + public static readonly TimeSpan ShortTestDuration = TimeSpan.FromTicks(2500); + + private static readonly Regex PrefixedLineRegex; public TestCase CrashedTestCase { get; private set; } public IList TestResults { get; } = new List(); @@ -24,8 +40,8 @@ public class StreamingStandardOutputTestResultParser static StreamingStandardOutputTestResultParser() { - string passedMarker = Regex.Escape(StandardOutputTestResultParser.Passed); - string failedMarker = Regex.Escape(StandardOutputTestResultParser.Failed); + string passedMarker = Regex.Escape(Passed); + string failedMarker = Regex.Escape(Failed); PrefixedLineRegex = new Regex($"(.+)((?:{passedMarker}|{failedMarker}).*)", RegexOptions.Compiled); } @@ -57,7 +73,7 @@ public void ReportLine(string line) private void DoReportLine(string line) { - if (StandardOutputTestResultParser.IsRunLine(line)) + if (IsRunLine(line)) { if (_consoleOutput.Count > 0) { @@ -80,8 +96,8 @@ public void Flush() private void ReportTestStart(string line) { - string qualifiedTestname = StandardOutputTestResultParser.RemovePrefix(line).Trim(); - TestCase testCase = StandardOutputTestResultParser.FindTestcase(qualifiedTestname, _testCasesRun); + string qualifiedTestname = RemovePrefix(line).Trim(); + TestCase testCase = FindTestcase(qualifiedTestname, _testCasesRun); if (testCase != null) _reporter.ReportTestsStarted(testCase.Yield()); } @@ -100,15 +116,15 @@ private TestResult CreateTestResult() { int currentLineIndex = 0; while (currentLineIndex < _consoleOutput.Count && - !StandardOutputTestResultParser.IsRunLine(_consoleOutput[currentLineIndex])) + !IsRunLine(_consoleOutput[currentLineIndex])) currentLineIndex++; if (currentLineIndex == _consoleOutput.Count) return null; string line = _consoleOutput[currentLineIndex++]; - string qualifiedTestname = StandardOutputTestResultParser.RemovePrefix(line).Trim(); - TestCase testCase = StandardOutputTestResultParser.FindTestcase(qualifiedTestname, _testCasesRun); + string qualifiedTestname = RemovePrefix(line).Trim(); + TestCase testCase = FindTestcase(qualifiedTestname, _testCasesRun); if (testCase == null) { _logger.DebugWarning($"No known test case for test result of line '{line}'' - are you repeating a test run, but tests have changed in the meantime?"); @@ -118,53 +134,46 @@ private TestResult CreateTestResult() if (currentLineIndex == _consoleOutput.Count) { CrashedTestCase = testCase; - return StandardOutputTestResultParser.CreateFailedTestResult( + return CreateFailedTestResult( testCase, TimeSpan.FromMilliseconds(0), - StandardOutputTestResultParser.CrashText, + CrashText, ""); } line = _consoleOutput[currentLineIndex++]; string errorMsg = ""; - while ( - !(StandardOutputTestResultParser.IsFailedLine(line) - || StandardOutputTestResultParser.IsPassedLine(line) - || StandardOutputTestResultParser.IsSkippedLine(line)) + while (!(IsFailedLine(line) || IsPassedLine(line) || IsSkippedLine(line)) && currentLineIndex <= _consoleOutput.Count) { errorMsg += line + "\n"; line = currentLineIndex < _consoleOutput.Count ? _consoleOutput[currentLineIndex] : ""; currentLineIndex++; } - if (StandardOutputTestResultParser.IsFailedLine(line)) + if (IsFailedLine(line)) { ErrorMessageParser parser = new ErrorMessageParser(errorMsg); parser.Parse(); - return StandardOutputTestResultParser.CreateFailedTestResult( + return CreateFailedTestResult( testCase, - StandardOutputTestResultParser.ParseDuration(line, _logger), + ParseDuration(line, _logger), parser.ErrorMessage, parser.ErrorStackTrace); } - if (StandardOutputTestResultParser.IsPassedLine(line)) + if (IsPassedLine(line)) { - return StandardOutputTestResultParser.CreatePassedTestResult( - testCase, - StandardOutputTestResultParser.ParseDuration(line, _logger)); + return CreatePassedTestResult(testCase, ParseDuration(line, _logger)); } - if (StandardOutputTestResultParser.IsSkippedLine(line)) + if (IsSkippedLine(line)) { - return StandardOutputTestResultParser.CreateSkippedTestResult( - testCase, - StandardOutputTestResultParser.ParseDuration(line, _logger)); + return CreateSkippedTestResult(testCase, ParseDuration(line, _logger)); } CrashedTestCase = testCase; - string message = StandardOutputTestResultParser.CrashText; + string message = CrashText; message += errorMsg == "" ? "" : $"\nTest output:\n\n{errorMsg}"; - TestResult result = StandardOutputTestResultParser.CreateFailedTestResult( + TestResult result = CreateFailedTestResult( testCase, TimeSpan.FromMilliseconds(0), message, @@ -172,6 +181,97 @@ private TestResult CreateTestResult() return result; } + private TimeSpan ParseDuration(string line, ILogger logger) + { + int durationInMs = 1; + try + { + // duration is a 64-bit number (no decimals) in the user's locale + int indexOfOpeningBracket = line.LastIndexOf('('); + int lengthOfDurationPart = line.Length - indexOfOpeningBracket - 2; + string durationPart = line.Substring(indexOfOpeningBracket + 1, lengthOfDurationPart); + durationPart = durationPart.Replace("ms", "").Trim(); + durationInMs = Int32.Parse(durationPart, NumberStyles.Number); + } + catch (Exception) + { + logger.LogWarning("Could not parse duration in line '" + line + "'"); + } + + return NormalizeDuration(TimeSpan.FromMilliseconds(durationInMs)); + } + + public static TimeSpan NormalizeDuration(TimeSpan duration) + { + return duration.TotalMilliseconds < 1 + ? ShortTestDuration + : duration; + } + + private TestResult CreatePassedTestResult(TestCase testCase, TimeSpan duration) + { + return new TestResult(testCase) + { + ComputerName = Environment.MachineName, + DisplayName = testCase.DisplayName, + Outcome = TestOutcome.Passed, + Duration = duration + }; + } + + private TestResult CreateSkippedTestResult(TestCase testCase, TimeSpan duration) + { + return new TestResult(testCase) + { + ComputerName = Environment.MachineName, + DisplayName = testCase.DisplayName, + Outcome = TestOutcome.Skipped, + Duration = duration + }; + } + + private TestResult CreateFailedTestResult(TestCase testCase, TimeSpan duration, string errorMessage, string errorStackTrace) + { + return new TestResult(testCase) + { + ComputerName = Environment.MachineName, + DisplayName = testCase.DisplayName, + Outcome = TestOutcome.Failed, + ErrorMessage = errorMessage, + ErrorStackTrace = errorStackTrace, + Duration = duration + }; + } + + private TestCase FindTestcase(string qualifiedTestname, IList testCasesRun) + { + return testCasesRun.SingleOrDefault(tc => tc.FullyQualifiedName == qualifiedTestname); + } + + private bool IsRunLine(string line) + { + return line.StartsWith(Run); + } + + private bool IsPassedLine(string line) + { + return line.StartsWith(Passed); + } + + private bool IsFailedLine(string line) + { + return line.StartsWith(Failed); + } + + private bool IsSkippedLine(string line) + { + return line.StartsWith(Skipped); + } + + private string RemovePrefix(string line) + { + return line.Substring(Run.Length); + } } } \ No newline at end of file diff --git a/GoogleTestAdapter/Core/TestResults/XmlTestResultParser.cs b/GoogleTestAdapter/Core/TestResults/XmlTestResultParser.cs index d1ef25c8d..23b7a9baa 100644 --- a/GoogleTestAdapter/Core/TestResults/XmlTestResultParser.cs +++ b/GoogleTestAdapter/Core/TestResults/XmlTestResultParser.cs @@ -207,7 +207,7 @@ private string GetQualifiedName(XmlNode testcaseNode) private TimeSpan ParseDuration(string durationInSeconds) { return - StandardOutputTestResultParser + StreamingStandardOutputTestResultParser .NormalizeDuration(TimeSpan.FromSeconds(double.Parse(durationInSeconds, NumberFormatInfo))); } From 96f5391e259b2eb460c06e002d474f201d11d6bd Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Mon, 4 Feb 2019 19:09:15 +0100 Subject: [PATCH 03/81] added test for treatment of duplicates --- .../TestResults/XmlTestResultParserTests.cs | 16 +++++++++++++++- .../Tests.Common/Resources/TestData/Umlauts.xml | 8 ++++++++ GoogleTestAdapter/Tests.Common/TestResources.cs | 1 + .../Tests.Common/Tests.Common.csproj | 3 +++ 4 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 GoogleTestAdapter/Tests.Common/Resources/TestData/Umlauts.xml diff --git a/GoogleTestAdapter/Core.Tests/TestResults/XmlTestResultParserTests.cs b/GoogleTestAdapter/Core.Tests/TestResults/XmlTestResultParserTests.cs index 1cc9203de..6a83b06aa 100644 --- a/GoogleTestAdapter/Core.Tests/TestResults/XmlTestResultParserTests.cs +++ b/GoogleTestAdapter/Core.Tests/TestResults/XmlTestResultParserTests.cs @@ -115,7 +115,7 @@ public void GetTestResults_Sample1_FindsFailureResult() [TestMethod] [TestCategory(Unit)] - public void GetTestResults_Sample1_FindsParamterizedFailureResult() + public void GetTestResults_Sample1_FindsParameterizedFailureResult() { IEnumerable testCases = TestDataCreator.ToTestCase("ParameterizedTestsTest1/AllEnabledTest.TestInstance/11", TestDataCreator.DummyExecutable, @"someSimpleParameterizedTest.cpp").Yield(); @@ -164,6 +164,20 @@ public void GetTestResults_Sample2_FindsFailureResult() results[0].ErrorStackTrace.Should().Contain(@"c:\prod\gtest-1.7.0\staticallylinkedgoogletests\main.cpp"); } + [TestMethod] + [TestCategory(Unit)] + public void GetTestResults_Umlauts_FindsOneResultAndWarns() + { + IEnumerable testCases = TestDataCreator.CreateDummyTestCases("TheClass.Täst1", "TheClass.Töst1", "TheClass.Täst2"); + + var parser = new XmlTestResultParser(testCases, "someexecutable", TestResources.XmlUmlauts, TestEnvironment.Logger); + List results = parser.GetTestResults(); + + results.Should().ContainSingle(); + AssertTestResultIsPassed(results[0]); + MockLogger.Verify(l => l.LogWarning(It.IsAny()), Times.Once); + } + public static void AssertTestResultIsPassed(Model.TestResult testResult) { diff --git a/GoogleTestAdapter/Tests.Common/Resources/TestData/Umlauts.xml b/GoogleTestAdapter/Tests.Common/Resources/TestData/Umlauts.xml new file mode 100644 index 000000000..aa73caa4f --- /dev/null +++ b/GoogleTestAdapter/Tests.Common/Resources/TestData/Umlauts.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/GoogleTestAdapter/Tests.Common/TestResources.cs b/GoogleTestAdapter/Tests.Common/TestResources.cs index d9696661f..9bc2816d3 100644 --- a/GoogleTestAdapter/Tests.Common/TestResources.cs +++ b/GoogleTestAdapter/Tests.Common/TestResources.cs @@ -66,6 +66,7 @@ public static class TestResources public const string XmlFile1 = TestdataDir + @"SampleResult1.xml"; public const string XmlFile2 = TestdataDir + @"SampleResult2.xml"; + public const string XmlUmlauts = TestdataDir + @"Umlauts.xml"; public const string XmlFileBroken = TestdataDir + @"SampleResult1_Broken.xml"; // ReSharper disable once InconsistentNaming public const string XmlFileBroken_InvalidStatusAttibute = TestdataDir + @"SampleResult1 _Broken_InvalidStatusAttribute.xml"; diff --git a/GoogleTestAdapter/Tests.Common/Tests.Common.csproj b/GoogleTestAdapter/Tests.Common/Tests.Common.csproj index 4079c51f7..a2bf38328 100644 --- a/GoogleTestAdapter/Tests.Common/Tests.Common.csproj +++ b/GoogleTestAdapter/Tests.Common/Tests.Common.csproj @@ -137,6 +137,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest From 8343983d196ae70386e815dee49933e43d40908b Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Fri, 22 Feb 2019 07:23:12 +0100 Subject: [PATCH 04/81] Added support for result codes not produced by gtest, e.g. for performing memory leak detection --- .../Core.Tests/GoogleTestDiscovererTests.cs | 23 ++- ...mingStandardOutputTestResultParserTests.cs | 180 ++++++++++++++++++ GoogleTestAdapter/Core/GoogleTestExecutor.cs | 53 +++++- GoogleTestAdapter/Core/Runners/ITestRunner.cs | 10 +- .../Core/Runners/ParallelTestRunner.cs | 22 ++- .../Core/Runners/PreparingTestRunner.cs | 2 + .../Core/Runners/SequentialTestRunner.cs | 13 +- .../Settings/IGoogleTestAdapterSettings.cs | 2 + .../Core/Settings/RunSettings.cs | 3 + .../Core/Settings/SettingsWrapper.cs | 8 + .../Core/TestCases/TestCaseFactory.cs | 25 ++- ...StreamingStandardOutputTestResultParser.cs | 42 +++- GoogleTestAdapter/GoogleTestAdapter.sln | 13 ++ .../Resources/AllTestSettings.gta.runsettings | 2 + .../TestAdapter.Tests/TestDiscovererTests.cs | 1 + .../TestExecutorParallelTests.cs | 12 ++ .../TestExecutorSequentialTests.cs | 12 ++ ...cutorSequentialTests_FrameworkDebugging.cs | 12 ++ .../TestExecutorTestsBase.cs | 137 +++++++++++++ .../TestAdapter/GoogleTestAdapterSettings.xsd | 2 +- .../Tests.Common/TestResources.cs | 3 + .../Tests/ProcessExecutorTests.cs | 2 +- GoogleTestAdapter/Tests.Common/TestsBase.cs | 1 + .../GoogleTestExtensionOptionsPage.cs | 1 + .../OptionsPages/GeneralOptionsDialogPage.cs | 10 + ...tionProjectSettings_Coverage_Isolation.xml | 4 +- ...tionProjectSettings_Coverage_Isolation.xml | 4 +- SampleTests/LeakCheckTests/LeakCheckTests.cpp | 140 ++++++++++++++ .../LeakCheckTests/LeakCheckTests.vcxproj | 178 +++++++++++++++++ .../LeakCheckTests.vcxproj.filters | 28 +++ SampleTests/LeakCheckTests/test_leak.cpp | 27 +++ SampleTests/SampleTests.sln | 15 ++ SampleTests/Tests/Main.cpp | 9 +- 33 files changed, 975 insertions(+), 21 deletions(-) create mode 100644 SampleTests/LeakCheckTests/LeakCheckTests.cpp create mode 100644 SampleTests/LeakCheckTests/LeakCheckTests.vcxproj create mode 100644 SampleTests/LeakCheckTests/LeakCheckTests.vcxproj.filters create mode 100644 SampleTests/LeakCheckTests/test_leak.cpp diff --git a/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTests.cs b/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTests.cs index 259b3ec9c..015701d18 100644 --- a/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTests.cs +++ b/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTests.cs @@ -156,6 +156,25 @@ public void GetTestsFromExecutable_SampleTestsDebug_FindsTestsWithLocation() FindTests(TestResources.Tests_DebugX86); } + [TestMethod] + [TestCategory(Integration)] + public void GetTestsFromExecutable_SampleTestsDebugWithResultCodeTest_FindsTestsWithLocationAndResultCodeTest() + { + string testCaseName = "ResultCode"; + MockOptions.Setup(o => o.ReturnCodeTestCase).Returns(testCaseName); + + var testCases = FindTests(TestResources.Tests_DebugX86, TestResources.NrOfTests + 1); + + string finalName = Path.GetFileName(TestResources.Tests_DebugX86).Replace(".", "_") + "." + testCaseName; + var resultCodeTestCase = testCases.Single(tc => tc.FullyQualifiedName == finalName); + resultCodeTestCase.DisplayName.Should().Be(finalName); + resultCodeTestCase.Source.Should().Be(TestResources.Tests_DebugX86); + resultCodeTestCase.CodeFilePath.Should().BeEmpty(); + resultCodeTestCase.LineNumber.Should().Be(0); + + MockLogger.Verify(l => l.DebugInfo(It.Is(msg => msg.Contains("Exit code") && msg.Contains("ignored"))), Times.Once); + } + [TestMethod] [TestCategory(Integration)] public void GetTestsFromExecutable_SampleTestsRelease_FindsTestsWithLocation() @@ -417,7 +436,7 @@ private void AssertIsGoogleTestExecutable(string executable, bool isGoogleTestEx .Be(isGoogleTestExecutable); } - private void FindTests(string location, int expectedNrOfTestCases = TestResources.NrOfTests) + private IList FindTests(string location, int expectedNrOfTestCases = TestResources.NrOfTests) { var discoverer = new GoogleTestDiscoverer(TestEnvironment.Logger, TestEnvironment.Options); IList testCases = discoverer.GetTestsFromExecutable(location); @@ -433,6 +452,8 @@ private void FindTests(string location, int expectedNrOfTestCases = TestResource testCase.DisplayName.Should().Be("Arr/TypeParameterizedTests/1.CanDefeatMath"); testCase.CodeFilePath.Should().EndWith(@"sampletests\tests\typeparameterizedtests.cpp"); testCase.LineNumber.Should().Be(56); + + return testCases; } private void FindExternallyLinkedTests(string location) diff --git a/GoogleTestAdapter/Core.Tests/TestResults/StreamingStandardOutputTestResultParserTests.cs b/GoogleTestAdapter/Core.Tests/TestResults/StreamingStandardOutputTestResultParserTests.cs index c356ea0d1..3ecc547c9 100644 --- a/GoogleTestAdapter/Core.Tests/TestResults/StreamingStandardOutputTestResultParserTests.cs +++ b/GoogleTestAdapter/Core.Tests/TestResults/StreamingStandardOutputTestResultParserTests.cs @@ -331,6 +331,186 @@ public void GetTestResults_OutputWithConsoleOutput_ConsoleOutputIsIgnored() CheckStandardOutputResultParser(cases, consoleOutput, results, parser.CrashedTestCase); } + [TestMethod] + [TestCategory(Unit)] + public void GetTestResults_OutputWithEmptyResultCode_NoResultCodeOutputIsParsed() + { + string[] consoleOutput = { + @"[==========] Running 1 tests from 1 test case.", + @"[----------] Global test environment set-up.", + @"[----------] 1 tests from TestMath", + @"[ RUN ] TestMath.AddPasses", + @"Some output produced by the exe", + @"[ OK ] TestMath.AddPasses(0 ms)", + @"[----------] 1 tests from TestMath(26 ms total)", + @"", + @"[----------] Global test environment tear-down", + @"[==========] 3 tests from 1 test case ran. (36 ms total)", + @"[ PASSED ] 1 test.", + @"", + StreamingStandardOutputTestResultParser.GtaResultCodeOutputBegin, + StreamingStandardOutputTestResultParser.GtaResultCodeOutputEnd, + }; + var cases = GetTestCases(); + + var parser = new StreamingStandardOutputTestResultParser(cases, MockLogger.Object, MockFrameworkReporter.Object); + consoleOutput.ToList().ForEach(parser.ReportLine); + parser.Flush(); + + parser.ResultCodeOutput.Should().BeEmpty(); + } + + [TestMethod] + [TestCategory(Unit)] + public void GetTestResults_OutputWithResultCode_ResultCodeOutputIsParsed() + { + string[] consoleOutput = { + @"[==========] Running 1 tests from 1 test case.", + @"[----------] Global test environment set-up.", + @"[----------] 1 tests from TestMath", + @"[ RUN ] TestMath.AddPasses", + @"Some output produced by the exe", + @"[ OK ] TestMath.AddPasses(0 ms)", + @"[----------] 1 tests from TestMath(26 ms total)", + @"", + @"[----------] Global test environment tear-down", + @"[==========] 3 tests from 1 test case ran. (36 ms total)", + @"[ PASSED ] 1 test.", + @"", + StreamingStandardOutputTestResultParser.GtaResultCodeOutputBegin, + @"Some test output", + StreamingStandardOutputTestResultParser.GtaResultCodeOutputEnd, + }; + var cases = GetTestCases(); + + var parser = new StreamingStandardOutputTestResultParser(cases, MockLogger.Object, MockFrameworkReporter.Object); + consoleOutput.ToList().ForEach(parser.ReportLine); + parser.Flush(); + + parser.ResultCodeOutput.Should().BeEquivalentTo("Some test output"); + } + + [TestMethod] + [TestCategory(Unit)] + public void GetTestResults_OutputWithTwoLinesResultCode_ResultCodeOutputIsParsed() + { + string[] consoleOutput = { + @"[==========] Running 1 tests from 1 test case.", + @"[----------] Global test environment set-up.", + @"[----------] 1 tests from TestMath", + @"[ RUN ] TestMath.AddPasses", + @"Some output produced by the exe", + @"[ OK ] TestMath.AddPasses(0 ms)", + @"[----------] 1 tests from TestMath(26 ms total)", + @"", + @"[----------] Global test environment tear-down", + @"[==========] 3 tests from 1 test case ran. (36 ms total)", + @"[ PASSED ] 1 test.", + @"", + StreamingStandardOutputTestResultParser.GtaResultCodeOutputBegin, + "Output 1", + "Output 2", + StreamingStandardOutputTestResultParser.GtaResultCodeOutputEnd, + }; + var cases = GetTestCases(); + + var parser = new StreamingStandardOutputTestResultParser(cases, MockLogger.Object, MockFrameworkReporter.Object); + consoleOutput.ToList().ForEach(parser.ReportLine); + parser.Flush(); + + parser.ResultCodeOutput.Should().BeEquivalentTo("Output 1", "Output 2"); + } + + [TestMethod] + [TestCategory(Unit)] + public void GetTestResults_OutputWithTwoLinesResultCodeAndAdditionalOutput_ResultCodeOutputIsParsed() + { + string[] consoleOutput = { + @"[==========] Running 1 tests from 1 test case.", + @"[----------] Global test environment set-up.", + @"[----------] 1 tests from TestMath", + @"[ RUN ] TestMath.AddPasses", + @"Some output produced by the exe", + @"[ OK ] TestMath.AddPasses(0 ms)", + @"[----------] 1 tests from TestMath(26 ms total)", + @"", + @"[----------] Global test environment tear-down", + @"[==========] 3 tests from 1 test case ran. (36 ms total)", + @"[ PASSED ] 1 test.", + @"", + StreamingStandardOutputTestResultParser.GtaResultCodeOutputBegin, + "Output 1", + "Output 2", + StreamingStandardOutputTestResultParser.GtaResultCodeOutputEnd, + "Some more output" + }; + var cases = GetTestCases(); + + var parser = new StreamingStandardOutputTestResultParser(cases, MockLogger.Object, MockFrameworkReporter.Object); + consoleOutput.ToList().ForEach(parser.ReportLine); + parser.Flush(); + + parser.ResultCodeOutput.Should().BeEquivalentTo("Output 1", "Output 2"); + } + + [TestMethod] + [TestCategory(Unit)] + public void GetTestResults_OutputWithNoLinesResultCodeAndNoEnd_NoResultCodeOutputIsParsed() + { + string[] consoleOutput = { + @"[==========] Running 1 tests from 1 test case.", + @"[----------] Global test environment set-up.", + @"[----------] 1 tests from TestMath", + @"[ RUN ] TestMath.AddPasses", + @"Some output produced by the exe", + @"[ OK ] TestMath.AddPasses(0 ms)", + @"[----------] 1 tests from TestMath(26 ms total)", + @"", + @"[----------] Global test environment tear-down", + @"[==========] 3 tests from 1 test case ran. (36 ms total)", + @"[ PASSED ] 1 test.", + @"", + StreamingStandardOutputTestResultParser.GtaResultCodeOutputBegin + }; + var cases = GetTestCases(); + + var parser = new StreamingStandardOutputTestResultParser(cases, MockLogger.Object, MockFrameworkReporter.Object); + consoleOutput.ToList().ForEach(parser.ReportLine); + parser.Flush(); + + parser.ResultCodeOutput.Should().BeEmpty(); + } + + [TestMethod] + [TestCategory(Unit)] + public void GetTestResults_OutputWithTwoLinesResultCodeAndNoEnd_ResultCodeOutputIsParsed() + { + string[] consoleOutput = { + @"[==========] Running 1 tests from 1 test case.", + @"[----------] Global test environment set-up.", + @"[----------] 1 tests from TestMath", + @"[ RUN ] TestMath.AddPasses", + @"Some output produced by the exe", + @"[ OK ] TestMath.AddPasses(0 ms)", + @"[----------] 1 tests from TestMath(26 ms total)", + @"", + @"[----------] Global test environment tear-down", + @"[==========] 3 tests from 1 test case ran. (36 ms total)", + @"[ PASSED ] 1 test.", + @"", + StreamingStandardOutputTestResultParser.GtaResultCodeOutputBegin, + "Output 1", + "Output 2", + }; + var cases = GetTestCases(); + + var parser = new StreamingStandardOutputTestResultParser(cases, MockLogger.Object, MockFrameworkReporter.Object); + consoleOutput.ToList().ForEach(parser.ReportLine); + parser.Flush(); + + parser.ResultCodeOutput.Should().BeEquivalentTo("Output 1", "Output 2"); + } + [TestMethod] [TestCategory(Unit)] public void GetTestResults_OutputWithPrefixingTest_BothTestsAreFound() diff --git a/GoogleTestAdapter/Core/GoogleTestExecutor.cs b/GoogleTestAdapter/Core/GoogleTestExecutor.cs index 74eab0e7d..16733538e 100644 --- a/GoogleTestAdapter/Core/GoogleTestExecutor.cs +++ b/GoogleTestAdapter/Core/GoogleTestExecutor.cs @@ -1,13 +1,16 @@ -using System.Linq; +using System; +using System.Linq; using System.Collections.Generic; using GoogleTestAdapter.Common; using GoogleTestAdapter.Model; using GoogleTestAdapter.Runners; using GoogleTestAdapter.Framework; -using GoogleTestAdapter.ProcessExecution; +using GoogleTestAdapter.Helpers; using GoogleTestAdapter.ProcessExecution.Contracts; using GoogleTestAdapter.Scheduling; using GoogleTestAdapter.Settings; +using GoogleTestAdapter.TestCases; +using GoogleTestAdapter.TestResults; namespace GoogleTestAdapter { @@ -48,6 +51,52 @@ public void RunTests(IEnumerable testCasesToRun, ITestFrameworkReporte _runner.RunTests(testCasesToRunAsArray, isBeingDebugged, _processExecutorFactory); + if (!string.IsNullOrWhiteSpace(_settings.ReturnCodeTestCase)) + { + bool printWarning = false; + foreach (ExecutableResult executableResult in _runner.ExecutableResults) + { + var resultCodeTestCase = TestCaseFactory.CreateResultCodeTestCase(_settings.ReturnCodeTestCase, executableResult.Executable); + reporter.ReportTestsStarted(resultCodeTestCase.Yield()); + + int resultCode = executableResult.ResultCode; + if (resultCode == 0) + { + var testResult = + StreamingStandardOutputTestResultParser.CreatePassedTestResult(resultCodeTestCase, + TimeSpan.Zero); + if (executableResult.ResultCodeOutput.Any()) + { + string message = $"{Environment.NewLine}{Environment.NewLine}Output:{Environment.NewLine}"; + message += string.Join(Environment.NewLine, executableResult.ResultCodeOutput); + testResult.ErrorMessage = message; + } + + reporter.ReportTestResults(testResult.Yield()); + } + else + { + string message = $"Exit code: {resultCode}"; + if (executableResult.ResultCodeOutput.Any()) + { + message += $"{Environment.NewLine}{Environment.NewLine}Output:{Environment.NewLine}"; + message += string.Join(Environment.NewLine, executableResult.ResultCodeOutput); + } + else if (isBeingDebugged && !_settings.UseNewTestExecutionFramework) + { + printWarning = true; + } + + reporter.ReportTestResults(StreamingStandardOutputTestResultParser.CreateFailedTestResult(resultCodeTestCase, TimeSpan.Zero, message, "").Yield()); + } + } + + if (printWarning) + { + _logger.LogWarning($"Result code output can not be collected while debugging if option '{SettingsWrapper.OptionUseNewTestExecutionFramework}' is false"); + } + } + if (_settings.ParallelTestExecution) _schedulingAnalyzer.PrintStatisticsToDebugOutput(); } diff --git a/GoogleTestAdapter/Core/Runners/ITestRunner.cs b/GoogleTestAdapter/Core/Runners/ITestRunner.cs index 4435b5a2d..0b4dbd7fb 100644 --- a/GoogleTestAdapter/Core/Runners/ITestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/ITestRunner.cs @@ -1,17 +1,25 @@ using System.Collections.Generic; using GoogleTestAdapter.Model; -using GoogleTestAdapter.ProcessExecution; using GoogleTestAdapter.ProcessExecution.Contracts; namespace GoogleTestAdapter.Runners { + public class ExecutableResult + { + public string Executable { get; set; } + public int ResultCode { get; set; } + public IList ResultCodeOutput { get; set; } + } + public interface ITestRunner { void RunTests(IEnumerable testCasesToRun, bool isBeingDebugged, IDebuggedProcessExecutorFactory processExecutorFactory); void Cancel(); + + IList ExecutableResults { get; } } } \ No newline at end of file diff --git a/GoogleTestAdapter/Core/Runners/ParallelTestRunner.cs b/GoogleTestAdapter/Core/Runners/ParallelTestRunner.cs index 18d7b95d8..af7af57d3 100644 --- a/GoogleTestAdapter/Core/Runners/ParallelTestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/ParallelTestRunner.cs @@ -1,5 +1,6 @@ // This file has been modified by Microsoft on 6/2017. +using System; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -7,7 +8,6 @@ using GoogleTestAdapter.Scheduling; using GoogleTestAdapter.Model; using GoogleTestAdapter.Framework; -using GoogleTestAdapter.ProcessExecution; using GoogleTestAdapter.ProcessExecution.Contracts; using GoogleTestAdapter.Settings; @@ -45,8 +45,28 @@ public void RunTests(IEnumerable testCasesToRun, bool isBeingDebugged, { thread.Join(); } + + foreach (IGrouping results in _testRunners.SelectMany(r => r.ExecutableResults).GroupBy(r => r.Executable)) + { + var completeOutput = new List(); + foreach (ExecutableResult result in results) + { + completeOutput.Add(Environment.NewLine); + completeOutput.AddRange(result.ResultCodeOutput); + } + completeOutput.RemoveAt(0); + + ExecutableResults.Add(new ExecutableResult + { + Executable = results.Key, + ResultCode = results.Max(r => r.ResultCode), + ResultCodeOutput = completeOutput + }); + } } + public IList ExecutableResults { get; } = new List(); + public void Cancel() { lock (this) diff --git a/GoogleTestAdapter/Core/Runners/PreparingTestRunner.cs b/GoogleTestAdapter/Core/Runners/PreparingTestRunner.cs index 284d17c99..45138c899 100644 --- a/GoogleTestAdapter/Core/Runners/PreparingTestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/PreparingTestRunner.cs @@ -74,6 +74,8 @@ public void RunTests(IEnumerable testCasesToRun, bool isBeingDebugged, } } + public IList ExecutableResults => _innerTestRunner.ExecutableResults; + public void Cancel() { _innerTestRunner.Cancel(); diff --git a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs index fc6a6c64d..5b2352b35 100644 --- a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs @@ -67,6 +67,8 @@ public void RunTests(IEnumerable testCasesToRun, bool isBeingDebugged, } } + public IList ExecutableResults { get; } = new List(); + public void Cancel() { _canceled = true; @@ -196,7 +198,7 @@ void OnNewOutputLine(string line) ? processExecutorFactory.CreateNativeDebuggingExecutor(printTestOutput, _logger) : processExecutorFactory.CreateFrameworkDebuggingExecutor(printTestOutput, _logger) : processExecutorFactory.CreateExecutor(printTestOutput, _logger); - _processExecutor.ExecuteCommandBlocking( + int resultCode = _processExecutor.ExecuteCommandBlocking( executable, arguments.CommandLine, workingDir, pathExtension, isTestOutputAvailable ? (Action) OnNewOutputLine : null); streamingParser.Flush(); @@ -204,6 +206,13 @@ void OnNewOutputLine(string line) if (printTestOutput) _logger.LogInfo($"{_threadName}<<<<<<<<<<<<<<< End of Output"); + ExecutableResults.Add(new ExecutableResult + { + Executable = executable, + ResultCode = resultCode, + ResultCodeOutput = streamingParser.ResultCodeOutput + }); + var consoleOutput = new List(); new TestDurationSerializer().UpdateTestDurations(streamingParser.TestResults); _logger.DebugInfo( @@ -211,7 +220,7 @@ void OnNewOutputLine(string line) foreach (TestResult result in streamingParser.TestResults) { if (!_schedulingAnalyzer.AddActualDuration(result.TestCase, (int) result.Duration.TotalMilliseconds)) - _logger.LogWarning($"{_threadName}TestCase already in analyzer: {result.TestCase.FullyQualifiedName}"); + _logger.DebugWarning($"{_threadName}TestCase already in analyzer: {result.TestCase.FullyQualifiedName}"); } return consoleOutput; } diff --git a/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs b/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs index c873155b9..60bc4c4f1 100644 --- a/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs +++ b/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs @@ -45,6 +45,7 @@ public interface IGoogleTestAdapterSettings bool? ShowReleaseNotes { get; set; } bool? KillProcessesOnCancel { get; set; } bool? SkipOriginCheck { get; set; } + string ReturnCodeTestCase { get; set; } bool? UseNewTestExecutionFramework { get; set; } @@ -85,6 +86,7 @@ public static void GetUnsetValuesFrom(this IGoogleTestAdapterSettings self, IGoo self.ShowReleaseNotes = self.ShowReleaseNotes ?? other.ShowReleaseNotes; self.KillProcessesOnCancel = self.KillProcessesOnCancel ?? other.KillProcessesOnCancel; self.SkipOriginCheck = self.SkipOriginCheck ?? other.SkipOriginCheck; + self.ReturnCodeTestCase = self.ReturnCodeTestCase ?? other.ReturnCodeTestCase; self.UseNewTestExecutionFramework = self.UseNewTestExecutionFramework ?? other.UseNewTestExecutionFramework; diff --git a/GoogleTestAdapter/Core/Settings/RunSettings.cs b/GoogleTestAdapter/Core/Settings/RunSettings.cs index f83c72aac..7e5a4efe7 100644 --- a/GoogleTestAdapter/Core/Settings/RunSettings.cs +++ b/GoogleTestAdapter/Core/Settings/RunSettings.cs @@ -95,6 +95,9 @@ public RunSettings(string projectRegex) public bool? SkipOriginCheck { get; set; } public bool ShouldSerializeSkipOriginCheck() { return SkipOriginCheck != null; } + public string ReturnCodeTestCase { get; set; } + public bool ShouldSerializeReturnCodeTestCase() { return ReturnCodeTestCase != null; } + public virtual bool? UseNewTestExecutionFramework { get; set; } public bool ShouldSerializeUseNewTestExecutionFramework() { return UseNewTestExecutionFramework != null; } diff --git a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs index 6731e4b3a..208e6a422 100644 --- a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs +++ b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs @@ -574,6 +574,14 @@ public string GetBatchForTestTeardown(string testDirectory, int threadId) public virtual bool SkipOriginCheck => _currentSettings.SkipOriginCheck ?? OptionSkipOriginCheckDefaultValue; + + public const string OptionReturnCodeTestCase = "Exit code test case"; + public const string OptionReturnCodeTestCaseDefaultValue = ""; + public const string OptionReturnCodeTestCaseDescription = + "If non-empty, an additional test case will be generated per test executable that passes if and only if the test executable returns exit code 0."; + + public virtual string ReturnCodeTestCase => _currentSettings.ReturnCodeTestCase ?? OptionReturnCodeTestCaseDefaultValue; + #endregion #region ParallelizationOptionsPage diff --git a/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs b/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs index 5a37f461a..a385d2b29 100644 --- a/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs +++ b/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs @@ -75,7 +75,7 @@ public IList CreateTestCases(Action reportTestCase = null) }; string workingDir = _settings.GetWorkingDirForDiscovery(_executable); - var finalParams = GetDiscoveryParams(); + var finalParams = GetDiscoveryParams(); try { int processExitCode = ExecutionFailed; @@ -115,8 +115,18 @@ void OnReportOutputLine(string line) } } - if (!CheckProcessExitCode(processExitCode, standardOutput, workingDir, finalParams)) + if (!string.IsNullOrWhiteSpace(_settings.ReturnCodeTestCase)) + { + var resultCodeTestCase = CreateResultCodeTestCase(); + resultCodeTestCase.Properties.Add(new TestCaseMetaDataProperty(1, 1)); + testCases.Add(resultCodeTestCase); + reportTestCase?.Invoke(resultCodeTestCase); + _logger.DebugInfo($"Exit code of test executable is ignored because option '{SettingsWrapper.OptionReturnCodeTestCase}' is set"); + } + else if (!CheckProcessExitCode(processExitCode, standardOutput, workingDir, finalParams)) + { return new List(); + } } catch (Exception e) { @@ -126,6 +136,17 @@ void OnReportOutputLine(string line) return testCases; } + private TestCase CreateResultCodeTestCase() + { + return CreateResultCodeTestCase(_settings.ReturnCodeTestCase, _executable); + } + + public static TestCase CreateResultCodeTestCase(string name, string executable) + { + string testCaseName = $"{Path.GetFileName(executable).Replace(".", "_")}.{name}"; + return new TestCase(testCaseName, executable, testCaseName, "", 0); + } + private string GetDiscoveryParams() { string finalParams = GoogleTestConstants.ListTestsOption; diff --git a/GoogleTestAdapter/Core/TestResults/StreamingStandardOutputTestResultParser.cs b/GoogleTestAdapter/Core/TestResults/StreamingStandardOutputTestResultParser.cs index 6ed27bc35..712369948 100644 --- a/GoogleTestAdapter/Core/TestResults/StreamingStandardOutputTestResultParser.cs +++ b/GoogleTestAdapter/Core/TestResults/StreamingStandardOutputTestResultParser.cs @@ -17,6 +17,9 @@ public class StreamingStandardOutputTestResultParser private const string Passed = "[ OK ]"; private const string Skipped = "[ SKIPPED ]"; + public const string GtaResultCodeOutputBegin = "GTA_RESULT_CODE_OUTPUT_BEGIN"; + public const string GtaResultCodeOutputEnd = "GTA_RESULT_CODE_OUTPUT_END"; + public const string CrashText = "!! This test has probably CRASHED !!"; /// @@ -31,12 +34,14 @@ public class StreamingStandardOutputTestResultParser public TestCase CrashedTestCase { get; private set; } public IList TestResults { get; } = new List(); + public IList ResultCodeOutput { get; } = new List(); private readonly List _testCasesRun; private readonly ILogger _logger; private readonly ITestFrameworkReporter _reporter; private readonly List _consoleOutput = new List(); + private bool _isParsingResultCodeOutput; static StreamingStandardOutputTestResultParser() { @@ -73,15 +78,33 @@ public void ReportLine(string line) private void DoReportLine(string line) { - if (IsRunLine(line)) + if (IsRunLine(line) || line.StartsWith(GtaResultCodeOutputBegin)) { if (_consoleOutput.Count > 0) { ReportTestResult(); _consoleOutput.Clear(); } - ReportTestStart(line); + + if (IsRunLine(line)) + { + ReportTestStart(line); + } + else + { + _isParsingResultCodeOutput = true; + return; + } } + + if (line.StartsWith(GtaResultCodeOutputEnd)) + { + _consoleOutput.ForEach(l => ResultCodeOutput.Add(l)); + _consoleOutput.Clear(); + _isParsingResultCodeOutput = false; + return; + } + _consoleOutput.Add(line); } @@ -89,7 +112,16 @@ public void Flush() { if (_consoleOutput.Count > 0) { - ReportTestResult(); + if (_isParsingResultCodeOutput) + { + _consoleOutput.ForEach(l => ResultCodeOutput.Add(l)); + _isParsingResultCodeOutput = false; + } + else + { + ReportTestResult(); + } + _consoleOutput.Clear(); } } @@ -208,7 +240,7 @@ public static TimeSpan NormalizeDuration(TimeSpan duration) : duration; } - private TestResult CreatePassedTestResult(TestCase testCase, TimeSpan duration) + public static TestResult CreatePassedTestResult(TestCase testCase, TimeSpan duration) { return new TestResult(testCase) { @@ -230,7 +262,7 @@ private TestResult CreateSkippedTestResult(TestCase testCase, TimeSpan duration) }; } - private TestResult CreateFailedTestResult(TestCase testCase, TimeSpan duration, string errorMessage, string errorStackTrace) + public static TestResult CreateFailedTestResult(TestCase testCase, TimeSpan duration, string errorMessage, string errorStackTrace) { return new TestResult(testCase) { diff --git a/GoogleTestAdapter/GoogleTestAdapter.sln b/GoogleTestAdapter/GoogleTestAdapter.sln index 795cd0824..ef468f2ae 100644 --- a/GoogleTestAdapter/GoogleTestAdapter.sln +++ b/GoogleTestAdapter/GoogleTestAdapter.sln @@ -161,6 +161,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Donations", "Donations", "{ Web\Donations\thinkpad_t580.png = Web\Donations\thinkpad_t580.png EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LeakCheckTests", "..\SampleTests\LeakCheckTests\LeakCheckTests.vcxproj", "{41791F46-44CF-459B-9F77-049CE1C9D203}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution VsPackage.Shared\VsPackage.Shared.projitems*{55294b5f-a075-43f2-b0e9-2b11925e8b91}*SharedItemsImports = 4 @@ -584,6 +586,16 @@ Global {05C435E1-603C-4402-B28C-E54932F3131C}.Release|x64.Deploy.0 = Release|x64 {05C435E1-603C-4402-B28C-E54932F3131C}.Release|x86.ActiveCfg = Release|x64 {05C435E1-603C-4402-B28C-E54932F3131C}.Release|x86.Build.0 = Release|x64 + {41791F46-44CF-459B-9F77-049CE1C9D203}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {41791F46-44CF-459B-9F77-049CE1C9D203}.Debug|x64.ActiveCfg = Debug|x64 + {41791F46-44CF-459B-9F77-049CE1C9D203}.Debug|x64.Build.0 = Debug|x64 + {41791F46-44CF-459B-9F77-049CE1C9D203}.Debug|x86.ActiveCfg = Debug|Win32 + {41791F46-44CF-459B-9F77-049CE1C9D203}.Debug|x86.Build.0 = Debug|Win32 + {41791F46-44CF-459B-9F77-049CE1C9D203}.Release|Any CPU.ActiveCfg = Release|Win32 + {41791F46-44CF-459B-9F77-049CE1C9D203}.Release|x64.ActiveCfg = Release|x64 + {41791F46-44CF-459B-9F77-049CE1C9D203}.Release|x64.Build.0 = Release|x64 + {41791F46-44CF-459B-9F77-049CE1C9D203}.Release|x86.ActiveCfg = Release|Win32 + {41791F46-44CF-459B-9F77-049CE1C9D203}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -620,6 +632,7 @@ Global {05C435E1-603C-4402-B28C-E54932F3131C} = {475245AA-A07D-41D8-BC84-959C5E12A52C} {883EFE71-6B36-4813-B1DB-80D9B972B8D5} = {1F754A4D-BD42-4368-8B90-F3C03F24A2F3} {58B6EF41-D226-40A9-A959-0543270D572F} = {883EFE71-6B36-4813-B1DB-80D9B972B8D5} + {41791F46-44CF-459B-9F77-049CE1C9D203} = {1FF56AF6-0ACE-4FE8-B802-4832703EC2DC} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C942DDD5-B04E-4D57-BA9F-A444392C9480} diff --git a/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings b/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings index 799070177..b42d41ced 100644 --- a/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings +++ b/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings @@ -29,6 +29,8 @@ true true false + + diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestDiscovererTests.cs b/GoogleTestAdapter/TestAdapter.Tests/TestDiscovererTests.cs index 390a0ad8e..7f88bce05 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestDiscovererTests.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestDiscovererTests.cs @@ -76,6 +76,7 @@ private void MarkUntrusted(string path) [TestCategory(Integration)] public void DiscoverTests_UntrustedExecutableWithSkipOriginCheck_IsRun() { + // ReSharper disable once AssignNullToNotNullAttribute var semPath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(TestResources.SemaphoreExe), "SemaphoreExe.sem")); // ReSharper disable once AssignNullToNotNullAttribute var temp2Exe = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(TestResources.SemaphoreExe), "Temp2.exe")); diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorParallelTests.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorParallelTests.cs index 3ae650f83..2ebd3c033 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorParallelTests.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorParallelTests.cs @@ -160,6 +160,18 @@ public override void RunTests_WithoutPathExtension_ExecutionFails() base.RunTests_WithoutPathExtension_ExecutionFails(); } + [TestMethod] + public override void RunTests_ResultCodeTest_PassingTestResultIsProduced() + { + base.RunTests_ResultCodeTest_PassingTestResultIsProduced(); + } + + [TestMethod] + public override void RunTests_ResultCodeTest_FailingTestResultIsProduced() + { + base.RunTests_ResultCodeTest_FailingTestResultIsProduced(); + } + #endregion } diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests.cs index 5f803d43e..bdafbeaa9 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests.cs @@ -183,6 +183,18 @@ public override void RunTests_WithoutPathExtension_ExecutionFails() base.RunTests_WithoutPathExtension_ExecutionFails(); } + [TestMethod] + public override void RunTests_ResultCodeTest_PassingTestResultIsProduced() + { + base.RunTests_ResultCodeTest_PassingTestResultIsProduced(); + } + + [TestMethod] + public override void RunTests_ResultCodeTest_FailingTestResultIsProduced() + { + base.RunTests_ResultCodeTest_FailingTestResultIsProduced(); + } + #endregion } diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs index 752492f1c..27236f3b5 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs @@ -186,6 +186,18 @@ public override void RunTests_CancelingExecutor_StopsTestExecution() base.RunTests_CancelingExecutor_StopsTestExecution(); } + [TestMethod] + public override void RunTests_ResultCodeTest_PassingTestResultIsProduced() + { + base.RunTests_ResultCodeTest_PassingTestResultIsProduced(); + } + + [TestMethod] + public override void RunTests_ResultCodeTest_FailingTestResultIsProduced() + { + base.RunTests_ResultCodeTest_FailingTestResultIsProduced(); + } + #endregion } } \ No newline at end of file diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs index 12f9f9973..b274aaaea 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs @@ -1,12 +1,16 @@ using System; +using System.IO; using System.Linq; using FluentAssertions; +using GoogleTestAdapter.DiaResolver; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using GoogleTestAdapter.Helpers; using GoogleTestAdapter.Runners; using GoogleTestAdapter.Model; +using GoogleTestAdapter.ProcessExecution; using GoogleTestAdapter.Settings; +using GoogleTestAdapter.TestResults; using GoogleTestAdapter.Tests.Common; using VsTestCase = Microsoft.VisualStudio.TestPlatform.ObjectModel.TestCase; using VsTestResult = Microsoft.VisualStudio.TestPlatform.ObjectModel.TestResult; @@ -93,6 +97,20 @@ public virtual void RunTests_WorkingDir_IsSetCorrectly() RunAndVerifySingleTest(testCase, VsTestOutcome.Passed); } + [TestMethod] + [TestCategory(Integration)] + public virtual void RunTests_ResultCodeTest_FailingTestResultIsProduced() + { + RunResultCodeTest("TestMath.AddFails", VsTestOutcome.Failed); + } + + [TestMethod] + [TestCategory(Integration)] + public virtual void RunTests_ResultCodeTest_PassingTestResultIsProduced() + { + RunResultCodeTest("TestMath.AddPasses", VsTestOutcome.Passed); + } + [TestMethod] [TestCategory(Integration)] public virtual void RunTests_ExternallyLinkedX86Tests_CorrectTestResults() @@ -275,6 +293,125 @@ protected void RunAndVerifyTests(string executable, int nrOfPassedTests, int nrO CheckMockInvocations(nrOfPassedTests, nrOfFailedTests, nrOfUnexecutedTests, nrOfSkippedTests); } + [TestMethod] + [TestCategory(Integration)] + public void MemoryLeakTests_PassingWithLeaks_CorrectResult() + { + bool outputAvailable = MockOptions.Object.UseNewTestExecutionFramework || + !MockRunContext.Object.IsBeingDebugged; + RunMemoryLeakTest(TestResources.LeakCheckTests_DebugX86, "memory_leaks.passing_and_leaking", VsTestOutcome.Passed, VsTestOutcome.Failed, + msg => msg.Contains("Exit code: 1") + && (!outputAvailable || msg.Contains("Detected memory leaks!"))); + } + + [TestMethod] + [TestCategory(Integration)] + public void MemoryLeakTests_FailingWithLeaks_CorrectResult() + { + bool outputAvailable = MockOptions.Object.UseNewTestExecutionFramework || + !MockRunContext.Object.IsBeingDebugged; + RunMemoryLeakTest(TestResources.LeakCheckTests_DebugX86, "memory_leaks.failing_and_leaking", VsTestOutcome.Failed, VsTestOutcome.Failed, + msg => msg.Contains("Exit code: 1") + && (!outputAvailable || msg.Contains("Detected memory leaks!"))); + } + + [TestMethod] + [TestCategory(Integration)] + public void MemoryLeakTests_PassingWithoutLeaks_CorrectResult() + { + RunMemoryLeakTest(TestResources.LeakCheckTests_DebugX86, "memory_leaks.passing", VsTestOutcome.Passed, VsTestOutcome.Passed, + msg => msg == null); + } + + [TestMethod] + [TestCategory(Integration)] + public void MemoryLeakTests_PassingWithoutLeaksRelease_CorrectResult() + { + bool outputAvailable = MockOptions.Object.UseNewTestExecutionFramework || + !MockRunContext.Object.IsBeingDebugged; + RunMemoryLeakTest(TestResources.LeakCheckTests_ReleaseX86, "memory_leaks.passing_and_leaking", VsTestOutcome.Passed, VsTestOutcome.Passed, + msg => !outputAvailable || msg.Contains("Memory leak detection is only performed if compiled with Debug configuration.")); + } + + //[TestMethod] + //[TestCategory(Integration)] + //public void FooTest4() + //{ + // RunMemoryLeakTest(TestResources.LeakCheckTests_DebugX86, "memory_leaks.failing", VsTestOutcome.Passed, VsTestOutcome.Passed); + //} + + private void RunMemoryLeakTest(string executable, string testCaseName, VsTestOutcome testOutcome, VsTestOutcome leakCheckOutcome, Func errorMessagePredicate) + { + string resultCodeTestName = "MemoryLeakTest"; + MockOptions.Setup(o => o.ReturnCodeTestCase).Returns(resultCodeTestName); + MockOptions.Setup(o => o.AdditionalTestExecutionParam).Returns("-is_run_by_gta"); + + var testCases = new GoogleTestDiscoverer(MockLogger.Object, TestEnvironment.Options, + new ProcessExecutorFactory(), new DefaultDiaResolverFactory()).GetTestsFromExecutable(executable); + var testCase = testCases.Single(tc => tc.DisplayName == testCaseName); + + var executor = new TestExecutor(TestEnvironment.Logger, TestEnvironment.Options); + executor.RunTests(testCase.Yield().Select(tc => tc.ToVsTestCase()), MockRunContext.Object, MockFrameworkHandle.Object); + + MockFrameworkHandle.Verify(h => h.RecordResult(It.Is(result => + result.TestCase.FullyQualifiedName == testCaseName + && result.Outcome == testOutcome + )), + Times.Once); + + MockFrameworkHandle.Verify(h => h.RecordResult(It.Is(result => + result.TestCase.FullyQualifiedName.EndsWith("MemoryLeakTest") + && result.Outcome == leakCheckOutcome + && (result.ErrorMessage == null || !result.ErrorMessage.Contains(StreamingStandardOutputTestResultParser.GtaResultCodeOutputBegin)) + && (result.ErrorMessage == null || !result.ErrorMessage.Contains(StreamingStandardOutputTestResultParser.GtaResultCodeOutputEnd)) + && errorMessagePredicate(result.ErrorMessage) + )), + Times.Once); + } + + private void RunResultCodeTest(string testCaseName, VsTestOutcome outcome) + { + string resultCodeTestName = "ResultCode"; + MockOptions.Setup(o => o.ReturnCodeTestCase).Returns(resultCodeTestName); + + TestCase testCase = TestDataCreator.GetTestCases(testCaseName).First(); + + TestExecutor executor = new TestExecutor(TestEnvironment.Logger, TestEnvironment.Options); + executor.RunTests(testCase.ToVsTestCase().Yield(), MockRunContext.Object, MockFrameworkHandle.Object); + + MockFrameworkHandle.Verify(h => h.RecordResult(It.Is(result => + result.TestCase.FullyQualifiedName == testCaseName + && result.Outcome == outcome + )), + Times.Once); + + // ReSharper disable once PossibleNullReferenceException + string finalName = Path.GetFileName(testCase.Source).Replace(".", "_") + "." + resultCodeTestName; + bool outputAvailable = MockOptions.Object.UseNewTestExecutionFramework || + !MockRunContext.Object.IsBeingDebugged; + Func errorMessagePredicate = outcome == VsTestOutcome.Failed + ? result => result.ErrorMessage.Contains("Exit code: 1") + && (!outputAvailable || result.ErrorMessage.Contains("The result code output")) + && !result.ErrorMessage.Contains(StreamingStandardOutputTestResultParser.GtaResultCodeOutputBegin) + && !result.ErrorMessage.Contains(StreamingStandardOutputTestResultParser.GtaResultCodeOutputEnd) + && !result.ErrorMessage.Contains("Some more output") + : (Func) (result => result.ErrorMessage == null); + MockFrameworkHandle.Verify(h => h.RecordResult(It.Is(result => + result.TestCase.FullyQualifiedName == finalName + && result.Outcome == outcome + && errorMessagePredicate(result) + )), + Times.Once); + + MockFrameworkHandle.Verify(h => h.RecordResult(It.IsAny()), Times.Exactly(2)); + + if (!outputAvailable && outcome == VsTestOutcome.Failed) + { + MockLogger.Verify(l => l.LogWarning(It.Is(msg => msg.Contains("Result code") + && msg.Contains(SettingsWrapper.OptionUseNewTestExecutionFramework))), Times.Once); + } + } + } } \ No newline at end of file diff --git a/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd b/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd index 4040bbe42..b7012a803 100644 --- a/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd +++ b/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd @@ -77,7 +77,7 @@ Corresponds to option 'Use native debugging' - + Only for internal use diff --git a/GoogleTestAdapter/Tests.Common/TestResources.cs b/GoogleTestAdapter/Tests.Common/TestResources.cs index 9bc2816d3..7242eef73 100644 --- a/GoogleTestAdapter/Tests.Common/TestResources.cs +++ b/GoogleTestAdapter/Tests.Common/TestResources.cs @@ -61,6 +61,9 @@ public static class TestResources public const string DllTestsDll_ReleaseX64 = SampleTestsBuildDir + @"Release-x64\DllProject.dll"; public const int NrOfDllTests = 2; + public const string LeakCheckTests_DebugX86 = SampleTestsBuildDir + @"Debug\LeakCheckTests_gta.exe"; + public const string LeakCheckTests_ReleaseX86 = SampleTestsBuildDir + @"Release\LeakCheckTests_gta.exe"; + public const string SucceedingBatch = @"Tests\Returns0.bat"; public const string FailingBatch = @"Tests\Returns1.bat"; diff --git a/GoogleTestAdapter/Tests.Common/Tests/ProcessExecutorTests.cs b/GoogleTestAdapter/Tests.Common/Tests/ProcessExecutorTests.cs index 6ffd1953f..23cf1fc1b 100644 --- a/GoogleTestAdapter/Tests.Common/Tests/ProcessExecutorTests.cs +++ b/GoogleTestAdapter/Tests.Common/Tests/ProcessExecutorTests.cs @@ -46,7 +46,7 @@ protected void Test_ExecuteProcessBlocking_SampleTests() exitCode.Should().Be(1); output.Should().Contain(s => s.Contains("TestMath.AddPasses")); - output.Should().HaveCount(608); + output.Should().HaveCount(612); } protected void Test_WithSimpleCommand_ReturnsOutputOfCommand() diff --git a/GoogleTestAdapter/Tests.Common/TestsBase.cs b/GoogleTestAdapter/Tests.Common/TestsBase.cs index ffe4fd0f3..05806b0b7 100644 --- a/GoogleTestAdapter/Tests.Common/TestsBase.cs +++ b/GoogleTestAdapter/Tests.Common/TestsBase.cs @@ -92,6 +92,7 @@ public static void SetupOptions(Mock mockOptions) mockOptions.Setup(o => o.WorkingDir).Returns(SettingsWrapper.OptionWorkingDirDefaultValue); mockOptions.Setup(o => o.KillProcessesOnCancel).Returns(SettingsWrapper.OptionKillProcessesOnCancelDefaultValue); mockOptions.Setup(o => o.SkipOriginCheck).Returns(SettingsWrapper.OptionSkipOriginCheckDefaultValue); + mockOptions.Setup(o => o.ReturnCodeTestCase).Returns(SettingsWrapper.OptionReturnCodeTestCaseDefaultValue); mockOptions.Setup(o => o.UseNewTestExecutionFramework).Returns(true); diff --git a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs index 324174654..5e2795f35 100644 --- a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs @@ -240,6 +240,7 @@ private RunSettings GetRunSettingsFromOptionPages() BatchForTestTeardown = _generalOptions.BatchForTestTeardown, KillProcessesOnCancel = _generalOptions.KillProcessesOnCancel, SkipOriginCheck = _generalOptions.SkipOriginCheck, + ReturnCodeTestCase = _generalOptions.ReturnCodeTestCase, CatchExceptions = _googleTestOptions.CatchExceptions, BreakOnFailure = _googleTestOptions.BreakOnFailure, diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs index a9cf595f3..e9be7bcdb 100644 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs @@ -243,6 +243,16 @@ public bool SkipOriginCheck } private bool _skipOriginCheck = SettingsWrapper.OptionSkipOriginCheckDefaultValue; + [Category(SettingsWrapper.CategoryMiscName)] + [DisplayName(SettingsWrapper.OptionReturnCodeTestCase)] + [Description(SettingsWrapper.OptionReturnCodeTestCaseDescription)] + public string ReturnCodeTestCase + { + get { return _returnCodeTestCase; } + set { SetAndNotify(ref _returnCodeTestCase, value); } + } + private string _returnCodeTestCase = SettingsWrapper.OptionReturnCodeTestCaseDefaultValue; + #endregion } diff --git a/GoogleTestAdapter/VsPackage.Tests.Generated/GoldenFiles/ConsoleDllTests__SampleTests170_SolutionProjectSettings_Coverage_Isolation.xml b/GoogleTestAdapter/VsPackage.Tests.Generated/GoldenFiles/ConsoleDllTests__SampleTests170_SolutionProjectSettings_Coverage_Isolation.xml index 40f89ad16..b10ea1866 100644 --- a/GoogleTestAdapter/VsPackage.Tests.Generated/GoldenFiles/ConsoleDllTests__SampleTests170_SolutionProjectSettings_Coverage_Isolation.xml +++ b/GoogleTestAdapter/VsPackage.Tests.Generated/GoldenFiles/ConsoleDllTests__SampleTests170_SolutionProjectSettings_Coverage_Isolation.xml @@ -155,7 +155,7 @@ at #2 - scopedtracestests.cpp:34 in $(Directory)\sampletests\tests\scopedtracest Value of: i Actual: 1 Expected: 0 - at main.cpp:39 in $(Directory)\sampletests\tests\main.cpp:line 39 + at main.cpp:46 in $(Directory)\sampletests\tests\main.cpp:line 46 @@ -182,7 +182,7 @@ Expected: 0 Expected: 0 at #1 - scopedtracestests.cpp:49 in $(Directory)\sampletests\tests\scopedtracestests.cpp:line 49 at #2 - scopedtracestests.cpp:12 in $(Directory)\sampletests\tests\scopedtracestests.cpp:line 12 -at #3 - main.cpp:39 in $(Directory)\sampletests\tests\main.cpp:line 39 +at #3 - main.cpp:46 in $(Directory)\sampletests\tests\main.cpp:line 46 diff --git a/GoogleTestAdapter/VsPackage.Tests.Generated/GoldenFiles/ConsoleDllTests__SampleTests_SolutionProjectSettings_Coverage_Isolation.xml b/GoogleTestAdapter/VsPackage.Tests.Generated/GoldenFiles/ConsoleDllTests__SampleTests_SolutionProjectSettings_Coverage_Isolation.xml index 04f05157f..fc114672f 100644 --- a/GoogleTestAdapter/VsPackage.Tests.Generated/GoldenFiles/ConsoleDllTests__SampleTests_SolutionProjectSettings_Coverage_Isolation.xml +++ b/GoogleTestAdapter/VsPackage.Tests.Generated/GoldenFiles/ConsoleDllTests__SampleTests_SolutionProjectSettings_Coverage_Isolation.xml @@ -170,7 +170,7 @@ at #2 - scopedtracestests.cpp:34 in $(Directory)\sampletests\tests\scopedtracest 0 i Which is: 1 - at main.cpp:39 in $(Directory)\sampletests\tests\main.cpp:line 39 + at main.cpp:46 in $(Directory)\sampletests\tests\main.cpp:line 46 @@ -201,7 +201,7 @@ at #2 - scopedtracestests.cpp:34 in $(Directory)\sampletests\tests\scopedtracest Which is: 1 at #1 - scopedtracestests.cpp:49 in $(Directory)\sampletests\tests\scopedtracestests.cpp:line 49 at #2 - scopedtracestests.cpp:12 in $(Directory)\sampletests\tests\scopedtracestests.cpp:line 12 -at #3 - main.cpp:39 in $(Directory)\sampletests\tests\main.cpp:line 39 +at #3 - main.cpp:46 in $(Directory)\sampletests\tests\main.cpp:line 46 diff --git a/SampleTests/LeakCheckTests/LeakCheckTests.cpp b/SampleTests/LeakCheckTests/LeakCheckTests.cpp new file mode 100644 index 000000000..bacd2f7d4 --- /dev/null +++ b/SampleTests/LeakCheckTests/LeakCheckTests.cpp @@ -0,0 +1,140 @@ +#include "gtest/gtest.h" +#include +#include +#include + +// construct new singleton instance on first allocation, to perform memory leak reporting on destruction +// construction is performed in overridden 'new' operator (see Common\stdafx.cpp) to ensure its initialized +// before first allocation +namespace gsi +{ + namespace diag + { + class EnableLeakCheck + { + public: + static void Initialize() + { + static EnableLeakCheck leakReporter; + } + private: + EnableLeakCheck() {} + ~EnableLeakCheck() + { + _CrtDumpMemoryLeaks(); + } + }; + } +} + +void InitializeLeakCheck_() +{ + gsi::diag::EnableLeakCheck::Initialize(); +} + +#undef new + +void* operator new(size_t size) //throw( std::bad_alloc ) +{ + InitializeLeakCheck_(); + return malloc(size); +} + +void* operator new[](size_t const size) +{ + InitializeLeakCheck_(); + return operator new(size); +} + + +bool is_run_by_gta = false; + + +namespace +{ + template inline size_t lengthof(T const (&array)[N]) { return N; } + template struct lengthof_sizer + { + unsigned char count[N]; + }; + template< class T, int N > inline lengthof_sizer lengthof_get_sizer(T const (&array)[N]) { return lengthof_sizer(); } + #define LENGTHOF( a ) sizeof( lengthof_get_sizer( a ).count ) + + class ShutdownReportHook + { + public: + static void RegisterMemoryLeakAssertOnExit() + { + _CrtSetReportHookW2(_CRT_RPTHOOK_INSTALL, &RunHook_); + } + private: + static int RunHook_ + ( + int reportType, + wchar_t *message, + int *returnValue + ) + { + // Detect when the memory leak dump is starting, and flag for special processing of leak reports. + const wchar_t szStartDumpString[] = L"Detected memory leaks!"; //CRT is hard coded to say "Detected memory leaks!\n" in the memory leak report + if (::wcsncmp(message, szStartDumpString, LENGTHOF(szStartDumpString) - 1) == 0) + { + if (is_run_by_gta) + std::cout << "GTA_RESULT_CODE_OUTPUT_BEGIN\n"; + std::wcout << std::wstring(message) << "\n"; + + exit(1); + } + + return 0; + } + }; +} + +struct InitCleanupOnExit +{ + InitCleanupOnExit() + { + std::atexit(&CleanupOnExit_); // Cleanup event sink on program shutdown. + } + +private: + + static void CleanupOnExit_() + { + // Memory leaks reports happen on shutdown after this point, so force them to go out via stderr + // so any parent process will see it as an error. + ShutdownReportHook::RegisterMemoryLeakAssertOnExit(); + } + +} gInitCleanupOnExit; + + +int main(int argc, char** argv) +{ + std::string prefix("-is_run_by_gta"); + + for (int i = 0; i < argc; i++) + { + std::cout << argv[i] << "\n"; + if (strncmp(argv[i], prefix.c_str(), strlen(prefix.c_str())) == 0) + { + is_run_by_gta = true; + break; + } + } + + testing::InitGoogleTest(&argc, argv); + int returnValue = RUN_ALL_TESTS(); + + #ifndef _DEBUG + if (is_run_by_gta) + { + std::cout << "GTA_RESULT_CODE_OUTPUT_BEGIN\n"; + std::cout << "Memory leak detection is only performed if compiled with Debug configuration.\n"; + } + #endif + + // memory leak detection will do exit(1) if memory leaks are found + return is_run_by_gta ? 0 : returnValue; +} \ No newline at end of file diff --git a/SampleTests/LeakCheckTests/LeakCheckTests.vcxproj b/SampleTests/LeakCheckTests/LeakCheckTests.vcxproj new file mode 100644 index 000000000..6b39db3f0 --- /dev/null +++ b/SampleTests/LeakCheckTests/LeakCheckTests.vcxproj @@ -0,0 +1,178 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {41791F46-44CF-459B-9F77-049CE1C9D203} + Win32Proj + LeakCheckTests + 10.0.17763.0 + + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + LeakCheckTests_gta + $(EnlistmentRoot)out\binaries\$(SolutionName)\$(Configuration)$(PlatformSuffix)\ + $(EnlistmentRoot)out\intermediate\$(SolutionName)\$(Configuration)\$(MSBuildProjectName)\ + + + true + LeakCheckTests_gta + $(EnlistmentRoot)out\binaries\$(SolutionName)\$(Configuration)$(PlatformSuffix)\ + $(EnlistmentRoot)out\intermediate\$(SolutionName)\$(Configuration)\$(MSBuildProjectName)\ + + + false + LeakCheckTests_gta + $(EnlistmentRoot)out\binaries\$(SolutionName)\$(Configuration)$(PlatformSuffix)\ + $(EnlistmentRoot)out\intermediate\$(SolutionName)\$(Configuration)\$(MSBuildProjectName)\ + + + false + LeakCheckTests_gta + $(EnlistmentRoot)out\binaries\$(SolutionName)\$(Configuration)$(PlatformSuffix)\ + $(EnlistmentRoot)out\intermediate\$(SolutionName)\$(Configuration)\$(MSBuildProjectName)\ + + + + NotUsing + Level3 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + $(ProjectDir)..\3rdparty\gtest-1.8.1\fused-src;%(AdditionalIncludeDirectories) + + + Console + DebugFull + + + + + NotUsing + Level3 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + $(ProjectDir)..\3rdparty\gtest-1.8.1\fused-src;%(AdditionalIncludeDirectories) + + + Console + DebugFull + + + + + NotUsing + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + $(ProjectDir)..\3rdparty\gtest-1.8.1\fused-src;%(AdditionalIncludeDirectories) + + + Console + true + true + DebugFull + + + + + NotUsing + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + $(ProjectDir)..\3rdparty\gtest-1.8.1\fused-src;%(AdditionalIncludeDirectories) + + + Console + true + true + DebugFull + + + + + + + + + + + \ No newline at end of file diff --git a/SampleTests/LeakCheckTests/LeakCheckTests.vcxproj.filters b/SampleTests/LeakCheckTests/LeakCheckTests.vcxproj.filters new file mode 100644 index 000000000..e876341ff --- /dev/null +++ b/SampleTests/LeakCheckTests/LeakCheckTests.vcxproj.filters @@ -0,0 +1,28 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/SampleTests/LeakCheckTests/test_leak.cpp b/SampleTests/LeakCheckTests/test_leak.cpp new file mode 100644 index 000000000..0a4c0d897 --- /dev/null +++ b/SampleTests/LeakCheckTests/test_leak.cpp @@ -0,0 +1,27 @@ +#include +#include "gtest\gtest.h" + +TEST(memory_leaks, passing) +{ + ASSERT_TRUE(true); +} + +// causes memory leak!? +//TEST(memory_leaks, failing) +//{ +// ASSERT_TRUE(false); +//} + +TEST(memory_leaks, passing_and_leaking) +{ + char * ch = new char[100]; + std::cout << "Leaking 100 chars...\n"; + ASSERT_TRUE(true); +} + +TEST(memory_leaks, failing_and_leaking) +{ + char * ch = new char[100]; + std::cout << "Leaking 100 chars...\n"; + ASSERT_TRUE(false); +} diff --git a/SampleTests/SampleTests.sln b/SampleTests/SampleTests.sln index 3cfecf4ec..18b43f429 100644 --- a/SampleTests/SampleTests.sln +++ b/SampleTests/SampleTests.sln @@ -31,6 +31,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DllTests", "DllDependentPro EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DllProject", "DllProject\DllProject.vcxproj", "{BAB53542-85AA-4780-9F48-2984C036189A}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LeakCheckTests", "LeakCheckTests\LeakCheckTests.vcxproj", "{41791F46-44CF-459B-9F77-049CE1C9D203}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -121,8 +123,21 @@ Global {BAB53542-85AA-4780-9F48-2984C036189A}.Release|Win32.Build.0 = Release|Win32 {BAB53542-85AA-4780-9F48-2984C036189A}.Release|x64.ActiveCfg = Release|x64 {BAB53542-85AA-4780-9F48-2984C036189A}.Release|x64.Build.0 = Release|x64 + {41791F46-44CF-459B-9F77-049CE1C9D203}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {41791F46-44CF-459B-9F77-049CE1C9D203}.Debug|Win32.ActiveCfg = Debug|Win32 + {41791F46-44CF-459B-9F77-049CE1C9D203}.Debug|Win32.Build.0 = Debug|Win32 + {41791F46-44CF-459B-9F77-049CE1C9D203}.Debug|x64.ActiveCfg = Debug|x64 + {41791F46-44CF-459B-9F77-049CE1C9D203}.Debug|x64.Build.0 = Debug|x64 + {41791F46-44CF-459B-9F77-049CE1C9D203}.Release|Any CPU.ActiveCfg = Release|Win32 + {41791F46-44CF-459B-9F77-049CE1C9D203}.Release|Win32.ActiveCfg = Release|Win32 + {41791F46-44CF-459B-9F77-049CE1C9D203}.Release|Win32.Build.0 = Release|Win32 + {41791F46-44CF-459B-9F77-049CE1C9D203}.Release|x64.ActiveCfg = Release|x64 + {41791F46-44CF-459B-9F77-049CE1C9D203}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B3435815-4855-4F5B-8ADE-F889A4CDE65B} + EndGlobalSection EndGlobal diff --git a/SampleTests/Tests/Main.cpp b/SampleTests/Tests/Main.cpp index 3cc9a9e34..9612d79b2 100644 --- a/SampleTests/Tests/Main.cpp +++ b/SampleTests/Tests/Main.cpp @@ -31,7 +31,14 @@ int main(int argc, char ** argv) } ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); + int result = RUN_ALL_TESTS(); + + std::cout << "GTA_RESULT_CODE_OUTPUT_BEGIN\n"; + std::cout << "The result code output\n"; + std::cout << "GTA_RESULT_CODE_OUTPUT_END\n"; + std::cout << "Some more output\n"; + + return result; } void CheckIfZeroInMain(int i) From b85d35c6281d5f607dbb02761754ec0015f34d50 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Fri, 22 Feb 2019 07:58:08 +0100 Subject: [PATCH 05/81] fixed tests, added method stubs for code coverage --- .../TestExecutorParallelTests.cs | 24 +++++++++++++++++++ .../TestExecutorSequentialTests.cs | 24 +++++++++++++++++++ ...cutorSequentialTests_FrameworkDebugging.cs | 24 +++++++++++++++++++ .../TestExecutorTestsBase.cs | 10 ++++---- 4 files changed, 77 insertions(+), 5 deletions(-) diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorParallelTests.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorParallelTests.cs index 2ebd3c033..780c1ceca 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorParallelTests.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorParallelTests.cs @@ -172,6 +172,30 @@ public override void RunTests_ResultCodeTest_FailingTestResultIsProduced() base.RunTests_ResultCodeTest_FailingTestResultIsProduced(); } + [TestMethod] + public override void MemoryLeakTests_FailingWithLeaks_CorrectResult() + { + base.MemoryLeakTests_FailingWithLeaks_CorrectResult(); + } + + [TestMethod] + public override void MemoryLeakTests_PassingWithLeaks_CorrectResult() + { + base.MemoryLeakTests_PassingWithLeaks_CorrectResult(); + } + + [TestMethod] + public override void MemoryLeakTests_PassingWithoutLeaksRelease_CorrectResult() + { + base.MemoryLeakTests_PassingWithoutLeaksRelease_CorrectResult(); + } + + [TestMethod] + public override void MemoryLeakTests_PassingWithoutLeaks_CorrectResult() + { + base.MemoryLeakTests_PassingWithoutLeaks_CorrectResult(); + } + #endregion } diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests.cs index bdafbeaa9..ca8e335a3 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests.cs @@ -195,6 +195,30 @@ public override void RunTests_ResultCodeTest_FailingTestResultIsProduced() base.RunTests_ResultCodeTest_FailingTestResultIsProduced(); } + [TestMethod] + public override void MemoryLeakTests_FailingWithLeaks_CorrectResult() + { + base.MemoryLeakTests_FailingWithLeaks_CorrectResult(); + } + + [TestMethod] + public override void MemoryLeakTests_PassingWithLeaks_CorrectResult() + { + base.MemoryLeakTests_PassingWithLeaks_CorrectResult(); + } + + [TestMethod] + public override void MemoryLeakTests_PassingWithoutLeaksRelease_CorrectResult() + { + base.MemoryLeakTests_PassingWithoutLeaksRelease_CorrectResult(); + } + + [TestMethod] + public override void MemoryLeakTests_PassingWithoutLeaks_CorrectResult() + { + base.MemoryLeakTests_PassingWithoutLeaks_CorrectResult(); + } + #endregion } diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs index 27236f3b5..462309d45 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs @@ -198,6 +198,30 @@ public override void RunTests_ResultCodeTest_FailingTestResultIsProduced() base.RunTests_ResultCodeTest_FailingTestResultIsProduced(); } + [TestMethod] + public override void MemoryLeakTests_FailingWithLeaks_CorrectResult() + { + base.MemoryLeakTests_FailingWithLeaks_CorrectResult(); + } + + [TestMethod] + public override void MemoryLeakTests_PassingWithLeaks_CorrectResult() + { + base.MemoryLeakTests_PassingWithLeaks_CorrectResult(); + } + + [TestMethod] + public override void MemoryLeakTests_PassingWithoutLeaksRelease_CorrectResult() + { + base.MemoryLeakTests_PassingWithoutLeaksRelease_CorrectResult(); + } + + [TestMethod] + public override void MemoryLeakTests_PassingWithoutLeaks_CorrectResult() + { + base.MemoryLeakTests_PassingWithoutLeaks_CorrectResult(); + } + #endregion } } \ No newline at end of file diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs index b274aaaea..eb6bcb69a 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs @@ -295,7 +295,7 @@ protected void RunAndVerifyTests(string executable, int nrOfPassedTests, int nrO [TestMethod] [TestCategory(Integration)] - public void MemoryLeakTests_PassingWithLeaks_CorrectResult() + public virtual void MemoryLeakTests_PassingWithLeaks_CorrectResult() { bool outputAvailable = MockOptions.Object.UseNewTestExecutionFramework || !MockRunContext.Object.IsBeingDebugged; @@ -306,7 +306,7 @@ public void MemoryLeakTests_PassingWithLeaks_CorrectResult() [TestMethod] [TestCategory(Integration)] - public void MemoryLeakTests_FailingWithLeaks_CorrectResult() + public virtual void MemoryLeakTests_FailingWithLeaks_CorrectResult() { bool outputAvailable = MockOptions.Object.UseNewTestExecutionFramework || !MockRunContext.Object.IsBeingDebugged; @@ -317,7 +317,7 @@ public void MemoryLeakTests_FailingWithLeaks_CorrectResult() [TestMethod] [TestCategory(Integration)] - public void MemoryLeakTests_PassingWithoutLeaks_CorrectResult() + public virtual void MemoryLeakTests_PassingWithoutLeaks_CorrectResult() { RunMemoryLeakTest(TestResources.LeakCheckTests_DebugX86, "memory_leaks.passing", VsTestOutcome.Passed, VsTestOutcome.Passed, msg => msg == null); @@ -325,7 +325,7 @@ public void MemoryLeakTests_PassingWithoutLeaks_CorrectResult() [TestMethod] [TestCategory(Integration)] - public void MemoryLeakTests_PassingWithoutLeaksRelease_CorrectResult() + public virtual void MemoryLeakTests_PassingWithoutLeaksRelease_CorrectResult() { bool outputAvailable = MockOptions.Object.UseNewTestExecutionFramework || !MockRunContext.Object.IsBeingDebugged; @@ -395,7 +395,7 @@ private void RunResultCodeTest(string testCaseName, VsTestOutcome outcome) && !result.ErrorMessage.Contains(StreamingStandardOutputTestResultParser.GtaResultCodeOutputBegin) && !result.ErrorMessage.Contains(StreamingStandardOutputTestResultParser.GtaResultCodeOutputEnd) && !result.ErrorMessage.Contains("Some more output") - : (Func) (result => result.ErrorMessage == null); + : (Func) (result => result.ErrorMessage == null || result.ErrorMessage.Contains("The result code output")); MockFrameworkHandle.Verify(h => h.RecordResult(It.Is(result => result.TestCase.FullyQualifiedName == finalName && result.Outcome == outcome From 25d401690113f46d4b724ff2218b40151086f6ae Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Fri, 22 Feb 2019 21:54:10 +0100 Subject: [PATCH 06/81] fixed treatment of result code tests, added settings for SampleTests solution --- GoogleTestAdapter/Core/GoogleTestExecutor.cs | 102 +++++++++++------- .../Core/Runners/SequentialTestRunner.cs | 2 +- .../Core/TestCases/TestCaseFactory.cs | 7 +- SampleTests/SampleTests.gta.runsettings | 4 + 4 files changed, 73 insertions(+), 42 deletions(-) diff --git a/GoogleTestAdapter/Core/GoogleTestExecutor.cs b/GoogleTestAdapter/Core/GoogleTestExecutor.cs index 16733538e..652d34672 100644 --- a/GoogleTestAdapter/Core/GoogleTestExecutor.cs +++ b/GoogleTestAdapter/Core/GoogleTestExecutor.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Collections.Generic; +using System.Diagnostics; using GoogleTestAdapter.Common; using GoogleTestAdapter.Model; using GoogleTestAdapter.Runners; @@ -51,54 +52,81 @@ public void RunTests(IEnumerable testCasesToRun, ITestFrameworkReporte _runner.RunTests(testCasesToRunAsArray, isBeingDebugged, _processExecutorFactory); - if (!string.IsNullOrWhiteSpace(_settings.ReturnCodeTestCase)) + HandleResultCodeTestCases(reporter, isBeingDebugged); + + if (_settings.ParallelTestExecution) + _schedulingAnalyzer.PrintStatisticsToDebugOutput(); + } + + private void HandleResultCodeTestCases(ITestFrameworkReporter reporter, bool isBeingDebugged) + { + Debug.Assert(_runner.ExecutableResults.Select(r => r.Executable).Distinct().Count() == _runner.ExecutableResults.Count); + + bool printWarning = false; + foreach (ExecutableResult executableResult in _runner.ExecutableResults) { - bool printWarning = false; - foreach (ExecutableResult executableResult in _runner.ExecutableResults) + _settings.ExecuteWithSettingsForExecutable(executableResult.Executable, () => { - var resultCodeTestCase = TestCaseFactory.CreateResultCodeTestCase(_settings.ReturnCodeTestCase, executableResult.Executable); - reporter.ReportTestsStarted(resultCodeTestCase.Yield()); - - int resultCode = executableResult.ResultCode; - if (resultCode == 0) + if (!string.IsNullOrWhiteSpace(_settings.ReturnCodeTestCase)) { - var testResult = - StreamingStandardOutputTestResultParser.CreatePassedTestResult(resultCodeTestCase, - TimeSpan.Zero); - if (executableResult.ResultCodeOutput.Any()) - { - string message = $"{Environment.NewLine}{Environment.NewLine}Output:{Environment.NewLine}"; - message += string.Join(Environment.NewLine, executableResult.ResultCodeOutput); - testResult.ErrorMessage = message; - } + var resultCodeTestCase = + TestCaseFactory.CreateResultCodeTestCase(_settings, executableResult.Executable); + reporter.ReportTestsStarted(resultCodeTestCase.Yield()); - reporter.ReportTestResults(testResult.Yield()); - } - else - { - string message = $"Exit code: {resultCode}"; - if (executableResult.ResultCodeOutput.Any()) + int resultCode = executableResult.ResultCode; + if (resultCode == 0) { - message += $"{Environment.NewLine}{Environment.NewLine}Output:{Environment.NewLine}"; - message += string.Join(Environment.NewLine, executableResult.ResultCodeOutput); - } - else if (isBeingDebugged && !_settings.UseNewTestExecutionFramework) + var testResult = CreatePassingResultCodeTestResult(resultCodeTestCase, executableResult); + reporter.ReportTestResults(testResult.Yield()); + } + else { - printWarning = true; + var testResult = CreateFailingResultCodeTestResult(resultCodeTestCase, executableResult, resultCode, isBeingDebugged, ref printWarning); + reporter.ReportTestResults(testResult.Yield()); } - - reporter.ReportTestResults(StreamingStandardOutputTestResultParser.CreateFailedTestResult(resultCodeTestCase, TimeSpan.Zero, message, "").Yield()); } - } + }, _logger); + } - if (printWarning) - { - _logger.LogWarning($"Result code output can not be collected while debugging if option '{SettingsWrapper.OptionUseNewTestExecutionFramework}' is false"); - } + if (printWarning) + { + _logger.LogWarning( + $"Result code output can not be collected while debugging if option '{SettingsWrapper.OptionUseNewTestExecutionFramework}' is false"); } + } - if (_settings.ParallelTestExecution) - _schedulingAnalyzer.PrintStatisticsToDebugOutput(); + private TestResult CreateFailingResultCodeTestResult(TestCase resultCodeTestCase, ExecutableResult executableResult, + int resultCode, bool isBeingDebugged, ref bool printWarning) + { + string message = $"Exit code: {resultCode}"; + if (executableResult.ResultCodeOutput.Any()) + { + message += $"{Environment.NewLine}{Environment.NewLine}Output:{Environment.NewLine}"; + message += string.Join(Environment.NewLine, executableResult.ResultCodeOutput); + } + else if (isBeingDebugged && !_settings.UseNewTestExecutionFramework) + { + printWarning = true; + } + + return StreamingStandardOutputTestResultParser + .CreateFailedTestResult(resultCodeTestCase, TimeSpan.Zero, message, ""); + } + + private static TestResult CreatePassingResultCodeTestResult(TestCase resultCodeTestCase, + ExecutableResult executableResult) + { + var testResult = + StreamingStandardOutputTestResultParser.CreatePassedTestResult(resultCodeTestCase, + TimeSpan.Zero); + if (executableResult.ResultCodeOutput.Any()) + { + string message = $"{Environment.NewLine}{Environment.NewLine}Output:{Environment.NewLine}"; + message += string.Join(Environment.NewLine, executableResult.ResultCodeOutput); + testResult.ErrorMessage = message; + } + + return testResult; } public void Cancel() diff --git a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs index 5b2352b35..2428fd878 100644 --- a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs @@ -87,7 +87,7 @@ private void RunTestsFromExecutable(string executable, string workingDir, string resultXmlFile = Path.GetTempFileName(); var serializer = new TestDurationSerializer(); - var generator = new CommandLineGenerator(testCasesToRun, executable.Length, userParameters, resultXmlFile, _settings); + var generator = new CommandLineGenerator(testCasesToRun.Where(tc => tc.Properties.Any(p => p is TestCaseMetaDataProperty)), executable.Length, userParameters, resultXmlFile, _settings); foreach (CommandLineGenerator.Args arguments in generator.GetCommandLines()) { if (_canceled) diff --git a/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs b/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs index a385d2b29..e55795628 100644 --- a/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs +++ b/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs @@ -118,7 +118,6 @@ void OnReportOutputLine(string line) if (!string.IsNullOrWhiteSpace(_settings.ReturnCodeTestCase)) { var resultCodeTestCase = CreateResultCodeTestCase(); - resultCodeTestCase.Properties.Add(new TestCaseMetaDataProperty(1, 1)); testCases.Add(resultCodeTestCase); reportTestCase?.Invoke(resultCodeTestCase); _logger.DebugInfo($"Exit code of test executable is ignored because option '{SettingsWrapper.OptionReturnCodeTestCase}' is set"); @@ -138,12 +137,12 @@ void OnReportOutputLine(string line) private TestCase CreateResultCodeTestCase() { - return CreateResultCodeTestCase(_settings.ReturnCodeTestCase, _executable); + return CreateResultCodeTestCase(_settings, _executable); } - public static TestCase CreateResultCodeTestCase(string name, string executable) + public static TestCase CreateResultCodeTestCase(SettingsWrapper settings, string executable) { - string testCaseName = $"{Path.GetFileName(executable).Replace(".", "_")}.{name}"; + string testCaseName = $"{Path.GetFileName(executable).Replace(".", "_")}.{settings.ReturnCodeTestCase}"; return new TestCase(testCaseName, executable, testCaseName, "", 0); } diff --git a/SampleTests/SampleTests.gta.runsettings b/SampleTests/SampleTests.gta.runsettings index 14f58bf5c..176d82c38 100644 --- a/SampleTests/SampleTests.gta.runsettings +++ b/SampleTests/SampleTests.gta.runsettings @@ -16,6 +16,10 @@ 60 + + MemoryLeakTest + -is_run_by_gta + \ No newline at end of file From cc6cf604731271bb6f65d35d50fc66852a2360a3 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sat, 23 Feb 2019 10:50:46 +0100 Subject: [PATCH 07/81] support for skipped result code tests; aggregation is done in GoogleTestExecutor; added docs; refactoring --- .../Core.Tests/GoogleTestExecutorTests.cs | 5 +- .../Settings/SettingsWrapperTests.cs | 32 ++--- GoogleTestAdapter/Core/Core.csproj | 4 + .../Core/GoogleTestDiscoverer.cs | 4 +- GoogleTestAdapter/Core/GoogleTestExecutor.cs | 83 +----------- GoogleTestAdapter/Core/Runners/ITestRunner.cs | 1 + .../Core/Runners/ParallelTestRunner.cs | 19 +-- .../Core/Runners/SequentialTestRunner.cs | 7 +- .../Core/Settings/SettingsWrapper.cs | 2 +- .../Core/TestCases/TestCaseFactory.cs | 16 +-- .../TestResults/IResultCodeTestsAggregator.cs | 10 ++ .../TestResults/IResultCodeTestsReporter.cs | 10 ++ .../TestResults/ResultCodeTestsAggregator.cs | 47 +++++++ .../TestResults/ResultCodeTestsReporter.cs | 119 ++++++++++++++++++ ...StreamingStandardOutputTestResultParser.cs | 8 ++ .../TestExecutorTestsBase.cs | 3 +- GoogleTestAdapter/TestAdapter/TestExecutor.cs | 9 +- README.md | 20 +++ SampleTests/LeakCheckTests/LeakCheckTests.cpp | 2 +- 19 files changed, 266 insertions(+), 135 deletions(-) create mode 100644 GoogleTestAdapter/Core/TestResults/IResultCodeTestsAggregator.cs create mode 100644 GoogleTestAdapter/Core/TestResults/IResultCodeTestsReporter.cs create mode 100644 GoogleTestAdapter/Core/TestResults/ResultCodeTestsAggregator.cs create mode 100644 GoogleTestAdapter/Core/TestResults/ResultCodeTestsReporter.cs diff --git a/GoogleTestAdapter/Core.Tests/GoogleTestExecutorTests.cs b/GoogleTestAdapter/Core.Tests/GoogleTestExecutorTests.cs index 4d678ed33..4f9ba1b43 100644 --- a/GoogleTestAdapter/Core.Tests/GoogleTestExecutorTests.cs +++ b/GoogleTestAdapter/Core.Tests/GoogleTestExecutorTests.cs @@ -3,6 +3,7 @@ using FluentAssertions; using GoogleTestAdapter.Model; using GoogleTestAdapter.Scheduling; +using GoogleTestAdapter.TestResults; using GoogleTestAdapter.Tests.Common; using GoogleTestAdapter.Tests.Common.Assertions; using GoogleTestAdapter.Tests.Common.Fakes; @@ -42,7 +43,9 @@ private void AssertDurationsFileIsCreated(bool parallelExecution) MockOptions.Setup(o => o.SolutionDir).Returns(TestResources.SampleTestsSolutionDir); var collectingReporter = new FakeFrameworkReporter(); - var testExecutor = new GoogleTestExecutor(TestEnvironment.Logger, TestEnvironment.Options, ProcessExecutorFactory); + var resultCodeTestsAggregator = new ResultCodeTestsAggregator(); + var resultCodeTestsReporter = new ResultCodeTestsReporter(MockFrameworkReporter.Object, resultCodeTestsAggregator, MockOptions.Object, MockLogger.Object); + var testExecutor = new GoogleTestExecutor(TestEnvironment.Logger, TestEnvironment.Options, ProcessExecutorFactory, resultCodeTestsReporter); testExecutor.RunTests(TestDataCreator.AllTestCasesExceptLoadTests, collectingReporter,false); sampleTestsDurationsFile.AsFileInfo() diff --git a/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs b/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs index abbc52a1c..deedbb7bf 100644 --- a/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs +++ b/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs @@ -551,10 +551,10 @@ public void ExecuteWithSettingsForExecutable_WithConfiguredProject_ShouldDeliver { var settings = CreateSettingsWrapper("solution_dir", "foo"); - settings.ExecuteWithSettingsForExecutable("foo", () => + settings.ExecuteWithSettingsForExecutable("foo", MockLogger.Object, () => { settings.WorkingDir.Should().Be("foo_dir"); - }, MockLogger.Object); + }); } [TestMethod] @@ -563,7 +563,7 @@ public void ExecuteWithSettingsForExecutable_WithConfiguredProject_ShouldSwitchB { var settings = CreateSettingsWrapper("solution_dir", "foo"); - settings.ExecuteWithSettingsForExecutable("foo", () => {}, MockLogger.Object); + settings.ExecuteWithSettingsForExecutable("foo", MockLogger.Object, () => {}); settings.WorkingDir.Should().Be("solution_dir"); } @@ -574,10 +574,10 @@ public void ExecuteWithSettingsForExecutable_WithUnconfiguredProject_ShouldDeliv { var settings = CreateSettingsWrapper("solution_dir", "foo"); - settings.ExecuteWithSettingsForExecutable("bar", () => + settings.ExecuteWithSettingsForExecutable("bar", MockLogger.Object, () => { settings.WorkingDir.Should().Be("solution_dir"); - }, MockLogger.Object); + }); } [TestMethod] @@ -586,14 +586,14 @@ public void ExecuteWithSettingsForExecutable_NestedExecutionOfSameExecutable_Sho { var settings = CreateSettingsWrapper("solution_dir", "foo"); - settings.ExecuteWithSettingsForExecutable("foo", () => + settings.ExecuteWithSettingsForExecutable("foo", MockLogger.Object, () => { - settings.ExecuteWithSettingsForExecutable("foo", () => + settings.ExecuteWithSettingsForExecutable("foo", MockLogger.Object, () => { settings.WorkingDir.Should().Be("foo_dir"); - }, MockLogger.Object); + }); - }, MockLogger.Object); + }); } [TestMethod] @@ -603,10 +603,10 @@ public void ExecuteWithSettingsForExecutable_NestedExecutionOfDifferentExecutabl var settings = CreateSettingsWrapper("solution_dir", "foo"); settings - .Invoking(s => s.ExecuteWithSettingsForExecutable("foo", () => + .Invoking(s => s.ExecuteWithSettingsForExecutable("foo", MockLogger.Object, () => { - s.ExecuteWithSettingsForExecutable("bar", () => { }, MockLogger.Object); - }, MockLogger.Object)) + s.ExecuteWithSettingsForExecutable("bar", MockLogger.Object, () => { }); + })) .Should().Throw(); } @@ -616,16 +616,16 @@ public void Clone_WhileExecuting_ReturnsFreshSettingsWrapperInstance() { var settings = CreateSettingsWrapper("solution_dir", "foo", "bar"); - settings.ExecuteWithSettingsForExecutable("foo", () => + settings.ExecuteWithSettingsForExecutable("foo", MockLogger.Object, () => { var settingsClone = settings.Clone(); settingsClone.WorkingDir.Should().Be("solution_dir"); - settingsClone.ExecuteWithSettingsForExecutable("bar", () => + settingsClone.ExecuteWithSettingsForExecutable("bar", MockLogger.Object, () => { settings.WorkingDir.Should().Be("foo_dir"); settingsClone.WorkingDir.Should().Be("bar_dir"); - }, MockLogger.Object); - }, MockLogger.Object); + }); + }); } private SettingsWrapper CreateSettingsWrapper(string solutionWorkdir, params string[] projects) diff --git a/GoogleTestAdapter/Core/Core.csproj b/GoogleTestAdapter/Core/Core.csproj index a1136408d..63730bf5b 100644 --- a/GoogleTestAdapter/Core/Core.csproj +++ b/GoogleTestAdapter/Core/Core.csproj @@ -99,6 +99,10 @@ + + + + diff --git a/GoogleTestAdapter/Core/GoogleTestDiscoverer.cs b/GoogleTestAdapter/Core/GoogleTestDiscoverer.cs index 72c72d95b..22563e304 100644 --- a/GoogleTestAdapter/Core/GoogleTestDiscoverer.cs +++ b/GoogleTestAdapter/Core/GoogleTestDiscoverer.cs @@ -47,7 +47,7 @@ public void DiscoverTests(IEnumerable executables, ITestFrameworkReporte private static void DiscoverTests(string executable, ITestFrameworkReporter reporter, SettingsWrapper settings, ILogger logger, IDiaResolverFactory diaResolverFactory, IProcessExecutorFactory processExecutorFactory) { - settings.ExecuteWithSettingsForExecutable(executable, () => + settings.ExecuteWithSettingsForExecutable(executable, logger, () => { if (!VerifyExecutableTrust(executable, settings, logger) || !IsGoogleTestExecutable(executable, settings.TestDiscoveryRegex, logger)) return; @@ -62,7 +62,7 @@ private static void DiscoverTests(string executable, ITestFrameworkReporter repo var factory = new TestCaseFactory(executable, logger, settings, diaResolverFactory, processExecutorFactory); factory.CreateTestCases(reportTestCases); logger.LogInfo("Found " + nrOfTestCases + " tests in executable " + executable); - }, logger); + }); } public IList GetTestsFromExecutable(string executable) diff --git a/GoogleTestAdapter/Core/GoogleTestExecutor.cs b/GoogleTestAdapter/Core/GoogleTestExecutor.cs index 652d34672..64a332f06 100644 --- a/GoogleTestAdapter/Core/GoogleTestExecutor.cs +++ b/GoogleTestAdapter/Core/GoogleTestExecutor.cs @@ -1,16 +1,12 @@ -using System; -using System.Linq; +using System.Linq; using System.Collections.Generic; -using System.Diagnostics; using GoogleTestAdapter.Common; using GoogleTestAdapter.Model; using GoogleTestAdapter.Runners; using GoogleTestAdapter.Framework; -using GoogleTestAdapter.Helpers; using GoogleTestAdapter.ProcessExecution.Contracts; using GoogleTestAdapter.Scheduling; using GoogleTestAdapter.Settings; -using GoogleTestAdapter.TestCases; using GoogleTestAdapter.TestResults; namespace GoogleTestAdapter @@ -22,16 +18,18 @@ public class GoogleTestExecutor private readonly ILogger _logger; private readonly SettingsWrapper _settings; private readonly IDebuggedProcessExecutorFactory _processExecutorFactory; + private readonly IResultCodeTestsReporter _resultCodeTestsReporter; private readonly SchedulingAnalyzer _schedulingAnalyzer; private ITestRunner _runner; private bool _canceled; - public GoogleTestExecutor(ILogger logger, SettingsWrapper settings, IDebuggedProcessExecutorFactory processExecutorFactory) + public GoogleTestExecutor(ILogger logger, SettingsWrapper settings, IDebuggedProcessExecutorFactory processExecutorFactory, IResultCodeTestsReporter resultCodeTestsReporter) { _logger = logger; _settings = settings; _processExecutorFactory = processExecutorFactory; + _resultCodeTestsReporter = resultCodeTestsReporter; _schedulingAnalyzer = new SchedulingAnalyzer(logger); } @@ -52,83 +50,12 @@ public void RunTests(IEnumerable testCasesToRun, ITestFrameworkReporte _runner.RunTests(testCasesToRunAsArray, isBeingDebugged, _processExecutorFactory); - HandleResultCodeTestCases(reporter, isBeingDebugged); + _resultCodeTestsReporter.ReportResultCodeTestCases(_runner.ExecutableResults, isBeingDebugged); if (_settings.ParallelTestExecution) _schedulingAnalyzer.PrintStatisticsToDebugOutput(); } - private void HandleResultCodeTestCases(ITestFrameworkReporter reporter, bool isBeingDebugged) - { - Debug.Assert(_runner.ExecutableResults.Select(r => r.Executable).Distinct().Count() == _runner.ExecutableResults.Count); - - bool printWarning = false; - foreach (ExecutableResult executableResult in _runner.ExecutableResults) - { - _settings.ExecuteWithSettingsForExecutable(executableResult.Executable, () => - { - if (!string.IsNullOrWhiteSpace(_settings.ReturnCodeTestCase)) - { - var resultCodeTestCase = - TestCaseFactory.CreateResultCodeTestCase(_settings, executableResult.Executable); - reporter.ReportTestsStarted(resultCodeTestCase.Yield()); - - int resultCode = executableResult.ResultCode; - if (resultCode == 0) - { - var testResult = CreatePassingResultCodeTestResult(resultCodeTestCase, executableResult); - reporter.ReportTestResults(testResult.Yield()); - } - else - { - var testResult = CreateFailingResultCodeTestResult(resultCodeTestCase, executableResult, resultCode, isBeingDebugged, ref printWarning); - reporter.ReportTestResults(testResult.Yield()); - } - } - }, _logger); - } - - if (printWarning) - { - _logger.LogWarning( - $"Result code output can not be collected while debugging if option '{SettingsWrapper.OptionUseNewTestExecutionFramework}' is false"); - } - } - - private TestResult CreateFailingResultCodeTestResult(TestCase resultCodeTestCase, ExecutableResult executableResult, - int resultCode, bool isBeingDebugged, ref bool printWarning) - { - string message = $"Exit code: {resultCode}"; - if (executableResult.ResultCodeOutput.Any()) - { - message += $"{Environment.NewLine}{Environment.NewLine}Output:{Environment.NewLine}"; - message += string.Join(Environment.NewLine, executableResult.ResultCodeOutput); - } - else if (isBeingDebugged && !_settings.UseNewTestExecutionFramework) - { - printWarning = true; - } - - return StreamingStandardOutputTestResultParser - .CreateFailedTestResult(resultCodeTestCase, TimeSpan.Zero, message, ""); - } - - private static TestResult CreatePassingResultCodeTestResult(TestCase resultCodeTestCase, - ExecutableResult executableResult) - { - var testResult = - StreamingStandardOutputTestResultParser.CreatePassedTestResult(resultCodeTestCase, - TimeSpan.Zero); - if (executableResult.ResultCodeOutput.Any()) - { - string message = $"{Environment.NewLine}{Environment.NewLine}Output:{Environment.NewLine}"; - message += string.Join(Environment.NewLine, executableResult.ResultCodeOutput); - testResult.ErrorMessage = message; - } - - return testResult; - } - public void Cancel() { lock (this) diff --git a/GoogleTestAdapter/Core/Runners/ITestRunner.cs b/GoogleTestAdapter/Core/Runners/ITestRunner.cs index 0b4dbd7fb..0e1502cbb 100644 --- a/GoogleTestAdapter/Core/Runners/ITestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/ITestRunner.cs @@ -10,6 +10,7 @@ public class ExecutableResult public string Executable { get; set; } public int ResultCode { get; set; } public IList ResultCodeOutput { get; set; } + public bool ResultCodeSkip { get; set; } } public interface ITestRunner diff --git a/GoogleTestAdapter/Core/Runners/ParallelTestRunner.cs b/GoogleTestAdapter/Core/Runners/ParallelTestRunner.cs index af7af57d3..26cffe381 100644 --- a/GoogleTestAdapter/Core/Runners/ParallelTestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/ParallelTestRunner.cs @@ -1,6 +1,5 @@ // This file has been modified by Microsoft on 6/2017. -using System; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -46,22 +45,10 @@ public void RunTests(IEnumerable testCasesToRun, bool isBeingDebugged, thread.Join(); } - foreach (IGrouping results in _testRunners.SelectMany(r => r.ExecutableResults).GroupBy(r => r.Executable)) + // ReSharper disable once InconsistentlySynchronizedField + foreach (var result in _testRunners.SelectMany(r => r.ExecutableResults)) { - var completeOutput = new List(); - foreach (ExecutableResult result in results) - { - completeOutput.Add(Environment.NewLine); - completeOutput.AddRange(result.ResultCodeOutput); - } - completeOutput.RemoveAt(0); - - ExecutableResults.Add(new ExecutableResult - { - Executable = results.Key, - ResultCode = results.Max(r => r.ResultCode), - ResultCodeOutput = completeOutput - }); + ExecutableResults.Add(result); } } diff --git a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs index 2428fd878..ed94f0aa1 100644 --- a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs @@ -50,7 +50,7 @@ public void RunTests(IEnumerable testCasesToRun, bool isBeingDebugged, if (_canceled) break; - _settings.ExecuteWithSettingsForExecutable(executable, () => + _settings.ExecuteWithSettingsForExecutable(executable, _logger, () => { string workingDir = _settings.GetWorkingDirForExecution(executable, _testDir, _threadId); string userParameters = _settings.GetUserParametersForExecution(executable, _testDir, _threadId); @@ -62,7 +62,7 @@ public void RunTests(IEnumerable testCasesToRun, bool isBeingDebugged, userParameters, isBeingDebugged, processExecutorFactory); - }, _logger); + }); } } @@ -210,7 +210,8 @@ void OnNewOutputLine(string line) { Executable = executable, ResultCode = resultCode, - ResultCodeOutput = streamingParser.ResultCodeOutput + ResultCodeOutput = streamingParser.ResultCodeOutput, + ResultCodeSkip = streamingParser.ResultCodeSkip }); var consoleOutput = new List(); diff --git a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs index 208e6a422..b43dcd954 100644 --- a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs +++ b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs @@ -73,7 +73,7 @@ public virtual SettingsWrapper Clone() // ReSharper disable once UnusedMember.Global public SettingsWrapper() { } - public void ExecuteWithSettingsForExecutable(string executable, Action action, ILogger logger) + public void ExecuteWithSettingsForExecutable(string executable, ILogger logger, Action action) { lock (_lock) { diff --git a/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs b/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs index e55795628..551cac260 100644 --- a/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs +++ b/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs @@ -12,6 +12,7 @@ using GoogleTestAdapter.ProcessExecution.Contracts; using GoogleTestAdapter.Runners; using GoogleTestAdapter.Settings; +using GoogleTestAdapter.TestResults; namespace GoogleTestAdapter.TestCases { @@ -117,10 +118,10 @@ void OnReportOutputLine(string line) if (!string.IsNullOrWhiteSpace(_settings.ReturnCodeTestCase)) { - var resultCodeTestCase = CreateResultCodeTestCase(); + var resultCodeTestCase = ResultCodeTestsReporter.CreateResultCodeTestCase(_settings, _executable); testCases.Add(resultCodeTestCase); reportTestCase?.Invoke(resultCodeTestCase); - _logger.DebugInfo($"Exit code of test executable is ignored because option '{SettingsWrapper.OptionReturnCodeTestCase}' is set"); + _logger.DebugInfo($"Exit code of executable '{_executable}' is ignored for test discovery because option '{SettingsWrapper.OptionReturnCodeTestCase}' is set"); } else if (!CheckProcessExitCode(processExitCode, standardOutput, workingDir, finalParams)) { @@ -135,17 +136,6 @@ void OnReportOutputLine(string line) return testCases; } - private TestCase CreateResultCodeTestCase() - { - return CreateResultCodeTestCase(_settings, _executable); - } - - public static TestCase CreateResultCodeTestCase(SettingsWrapper settings, string executable) - { - string testCaseName = $"{Path.GetFileName(executable).Replace(".", "_")}.{settings.ReturnCodeTestCase}"; - return new TestCase(testCaseName, executable, testCaseName, "", 0); - } - private string GetDiscoveryParams() { string finalParams = GoogleTestConstants.ListTestsOption; diff --git a/GoogleTestAdapter/Core/TestResults/IResultCodeTestsAggregator.cs b/GoogleTestAdapter/Core/TestResults/IResultCodeTestsAggregator.cs new file mode 100644 index 000000000..a8a1404ba --- /dev/null +++ b/GoogleTestAdapter/Core/TestResults/IResultCodeTestsAggregator.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using GoogleTestAdapter.Runners; + +namespace GoogleTestAdapter.TestResults +{ + public interface IResultCodeTestsAggregator + { + IEnumerable ComputeAggregatedResults(IEnumerable allResults); + } +} \ No newline at end of file diff --git a/GoogleTestAdapter/Core/TestResults/IResultCodeTestsReporter.cs b/GoogleTestAdapter/Core/TestResults/IResultCodeTestsReporter.cs new file mode 100644 index 000000000..1a865c96f --- /dev/null +++ b/GoogleTestAdapter/Core/TestResults/IResultCodeTestsReporter.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using GoogleTestAdapter.Runners; + +namespace GoogleTestAdapter.TestResults +{ + public interface IResultCodeTestsReporter + { + void ReportResultCodeTestCases(IEnumerable allResults, bool isBeingDebugged); + } +} \ No newline at end of file diff --git a/GoogleTestAdapter/Core/TestResults/ResultCodeTestsAggregator.cs b/GoogleTestAdapter/Core/TestResults/ResultCodeTestsAggregator.cs new file mode 100644 index 000000000..3c2e6e0b1 --- /dev/null +++ b/GoogleTestAdapter/Core/TestResults/ResultCodeTestsAggregator.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using GoogleTestAdapter.Runners; + +namespace GoogleTestAdapter.TestResults +{ + public class ResultCodeTestsAggregator : IResultCodeTestsAggregator + { + public IEnumerable ComputeAggregatedResults(IEnumerable allResults) + { + return allResults + .GroupBy(r => r.Executable) + .Select(results => new ExecutableResult + { + Executable = results.Key, + ResultCode = ComputeAggregatedResultCode(results), + ResultCodeOutput = ComputeAggregatedOutput(results), + ResultCodeSkip = results.All(r => r.ResultCodeSkip) + }); + } + + private List ComputeAggregatedOutput(IEnumerable results) + { + var completeOutput = new List(); + foreach (ExecutableResult result in results) + { + completeOutput.Add(Environment.NewLine); + completeOutput.AddRange(result.ResultCodeOutput); + } + + completeOutput.RemoveAt(0); + return completeOutput; + } + + [SuppressMessage("ReSharper", "PossibleMultipleEnumeration")] + private int ComputeAggregatedResultCode(IEnumerable results) + { + int minResultCode = results.Min(r => r.ResultCode); + int maxResultCode = results.Max(r => r.ResultCode); + return Math.Abs(maxResultCode) > Math.Abs(minResultCode) + ? maxResultCode + : minResultCode; + } + } +} \ No newline at end of file diff --git a/GoogleTestAdapter/Core/TestResults/ResultCodeTestsReporter.cs b/GoogleTestAdapter/Core/TestResults/ResultCodeTestsReporter.cs new file mode 100644 index 000000000..d5464983f --- /dev/null +++ b/GoogleTestAdapter/Core/TestResults/ResultCodeTestsReporter.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using GoogleTestAdapter.Common; +using GoogleTestAdapter.Framework; +using GoogleTestAdapter.Helpers; +using GoogleTestAdapter.Model; +using GoogleTestAdapter.Runners; +using GoogleTestAdapter.Settings; + +namespace GoogleTestAdapter.TestResults +{ + public class ResultCodeTestsReporter : IResultCodeTestsReporter + { + private readonly ITestFrameworkReporter _reporter; + private readonly IResultCodeTestsAggregator _resultCodeTestsAggregator; + private readonly SettingsWrapper _settings; + private readonly ILogger _logger; + + public ResultCodeTestsReporter(ITestFrameworkReporter reporter, IResultCodeTestsAggregator resultCodeTestsAggregator, + SettingsWrapper settings, ILogger logger) + { + _reporter = reporter; + _resultCodeTestsAggregator = resultCodeTestsAggregator; + _settings = settings; + _logger = logger; + } + + public static TestCase CreateResultCodeTestCase(SettingsWrapper settings, string executable) + { + string filename = Path.GetFileName(executable) ?? throw new InvalidOperationException($"Can't get filename from executable '{executable}'"); + string testCaseName = $"{filename.Replace(".", "_")}.{settings.ReturnCodeTestCase}"; + return new TestCase(testCaseName, executable, testCaseName, "", 0); + } + + public void ReportResultCodeTestCases(IEnumerable allResults, bool isBeingDebugged) + { + var aggregatedResults = _resultCodeTestsAggregator.ComputeAggregatedResults(allResults); + + bool printWarning = false; + foreach (var executableResult in aggregatedResults) + { + _settings.ExecuteWithSettingsForExecutable(executableResult.Executable, _logger, () => + { + if (!string.IsNullOrWhiteSpace(_settings.ReturnCodeTestCase)) + { + printWarning |= ReportResultCodeTestResult(executableResult, isBeingDebugged); + } + }); + } + + if (printWarning) + { + _logger.LogWarning( + $"Result code output can not be collected while debugging if option '{SettingsWrapper.OptionUseNewTestExecutionFramework}' is false"); + } + } + + private bool ReportResultCodeTestResult(ExecutableResult executableResult, bool isBeingDebugged) + { + var resultCodeTestCase = CreateResultCodeTestCase(_settings, executableResult.Executable); + _reporter.ReportTestsStarted(resultCodeTestCase.Yield()); + + TestResult testResult; + bool printWarning = false; + if (executableResult.ResultCode == 0) + { + testResult = CreatePassingResultCodeTestResult(resultCodeTestCase, executableResult); + if (executableResult.ResultCodeSkip) + { + testResult.Outcome = TestOutcome.Skipped; + } + } + else + { + testResult = CreateFailingResultCodeTestResult(resultCodeTestCase, executableResult, executableResult.ResultCode, + isBeingDebugged, out printWarning); + } + + _reporter.ReportTestResults(testResult.Yield()); + return printWarning; + } + + private TestResult CreatePassingResultCodeTestResult(TestCase resultCodeTestCase, + ExecutableResult executableResult) + { + var testResult = + StreamingStandardOutputTestResultParser.CreatePassedTestResult(resultCodeTestCase, + TimeSpan.Zero); + if (executableResult.ResultCodeOutput.Any()) + { + testResult.ErrorMessage = string.Join(Environment.NewLine, executableResult.ResultCodeOutput); + } + + return testResult; + } + + private TestResult CreateFailingResultCodeTestResult(TestCase resultCodeTestCase, ExecutableResult executableResult, + int resultCode, bool isBeingDebugged, out bool printWarning) + { + printWarning = false; + + string message = $"Exit code: {resultCode}"; + if (executableResult.ResultCodeOutput.Any()) + { + message += $"{Environment.NewLine}{Environment.NewLine}"; + message += string.Join(Environment.NewLine, executableResult.ResultCodeOutput); + } + else if (isBeingDebugged && !_settings.UseNewTestExecutionFramework) + { + printWarning = true; + } + + return StreamingStandardOutputTestResultParser + .CreateFailedTestResult(resultCodeTestCase, TimeSpan.Zero, message, ""); + } + } +} \ No newline at end of file diff --git a/GoogleTestAdapter/Core/TestResults/StreamingStandardOutputTestResultParser.cs b/GoogleTestAdapter/Core/TestResults/StreamingStandardOutputTestResultParser.cs index 712369948..b7cad441a 100644 --- a/GoogleTestAdapter/Core/TestResults/StreamingStandardOutputTestResultParser.cs +++ b/GoogleTestAdapter/Core/TestResults/StreamingStandardOutputTestResultParser.cs @@ -19,6 +19,7 @@ public class StreamingStandardOutputTestResultParser public const string GtaResultCodeOutputBegin = "GTA_RESULT_CODE_OUTPUT_BEGIN"; public const string GtaResultCodeOutputEnd = "GTA_RESULT_CODE_OUTPUT_END"; + public const string GtaResultCodeSkip = "GTA_RESULT_CODE_SKIP"; public const string CrashText = "!! This test has probably CRASHED !!"; @@ -35,6 +36,7 @@ public class StreamingStandardOutputTestResultParser public TestCase CrashedTestCase { get; private set; } public IList TestResults { get; } = new List(); public IList ResultCodeOutput { get; } = new List(); + public bool ResultCodeSkip { get; private set; } = false; private readonly List _testCasesRun; private readonly ILogger _logger; @@ -105,6 +107,12 @@ private void DoReportLine(string line) return; } + if (line.StartsWith(GtaResultCodeSkip)) + { + ResultCodeSkip = true; + return; + } + _consoleOutput.Add(line); } diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs index eb6bcb69a..1a33fba84 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs @@ -329,7 +329,8 @@ public virtual void MemoryLeakTests_PassingWithoutLeaksRelease_CorrectResult() { bool outputAvailable = MockOptions.Object.UseNewTestExecutionFramework || !MockRunContext.Object.IsBeingDebugged; - RunMemoryLeakTest(TestResources.LeakCheckTests_ReleaseX86, "memory_leaks.passing_and_leaking", VsTestOutcome.Passed, VsTestOutcome.Passed, + RunMemoryLeakTest(TestResources.LeakCheckTests_ReleaseX86, "memory_leaks.passing_and_leaking", VsTestOutcome.Passed, + outputAvailable ? VsTestOutcome.Skipped : VsTestOutcome.Passed, msg => !outputAvailable || msg.Contains("Memory leak detection is only performed if compiled with Debug configuration.")); } diff --git a/GoogleTestAdapter/TestAdapter/TestExecutor.cs b/GoogleTestAdapter/TestAdapter/TestExecutor.cs index 103b6e017..b24fecd09 100644 --- a/GoogleTestAdapter/TestAdapter/TestExecutor.cs +++ b/GoogleTestAdapter/TestAdapter/TestExecutor.cs @@ -15,6 +15,7 @@ using GoogleTestAdapter.TestAdapter.Helpers; using GoogleTestAdapter.TestAdapter.Framework; using GoogleTestAdapter.TestAdapter.ProcessExecution; +using GoogleTestAdapter.TestResults; namespace GoogleTestAdapter.TestAdapter { @@ -187,10 +188,10 @@ private static IList GetTestCasesOfExecutable(string executable, Setti return testCases; var discoverer = new GoogleTestDiscoverer(logger, settings); - settings.ExecuteWithSettingsForExecutable(executable, () => + settings.ExecuteWithSettingsForExecutable(executable, logger, () => { testCases = discoverer.GetTestsFromExecutable(executable); - }, logger); + }); return testCases; } @@ -225,13 +226,15 @@ private void DoRunTests(ICollection testCasesToRun, IRunContext runCon var debuggerAttacher = new MessageBasedDebuggerAttacher(_settings.DebuggingNamedPipeId, _logger); var processExecutorFactory = new DebuggedProcessExecutorFactory(frameworkHandle, debuggerAttacher); + var resultCodeTestsAggregator = new ResultCodeTestsAggregator(); + var resultCodeTestsReporter = new ResultCodeTestsReporter(reporter, resultCodeTestsAggregator, _settings, _logger); lock (_lock) { if (_canceled) return; - _executor = new GoogleTestExecutor(_logger, _settings, processExecutorFactory); + _executor = new GoogleTestExecutor(_logger, _settings, processExecutorFactory, resultCodeTestsReporter); } _executor.RunTests(testCasesToRun, reporter, runContext.IsBeingDebugged); reporter.AllTestsFinished(); diff --git a/README.md b/README.md index 9a365d6eb..fc82e7dab 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ Google Test Adapter (GTA) is a Visual Studio extension providing test discovery * Failed assertions and [SCOPED_TRACE](https://github.com/google/googletest/blob/master/googletest/docs/advanced.md#adding-traces-to-assertions)s are linked to their source locations * Identification of crashed tests * Test output can be piped to test console +* Exit code of test executables can be [reflected as an additional test](#evaluating_exit_code) * Execution of [parameterized batch files](#test_setup_and_teardown) for test setup/teardown * Automatic recognition of gtest executables (which can be overridden by using a [custom regex](#test_discovery_regex) or an indicator file) * Settings can be [shared via source control](#solution_settings) @@ -106,6 +107,25 @@ More precisely, traits are assigned to tests in three phases: Note that traits are assigned in an additive manner within each phase, and in an overriding manner between phases. For instance, if a test is assigned the traits *(Author,Foo)* and *(Author,Bar)* in phase 1, the test will have both traits. If the test is also assigned the trait *(Author,Baz)* in phases 2 or 3, it will only have that trait. See [test code](https://github.com/csoltenborn/GoogleTestAdapter/blob/master/GoogleTestAdapter/Core.Tests/AbstractGoogleTestDiscovererTraitTests.cs) for examples. +#### Evaluating the test executable's exit code +If option *Exit code test case* is non-empty, an additional test case will be generated per text executable, and that test case will pass if and only if the test executable's exit code is 0. This allows to reflect some additional result as a test case; for instance, the test executable might be built such that it performs memory leak detection at shutdown; the result of that check can then be seen within VS as the result of the according additional test. + +To increase usefulness of the additional tests, a couple of tokens can used as part of a test executable's output; if GTA sees theses tokens, it will act accordingly: +* `GTA_RESULT_CODE_OUTPUT_BEGIN`: This token will make GTA capture the following output and add it to the additional test case as error message. +* `GTA_RESULT_CODE_OUTPUT_END`: This token will stop GTA from adding the following output to the error message. If it is not provided, GTA will capture the complete remaining output as error message of the additional test. +* `GTA_RESULT_CODE_SKIP`: This token will make the additional test case have outcome *Skipped* if the test executable returns with exit code 0. This can e.g. be useful if a particular check is only perfomed in Debug mode. + +Note that when running tests in parallel, a test executable might be run more than once by GTA. In this case, the exit codes and respective outputs of a test exectutable are aggregated as follows: +* The exit code reported will be the one with the greatest absolute value; e.g., if the exit codes have been -2, 0, and 1, the reported exit code will be -2. +* Captured outputs will all go into the test's error message. +* The test will be reported as skipped if all runs of that executable have been reported as skipped. + +An example usage of the *Exit code test case* can be found as part of the SampleTests solution: [Project *MemoryLeakTests*](https://github.com/csoltenborn/GoogleTestAdapter/tree/master/SampleTests/MemoryLeakTests) makes use of MS' memory leak detection facilities and reports the results to VS via the described mechanism. Things to be noted: +* The mechanism is enabled for the project by means of GTA's [solution settings](https://github.com/csoltenborn/GoogleTestAdapter/blob/master/SampleTests/SampleTests.gta.runsettings). +* To make sure that the test executable behaves as a normal gtest executable when not run via GTA, a command line parameter `-is_run_by_gta` is passed to it via the *Additional test execution parameters* option (again provided via the solution settings). This allows the test executable to just return the result of gtests' `RUN_ALL_TESTS()` macro if run outside GTA, and to return the result of leak detetion otherwise (i.e., return 0 if and only if no leaks have been found). In case of the provided implementation for leak detection, this means to always return with exit code 0 in the `main()` method, since the leak detection code will actively call `exit(1)` if leaks are found. +* Since leak detection is only perfomed when the executable is compiled with Debug configuration, the main method makes use of the `GTA_RESULT_CODE_SKIP` and `GTA_RESULT_CODE_OUTPUT_BEGIN` tokens to make sure the test is reported as skipped in that setting, and to additionally produce some meaningful output. +* Finally, note that Google Test as of V1.8.1 [uses some memory allocation](https://github.com/google/googletest/pull/1142) which is recognized by MS' leak detection mechanism as a leak (although it isn't), in particular for failing assertions. Some of these "false positives" have been fixed with the linked issue, but there appear to be more. If you run into such problems, please report them against the [Google Test repository](https://github.com/google/googletest). + #### Running tests from command line with `VSTest.Console.exe` GTA can be used to run tests from the command line, which can be done making use of VS's [VSTest.Console.exe](https://msdn.microsoft.com/en-us/library/jj155800.aspx). GTA supports all the tool's command line options, including `/UseVsixExtensions` and `/TestAdapterPath`. diff --git a/SampleTests/LeakCheckTests/LeakCheckTests.cpp b/SampleTests/LeakCheckTests/LeakCheckTests.cpp index bacd2f7d4..62d0467d9 100644 --- a/SampleTests/LeakCheckTests/LeakCheckTests.cpp +++ b/SampleTests/LeakCheckTests/LeakCheckTests.cpp @@ -116,7 +116,6 @@ int main(int argc, char** argv) for (int i = 0; i < argc; i++) { - std::cout << argv[i] << "\n"; if (strncmp(argv[i], prefix.c_str(), strlen(prefix.c_str())) == 0) { is_run_by_gta = true; @@ -130,6 +129,7 @@ int main(int argc, char** argv) #ifndef _DEBUG if (is_run_by_gta) { + std::cout << "GTA_RESULT_CODE_SKIP\n"; std::cout << "GTA_RESULT_CODE_OUTPUT_BEGIN\n"; std::cout << "Memory leak detection is only performed if compiled with Debug configuration.\n"; } From 5e806e16e0ad40da6a93abd859e1f28f5599aefc Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sat, 23 Feb 2019 13:39:32 +0100 Subject: [PATCH 08/81] test improvements --- .../TestExecutorParallelTests.cs | 6 + .../TestExecutorSequentialTests.cs | 6 + ...cutorSequentialTests_FrameworkDebugging.cs | 6 + .../TestExecutorTestsBase.cs | 23 ++- .../AbstractConsoleIntegrationTests.cs | 21 ++- SampleTests/LeakCheckTests/LeakCheckTests.cpp | 154 +++++++++--------- SampleTests/LeakCheckTests/test_leak.cpp | 10 +- 7 files changed, 130 insertions(+), 96 deletions(-) diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorParallelTests.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorParallelTests.cs index 780c1ceca..00083b99f 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorParallelTests.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorParallelTests.cs @@ -196,6 +196,12 @@ public override void MemoryLeakTests_PassingWithoutLeaks_CorrectResult() base.MemoryLeakTests_PassingWithoutLeaks_CorrectResult(); } + [TestMethod] + public override void MemoryLeakTests_FailingWithoutLeaks_CorrectResult() + { + base.MemoryLeakTests_FailingWithoutLeaks_CorrectResult(); + } + #endregion } diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests.cs index ca8e335a3..88fc86618 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests.cs @@ -219,6 +219,12 @@ public override void MemoryLeakTests_PassingWithoutLeaks_CorrectResult() base.MemoryLeakTests_PassingWithoutLeaks_CorrectResult(); } + [TestMethod] + public override void MemoryLeakTests_FailingWithoutLeaks_CorrectResult() + { + base.MemoryLeakTests_FailingWithoutLeaks_CorrectResult(); + } + #endregion } diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs index 462309d45..599205bf8 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs @@ -222,6 +222,12 @@ public override void MemoryLeakTests_PassingWithoutLeaks_CorrectResult() base.MemoryLeakTests_PassingWithoutLeaks_CorrectResult(); } + [TestMethod] + public override void MemoryLeakTests_FailingWithoutLeaks_CorrectResult() + { + base.MemoryLeakTests_FailingWithoutLeaks_CorrectResult(); + } + #endregion } } \ No newline at end of file diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs index 1a33fba84..664df8803 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs @@ -323,6 +323,22 @@ public virtual void MemoryLeakTests_PassingWithoutLeaks_CorrectResult() msg => msg == null); } + [TestMethod] + [TestCategory(Integration)] + public virtual void MemoryLeakTests_FailingWithoutLeaks_CorrectResult() + { + try + { + RunMemoryLeakTest(TestResources.LeakCheckTests_DebugX86, "memory_leaks.failing", VsTestOutcome.Failed, VsTestOutcome.Passed, + msg => msg == null); + } + catch (MockException) + { + Assert.Inconclusive("skipped until gtest's 'memory leaks' are fixed..."); + } + Assert.Fail("Memory leak problem has been fixed :-) - enable test!"); + } + [TestMethod] [TestCategory(Integration)] public virtual void MemoryLeakTests_PassingWithoutLeaksRelease_CorrectResult() @@ -334,13 +350,6 @@ public virtual void MemoryLeakTests_PassingWithoutLeaksRelease_CorrectResult() msg => !outputAvailable || msg.Contains("Memory leak detection is only performed if compiled with Debug configuration.")); } - //[TestMethod] - //[TestCategory(Integration)] - //public void FooTest4() - //{ - // RunMemoryLeakTest(TestResources.LeakCheckTests_DebugX86, "memory_leaks.failing", VsTestOutcome.Passed, VsTestOutcome.Passed); - //} - private void RunMemoryLeakTest(string executable, string testCaseName, VsTestOutcome testOutcome, VsTestOutcome leakCheckOutcome, Func errorMessagePredicate) { string resultCodeTestName = "MemoryLeakTest"; diff --git a/GoogleTestAdapter/Tests.Common/AbstractConsoleIntegrationTests.cs b/GoogleTestAdapter/Tests.Common/AbstractConsoleIntegrationTests.cs index 6ca12d668..d368e6719 100644 --- a/GoogleTestAdapter/Tests.Common/AbstractConsoleIntegrationTests.cs +++ b/GoogleTestAdapter/Tests.Common/AbstractConsoleIntegrationTests.cs @@ -53,33 +53,36 @@ public static void GetDirectories(out string testAdapterDir, out string testSolu [TestCategory(TestMetadata.TestCategories.EndToEnd)] public virtual void Console_ListDiscoverers_DiscovererIsListed() { - Assert.Inconclusive("skipped until #184 is fixed..."); - string arguments = CreateListDiscoverersArguments(); string output = RunExecutableAndGetOutput(_solutionFile, arguments); - output.ToLower().Should().MatchRegex(@"executor:\/\/(testadapterforgoogletest|googletestrunner)\/v1"); + if (output.ToLower().Contains("googletestrunner")) + Assert.Fail("VS test framework appears to have been fixed :-) - enable test!"); + else + Assert.Inconclusive("skipped until vs test framework is fixed..."); } [TestMethod] [TestCategory(TestMetadata.TestCategories.EndToEnd)] public virtual void Console_ListExecutors_ExecutorIsListed() { - Assert.Inconclusive("skipped until #184 is fixed..."); - string arguments = CreateListExecutorsArguments(); string output = RunExecutableAndGetOutput(_solutionFile, arguments); - output.Should().MatchRegex(@"executor:\/\/(TestAdapterForGoogleTest|GoogleTestRunner)\/v1"); + if (output.ToLower().Contains("googletestrunner")) + Assert.Fail("VS test framework appears to have been fixed :-) - enable test!"); + else + Assert.Inconclusive("skipped until vs test framework is fixed..."); } [TestMethod] [TestCategory(TestMetadata.TestCategories.EndToEnd)] public virtual void Console_ListSettingsProviders_SettingsProviderIsListed() { - Assert.Inconclusive("skipped until #184 is fixed..."); - string arguments = CreateListSettingsProvidersArguments(); string output = RunExecutableAndGetOutput(_solutionFile, arguments); - output.Should().Contain(@"GoogleTestAdapter"); + if (output.ToLower().Contains("googletestadapter")) + Assert.Fail("VS test framework appears to have been fixed :-) - enable test!"); + else + Assert.Inconclusive("skipped until vs test framework is fixed..."); } diff --git a/SampleTests/LeakCheckTests/LeakCheckTests.cpp b/SampleTests/LeakCheckTests/LeakCheckTests.cpp index 62d0467d9..fac565a03 100644 --- a/SampleTests/LeakCheckTests/LeakCheckTests.cpp +++ b/SampleTests/LeakCheckTests/LeakCheckTests.cpp @@ -8,133 +8,137 @@ // before first allocation namespace gsi { - namespace diag - { - class EnableLeakCheck - { - public: - static void Initialize() - { - static EnableLeakCheck leakReporter; - } - private: - EnableLeakCheck() {} - ~EnableLeakCheck() - { - _CrtDumpMemoryLeaks(); - } - }; - } + namespace diag + { + class EnableLeakCheck + { + public: + static void Initialize() + { + static EnableLeakCheck leakReporter; + } + private: + EnableLeakCheck() {} + ~EnableLeakCheck() + { + _CrtDumpMemoryLeaks(); + } + }; + } } void InitializeLeakCheck_() { - gsi::diag::EnableLeakCheck::Initialize(); + gsi::diag::EnableLeakCheck::Initialize(); } #undef new void* operator new(size_t size) //throw( std::bad_alloc ) { - InitializeLeakCheck_(); - return malloc(size); + InitializeLeakCheck_(); + return malloc(size); } void* operator new[](size_t const size) { - InitializeLeakCheck_(); - return operator new(size); + InitializeLeakCheck_(); + return operator new(size); } bool is_run_by_gta = false; -namespace +namespace { - template inline size_t lengthof(T const (&array)[N]) { return N; } - template struct lengthof_sizer - { - unsigned char count[N]; - }; - template< class T, int N > inline lengthof_sizer lengthof_get_sizer(T const (&array)[N]) { return lengthof_sizer(); } - #define LENGTHOF( a ) sizeof( lengthof_get_sizer( a ).count ) - - class ShutdownReportHook - { - public: - static void RegisterMemoryLeakAssertOnExit() - { - _CrtSetReportHookW2(_CRT_RPTHOOK_INSTALL, &RunHook_); - } - private: - static int RunHook_ - ( - int reportType, - wchar_t *message, - int *returnValue - ) - { - // Detect when the memory leak dump is starting, and flag for special processing of leak reports. - const wchar_t szStartDumpString[] = L"Detected memory leaks!"; //CRT is hard coded to say "Detected memory leaks!\n" in the memory leak report - if (::wcsncmp(message, szStartDumpString, LENGTHOF(szStartDumpString) - 1) == 0) - { + template inline size_t lengthof(T const (&array)[N]) { return N; } + template struct lengthof_sizer + { + unsigned char count[N]; + }; + template< class T, int N > inline lengthof_sizer lengthof_get_sizer(T const (&array)[N]) { return lengthof_sizer(); } +#define LENGTHOF( a ) sizeof( lengthof_get_sizer( a ).count ) + + class ShutdownReportHook + { + public: + static void RegisterMemoryLeakAssertOnExit() + { + _CrtSetReportHookW2(_CRT_RPTHOOK_INSTALL, &RunHook_); + } + private: + static int RunHook_ + ( + int reportType, + wchar_t *message, + int *returnValue + ) + { + // Detect when the memory leak dump is starting, and flag for special processing of leak reports. + const wchar_t szStartDumpString[] = L"Detected memory leaks!"; //CRT is hard coded to say "Detected memory leaks!\n" in the memory leak report + if (::wcsncmp(message, szStartDumpString, LENGTHOF(szStartDumpString) - 1) == 0) + { if (is_run_by_gta) std::cout << "GTA_RESULT_CODE_OUTPUT_BEGIN\n"; + std::wcout << std::wstring(message) << "\n"; - exit(1); - } + if (is_run_by_gta) + std::cout << "Note that due to some weaknesses of Google Test and the used memory leak detection technology, the leak detection results are only reliable if at least one real test is executed, and if all executed tests have passed.\n"; + + exit(1); + } - return 0; - } - }; + return 0; + } + }; } struct InitCleanupOnExit { - InitCleanupOnExit() - { - std::atexit(&CleanupOnExit_); // Cleanup event sink on program shutdown. - } + InitCleanupOnExit() + { + std::atexit(&CleanupOnExit_); // Cleanup event sink on program shutdown. + } private: - static void CleanupOnExit_() - { - // Memory leaks reports happen on shutdown after this point, so force them to go out via stderr - // so any parent process will see it as an error. - ShutdownReportHook::RegisterMemoryLeakAssertOnExit(); - } + static void CleanupOnExit_() + { + // Memory leaks reports happen on shutdown after this point, so force them to go out via stderr + // so any parent process will see it as an error. + ShutdownReportHook::RegisterMemoryLeakAssertOnExit(); + } } gInitCleanupOnExit; int main(int argc, char** argv) { - std::string prefix("-is_run_by_gta"); - + std::string prefix("-is_run_by_gta"); for (int i = 0; i < argc; i++) - { - if (strncmp(argv[i], prefix.c_str(), strlen(prefix.c_str())) == 0) - { + { + if (strncmp(argv[i], prefix.c_str(), strlen(prefix.c_str())) == 0) + { is_run_by_gta = true; break; - } - } + } + } testing::InitGoogleTest(&argc, argv); - int returnValue = RUN_ALL_TESTS(); + int returnValue = RUN_ALL_TESTS(); - #ifndef _DEBUG +#ifndef _DEBUG if (is_run_by_gta) { std::cout << "GTA_RESULT_CODE_SKIP\n"; std::cout << "GTA_RESULT_CODE_OUTPUT_BEGIN\n"; std::cout << "Memory leak detection is only performed if compiled with Debug configuration.\n"; } - #endif +#endif // memory leak detection will do exit(1) if memory leaks are found + // thus, return 0 if run by gta since otherwise, a returnValue != 0 would result in the memory leak test being flagged as failed return is_run_by_gta ? 0 : returnValue; } \ No newline at end of file diff --git a/SampleTests/LeakCheckTests/test_leak.cpp b/SampleTests/LeakCheckTests/test_leak.cpp index 0a4c0d897..5b0ba8bc7 100644 --- a/SampleTests/LeakCheckTests/test_leak.cpp +++ b/SampleTests/LeakCheckTests/test_leak.cpp @@ -6,11 +6,11 @@ TEST(memory_leaks, passing) ASSERT_TRUE(true); } -// causes memory leak!? -//TEST(memory_leaks, failing) -//{ -// ASSERT_TRUE(false); -//} +TEST(memory_leaks, failing) +{ + std::cout << "This test does not leak, but a leak is reported due to the failed assertion...\n"; + ASSERT_TRUE(false); +} TEST(memory_leaks, passing_and_leaking) { From a5843ffa23bd3d4a067b8c4a1eddb7fefe9a1f93 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sat, 23 Feb 2019 19:30:03 +0100 Subject: [PATCH 09/81] added some unit tests --- .../Core.Tests/Core.Tests.csproj | 2 + .../ResultCodeTestsAggregatorTests.cs | 128 ++++++++++++ .../ResultCodeTestsReporterTests.cs | 195 ++++++++++++++++++ GoogleTestAdapter/Core/Runners/ITestRunner.cs | 24 ++- .../Core/Runners/SequentialTestRunner.cs | 9 +- .../TestResults/ResultCodeTestsAggregator.cs | 25 ++- .../TestResults/ResultCodeTestsReporter.cs | 18 +- 7 files changed, 366 insertions(+), 35 deletions(-) create mode 100644 GoogleTestAdapter/Core.Tests/TestResults/ResultCodeTestsAggregatorTests.cs create mode 100644 GoogleTestAdapter/Core.Tests/TestResults/ResultCodeTestsReporterTests.cs diff --git a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj index ed76511a9..7c1363fe2 100644 --- a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj +++ b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj @@ -96,8 +96,10 @@ + + diff --git a/GoogleTestAdapter/Core.Tests/TestResults/ResultCodeTestsAggregatorTests.cs b/GoogleTestAdapter/Core.Tests/TestResults/ResultCodeTestsAggregatorTests.cs new file mode 100644 index 000000000..9b882f25c --- /dev/null +++ b/GoogleTestAdapter/Core.Tests/TestResults/ResultCodeTestsAggregatorTests.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using FluentAssertions; +using GoogleTestAdapter.Runners; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using static GoogleTestAdapter.Tests.Common.TestMetadata.TestCategories; +// ReSharper disable RedundantArgumentDefaultValue + +namespace GoogleTestAdapter.TestResults +{ + [TestClass] + public class ResultCodeTestsAggregatorTests + { + [TestMethod] + [TestCategory(Unit)] + public void ComputeAggregatedResults_EmptyInput_EmptyResult() + { + GetAggregatedResults(new List()).Should().BeEmpty(); + } + + [TestMethod] + [TestCategory(Unit)] + public void ComputeAggregatedResults_SingleInput_InputIsReturned() + { + var allResults = new List + { + new ExecutableResult("Foo") + }; + var results = GetAggregatedResults(allResults).ToList(); + + results.Single().Should().BeEquivalentTo(allResults.Single()); + } + + [TestMethod] + [TestCategory(Unit)] + public void ComputeAggregatedResults_TwoInputsWithSameExecutable_ResultCodeIsAggregatedCorrectly() + { + var allResults = new List + { + new ExecutableResult("Foo", 0), + new ExecutableResult("Foo", 1) + }; + var results = GetAggregatedResults(allResults).ToList(); + + results.Single().Should().BeEquivalentTo(new ExecutableResult("Foo", 1)); + } + + [TestMethod] + [TestCategory(Unit)] + public void ComputeAggregatedResults_TwoInputsWithSameExecutableAllSkip_SkipIsAggregatedCorrectly() + { + var allResults = new List + { + new ExecutableResult("Foo", resultCodeSkip: true), + new ExecutableResult("Foo", resultCodeSkip: true) + }; + var results = GetAggregatedResults(allResults).ToList(); + + results.Single().Should().BeEquivalentTo(new ExecutableResult("Foo", resultCodeSkip: true)); + } + + [TestMethod] + [TestCategory(Unit)] + public void ComputeAggregatedResults_TwoInputsWithSameExecutableOneSkip_SkipIsAggregatedCorrectly() + { + var allResults = new List + { + new ExecutableResult("Foo", resultCodeSkip: true), + new ExecutableResult("Foo") + }; + var results = GetAggregatedResults(allResults).ToList(); + + results.Single().Should().BeEquivalentTo(new ExecutableResult("Foo")); + } + + [TestMethod] + [TestCategory(Unit)] + public void ComputeAggregatedResults_TwoInputsOneWithOutput_OutputAggregatedCorrectly() + { + var allResults = new List + { + new ExecutableResult("Foo", resultCodeOutput: new List {"Some output"}), + new ExecutableResult("Foo") + }; + var results = GetAggregatedResults(allResults).ToList(); + + results.Single().Should().BeEquivalentTo(new ExecutableResult("Foo", resultCodeOutput: new List {"Some output"})); + } + + [TestMethod] + [TestCategory(Unit)] + public void ComputeAggregatedResults_TwoInputsWithSameExecutable_CompleteInputIsAggregated() + { + var allResults = new List + { + new ExecutableResult("Foo", 0, new List {"Output 1"}, true), + new ExecutableResult("Foo", 1, new List {"Output 2"}) + }; + var results = GetAggregatedResults(allResults).ToList(); + + results.Single().Should().BeEquivalentTo(new ExecutableResult("Foo", 1, new List {"Output 1", Environment.NewLine, "Output 2"})); + } + + [TestMethod] + [TestCategory(Unit)] + public void ComputeAggregatedResults_ThreeInputsWithTwoExecutables_CompleteInputIsAggregated() + { + var allResults = new List + { + new ExecutableResult("Foo", 0, new List {"Output 1"}, true), + new ExecutableResult("Bar", 0, new List {"Output 1"}, true), + new ExecutableResult("Foo", 1, new List {"Output 2"}) + }; + var results = GetAggregatedResults(allResults).ToList(); + + results.Should().HaveCount(2); + results[0].Should().BeEquivalentTo(new ExecutableResult("Foo", 1, new List {"Output 1", Environment.NewLine, "Output 2"})); + results[1].Should().BeEquivalentTo(new ExecutableResult("Bar", 0, new List {"Output 1"}, true)); + } + + private IEnumerable GetAggregatedResults(IEnumerable allResults) + { + var aggregator = new ResultCodeTestsAggregator(); + return aggregator.ComputeAggregatedResults(allResults); + } + } +} diff --git a/GoogleTestAdapter/Core.Tests/TestResults/ResultCodeTestsReporterTests.cs b/GoogleTestAdapter/Core.Tests/TestResults/ResultCodeTestsReporterTests.cs new file mode 100644 index 000000000..28d8e8b65 --- /dev/null +++ b/GoogleTestAdapter/Core.Tests/TestResults/ResultCodeTestsReporterTests.cs @@ -0,0 +1,195 @@ +using System.Collections.Generic; +using System.Linq; +using GoogleTestAdapter.Model; +using GoogleTestAdapter.Runners; +using GoogleTestAdapter.Settings; +using GoogleTestAdapter.Tests.Common; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using static GoogleTestAdapter.Tests.Common.TestMetadata.TestCategories; + +namespace GoogleTestAdapter.TestResults +{ + [TestClass] + public class ResultCodeTestsReporterTests : TestsBase + { + private readonly Mock _mockAggregator = new Mock(); + private ResultCodeTestsReporter _reporter; + + private const string ResultCodeTestCaseName = nameof(ResultCodeTestCaseName); + + [TestInitialize] + public override void SetUp() + { + base.SetUp(); + + MockOptions.Setup(o => o.ReturnCodeTestCase).Returns(ResultCodeTestCaseName); + + _mockAggregator.Reset(); + _reporter = new ResultCodeTestsReporter(MockFrameworkReporter.Object, _mockAggregator.Object, MockOptions.Object, MockLogger.Object); + } + + [TestMethod] + [TestCategory(Unit)] + public void ReportResultCodeTestCases_EmptyInput_EmptyResult() + { + MockOptions.Setup(o => o.ReturnCodeTestCase).Returns(""); + _mockAggregator.Setup(a => a.ComputeAggregatedResults(It.IsAny>())).Returns( + new List + { + new ExecutableResult("Foo") + }); + + _reporter.ReportResultCodeTestCases(null, false); + + MockFrameworkReporter + .Verify(r => r.ReportTestResults(It.IsAny>()), Times.Never); + } + + [TestMethod] + [TestCategory(Unit)] + public void ReportResultCodeTestCases_Pass_CorrectResult() + { + _mockAggregator.Setup(a => a.ComputeAggregatedResults(It.IsAny>())).Returns( + new List + { + new ExecutableResult("Foo") + }); + _reporter.ReportResultCodeTestCases(null, false); + + MockFrameworkReporter + .Verify(r => r.ReportTestResults(It.Is>( + results => CheckResult(results.Single(), "Foo", TestOutcome.Passed))), + Times.Once); + } + + [TestMethod] + [TestCategory(Unit)] + public void ReportResultCodeTestCases_PassWithOutput_CorrectResult() + { + _mockAggregator.Setup(a => a.ComputeAggregatedResults(It.IsAny>())).Returns( + new List + { + new ExecutableResult("Foo", resultCodeOutput: new List {"Output 1", "", "Output 2"}) + }); + _reporter.ReportResultCodeTestCases(null, false); + + MockFrameworkReporter + .Verify(r => r.ReportTestResults(It.Is>( + results => CheckResult(results.Single(), "Foo", TestOutcome.Passed, "Output 1", "Output 2"))), + Times.Once); + } + + [TestMethod] + [TestCategory(Unit)] + public void ReportResultCodeTestCases_Fail_CorrectResult() + { + _mockAggregator.Setup(a => a.ComputeAggregatedResults(It.IsAny>())).Returns( + new List + { + new ExecutableResult("Foo", 1) + }); + _reporter.ReportResultCodeTestCases(null, false); + + MockFrameworkReporter + .Verify(r => r.ReportTestResults(It.Is>( + results => CheckResult(results.Single(), "Foo", TestOutcome.Failed))), + Times.Once); + } + + [TestMethod] + [TestCategory(Unit)] + public void ReportResultCodeTestCases_FailWithOutput_CorrectResult() + { + _mockAggregator.Setup(a => a.ComputeAggregatedResults(It.IsAny>())).Returns( + new List + { + new ExecutableResult("Foo", 1, resultCodeOutput: new List {"Output 1", "", "Output 2"}) + }); + _reporter.ReportResultCodeTestCases(null, false); + + MockFrameworkReporter + .Verify(r => r.ReportTestResults(It.Is>( + results => CheckResult(results.Single(), "Foo", TestOutcome.Failed, "Output 1", "Output 2"))), + Times.Once); + } + + [TestMethod] + [TestCategory(Unit)] + public void ReportResultCodeTestCases_PassAndSkip_CorrectResult() + { + _mockAggregator.Setup(a => a.ComputeAggregatedResults(It.IsAny>())).Returns( + new List + { + new ExecutableResult("Foo", resultCodeSkip: true) + }); + + _reporter.ReportResultCodeTestCases(null, false); + + MockFrameworkReporter + .Verify(r => r.ReportTestResults(It.Is>( + results => CheckResult(results.Single(), "Foo", TestOutcome.Skipped))), + Times.Once); + } + + [TestMethod] + [TestCategory(Unit)] + public void ReportResultCodeTestCases_FailAndSkip_CorrectResult() + { + _mockAggregator.Setup(a => a.ComputeAggregatedResults(It.IsAny>())).Returns( + new List + { + new ExecutableResult("Foo", 1, resultCodeSkip: true) + }); + + _reporter.ReportResultCodeTestCases(null, false); + + MockFrameworkReporter + .Verify(r => r.ReportTestResults(It.Is>( + results => CheckResult(results.Single(), "Foo", TestOutcome.Failed))), + Times.Once); + } + + [TestMethod] + [TestCategory(Unit)] + public void ReportResultCodeTestCases_PassButNoOutput_WarningIsLogged() + { + MockOptions.Setup(o => o.UseNewTestExecutionFramework).Returns(false); + _mockAggregator.Setup(a => a.ComputeAggregatedResults(It.IsAny>())).Returns( + new List + { + new ExecutableResult("Foo") + }); + + _reporter.ReportResultCodeTestCases(null, true); + + MockLogger.Verify(l => l.LogWarning(It.Is(msg => msg.Contains("collected") && msg.Contains(SettingsWrapper.OptionUseNewTestExecutionFramework))), Times.Once); + } + + [TestMethod] + [TestCategory(Unit)] + public void ReportResultCodeTestCases_FailButNoOutput_WarningIsLogged() + { + MockOptions.Setup(o => o.UseNewTestExecutionFramework).Returns(false); + _mockAggregator.Setup(a => a.ComputeAggregatedResults(It.IsAny>())).Returns( + new List + { + new ExecutableResult("Foo", 1) + }); + + _reporter.ReportResultCodeTestCases(null, true); + + MockLogger.Verify(l => l.LogWarning(It.Is(msg => msg.Contains("collected") && msg.Contains(SettingsWrapper.OptionUseNewTestExecutionFramework))), Times.Once); + } + + private static bool CheckResult(TestResult result, string executable, TestOutcome outcome, params string[] errorMessageParts) + { + return + result.TestCase.Source == executable && + result.DisplayName == $"{executable}.{ResultCodeTestCaseName}" && + result.TestCase.FullyQualifiedName == $"{executable}.{ResultCodeTestCaseName}" && + result.Outcome == outcome && + errorMessageParts.All(p => result.ErrorMessage.Contains(p)); + } + } +} diff --git a/GoogleTestAdapter/Core/Runners/ITestRunner.cs b/GoogleTestAdapter/Core/Runners/ITestRunner.cs index 0e1502cbb..b51bd936a 100644 --- a/GoogleTestAdapter/Core/Runners/ITestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/ITestRunner.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using GoogleTestAdapter.Model; using GoogleTestAdapter.ProcessExecution.Contracts; @@ -7,10 +8,23 @@ namespace GoogleTestAdapter.Runners public class ExecutableResult { - public string Executable { get; set; } - public int ResultCode { get; set; } - public IList ResultCodeOutput { get; set; } - public bool ResultCodeSkip { get; set; } + public string Executable { get; } + public int ResultCode { get; } + public IReadOnlyList ResultCodeOutput { get; } + public bool ResultCodeSkip { get; } + + public ExecutableResult(string executable, int resultCode = 0, IList resultCodeOutput = null, bool resultCodeSkip = false) + { + if (string.IsNullOrWhiteSpace(executable)) + { + throw new ArgumentException(nameof(executable)); + } + + Executable = executable; + ResultCode = resultCode; + ResultCodeOutput = (IReadOnlyList) (resultCodeOutput ?? new List()); + ResultCodeSkip = resultCodeSkip; + } } public interface ITestRunner diff --git a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs index ed94f0aa1..b7c44319e 100644 --- a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs @@ -206,13 +206,8 @@ void OnNewOutputLine(string line) if (printTestOutput) _logger.LogInfo($"{_threadName}<<<<<<<<<<<<<<< End of Output"); - ExecutableResults.Add(new ExecutableResult - { - Executable = executable, - ResultCode = resultCode, - ResultCodeOutput = streamingParser.ResultCodeOutput, - ResultCodeSkip = streamingParser.ResultCodeSkip - }); + ExecutableResults.Add(new ExecutableResult(executable, resultCode, streamingParser.ResultCodeOutput, + streamingParser.ResultCodeSkip)); var consoleOutput = new List(); new TestDurationSerializer().UpdateTestDurations(streamingParser.TestResults); diff --git a/GoogleTestAdapter/Core/TestResults/ResultCodeTestsAggregator.cs b/GoogleTestAdapter/Core/TestResults/ResultCodeTestsAggregator.cs index 3c2e6e0b1..0a17a4d60 100644 --- a/GoogleTestAdapter/Core/TestResults/ResultCodeTestsAggregator.cs +++ b/GoogleTestAdapter/Core/TestResults/ResultCodeTestsAggregator.cs @@ -12,13 +12,11 @@ public IEnumerable ComputeAggregatedResults(IEnumerable r.Executable) - .Select(results => new ExecutableResult - { - Executable = results.Key, - ResultCode = ComputeAggregatedResultCode(results), - ResultCodeOutput = ComputeAggregatedOutput(results), - ResultCodeSkip = results.All(r => r.ResultCodeSkip) - }); + .Select(results => new ExecutableResult( + executable: results.Key, + resultCode: ComputeAggregatedResultCode(results), + resultCodeOutput: ComputeAggregatedOutput(results), + resultCodeSkip: results.All(r => r.ResultCodeSkip))); } private List ComputeAggregatedOutput(IEnumerable results) @@ -26,11 +24,18 @@ private List ComputeAggregatedOutput(IEnumerable resul var completeOutput = new List(); foreach (ExecutableResult result in results) { - completeOutput.Add(Environment.NewLine); - completeOutput.AddRange(result.ResultCodeOutput); + if (result.ResultCodeOutput != null && result.ResultCodeOutput.Any(line => !string.IsNullOrWhiteSpace(line))) + { + completeOutput.Add(Environment.NewLine); + completeOutput.AddRange(result.ResultCodeOutput); + } + } + + if (completeOutput.Any()) + { + completeOutput.RemoveAt(0); } - completeOutput.RemoveAt(0); return completeOutput; } diff --git a/GoogleTestAdapter/Core/TestResults/ResultCodeTestsReporter.cs b/GoogleTestAdapter/Core/TestResults/ResultCodeTestsReporter.cs index d5464983f..789addc74 100644 --- a/GoogleTestAdapter/Core/TestResults/ResultCodeTestsReporter.cs +++ b/GoogleTestAdapter/Core/TestResults/ResultCodeTestsReporter.cs @@ -45,7 +45,8 @@ public void ReportResultCodeTestCases(IEnumerable allResults, { if (!string.IsNullOrWhiteSpace(_settings.ReturnCodeTestCase)) { - printWarning |= ReportResultCodeTestResult(executableResult, isBeingDebugged); + ReportResultCodeTestResult(executableResult); + printWarning |= isBeingDebugged && !_settings.UseNewTestExecutionFramework; } }); } @@ -57,13 +58,12 @@ public void ReportResultCodeTestCases(IEnumerable allResults, } } - private bool ReportResultCodeTestResult(ExecutableResult executableResult, bool isBeingDebugged) + private void ReportResultCodeTestResult(ExecutableResult executableResult) { var resultCodeTestCase = CreateResultCodeTestCase(_settings, executableResult.Executable); _reporter.ReportTestsStarted(resultCodeTestCase.Yield()); TestResult testResult; - bool printWarning = false; if (executableResult.ResultCode == 0) { testResult = CreatePassingResultCodeTestResult(resultCodeTestCase, executableResult); @@ -74,12 +74,10 @@ private bool ReportResultCodeTestResult(ExecutableResult executableResult, bool } else { - testResult = CreateFailingResultCodeTestResult(resultCodeTestCase, executableResult, executableResult.ResultCode, - isBeingDebugged, out printWarning); + testResult = CreateFailingResultCodeTestResult(resultCodeTestCase, executableResult, executableResult.ResultCode); } _reporter.ReportTestResults(testResult.Yield()); - return printWarning; } private TestResult CreatePassingResultCodeTestResult(TestCase resultCodeTestCase, @@ -97,20 +95,14 @@ private TestResult CreatePassingResultCodeTestResult(TestCase resultCodeTestCase } private TestResult CreateFailingResultCodeTestResult(TestCase resultCodeTestCase, ExecutableResult executableResult, - int resultCode, bool isBeingDebugged, out bool printWarning) + int resultCode) { - printWarning = false; - string message = $"Exit code: {resultCode}"; if (executableResult.ResultCodeOutput.Any()) { message += $"{Environment.NewLine}{Environment.NewLine}"; message += string.Join(Environment.NewLine, executableResult.ResultCodeOutput); } - else if (isBeingDebugged && !_settings.UseNewTestExecutionFramework) - { - printWarning = true; - } return StreamingStandardOutputTestResultParser .CreateFailedTestResult(resultCodeTestCase, TimeSpan.Zero, message, ""); From 812b8efaae2fa36a36f5a4196cfc3e7a19f1adc5 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sat, 23 Feb 2019 21:06:39 +0100 Subject: [PATCH 10/81] replace return code and result code with exit code for consistency --- .../Core.Tests/Core.Tests.csproj | 4 +- .../Core.Tests/GoogleTestDiscovererTests.cs | 16 ++--- .../Core.Tests/GoogleTestExecutorTests.cs | 6 +- ...sts.cs => ExitCodeTestsAggregatorTests.cs} | 18 +++--- ...Tests.cs => ExitCodeTestsReporterTests.cs} | 62 +++++++++---------- ...mingStandardOutputTestResultParserTests.cs | 44 ++++++------- GoogleTestAdapter/Core/Core.csproj | 8 +-- GoogleTestAdapter/Core/GoogleTestExecutor.cs | 8 +-- GoogleTestAdapter/Core/Runners/ITestRunner.cs | 14 ++--- .../Core/Runners/SequentialTestRunner.cs | 6 +- .../Settings/IGoogleTestAdapterSettings.cs | 4 +- .../Core/Settings/RunSettings.cs | 4 +- .../Core/Settings/SettingsWrapper.cs | 8 +-- .../Core/TestCases/TestCaseFactory.cs | 10 +-- ...gregator.cs => ExitCodeTestsAggregator.cs} | 24 +++---- ...tsReporter.cs => ExitCodeTestsReporter.cs} | 54 ++++++++-------- ...regator.cs => IExitCodeTestsAggregator.cs} | 2 +- .../TestResults/IExitCodeTestsReporter.cs | 10 +++ .../TestResults/IResultCodeTestsReporter.cs | 10 --- ...StreamingStandardOutputTestResultParser.cs | 32 +++++----- .../Resources/AllTestSettings.gta.runsettings | 2 +- .../TestExecutorParallelTests.cs | 8 +-- .../TestExecutorSequentialTests.cs | 8 +-- ...cutorSequentialTests_FrameworkDebugging.cs | 8 +-- .../TestExecutorTestsBase.cs | 28 ++++----- .../TestAdapter/GoogleTestAdapterSettings.xsd | 2 +- GoogleTestAdapter/TestAdapter/TestExecutor.cs | 6 +- .../Tests/ProcessExecutorTests.cs | 4 +- GoogleTestAdapter/Tests.Common/TestsBase.cs | 2 +- .../GoogleTestExtensionOptionsPage.cs | 2 +- .../OptionsPages/GeneralOptionsDialogPage.cs | 12 ++-- README.md | 8 +-- SampleTests/LeakCheckTests/LeakCheckTests.cpp | 6 +- SampleTests/SampleTests.gta.runsettings | 2 +- SampleTests/Tests/Main.cpp | 4 +- 35 files changed, 223 insertions(+), 223 deletions(-) rename GoogleTestAdapter/Core.Tests/TestResults/{ResultCodeTestsAggregatorTests.cs => ExitCodeTestsAggregatorTests.cs} (88%) rename GoogleTestAdapter/Core.Tests/TestResults/{ResultCodeTestsReporterTests.cs => ExitCodeTestsReporterTests.cs} (71%) rename GoogleTestAdapter/Core/TestResults/{ResultCodeTestsAggregator.cs => ExitCodeTestsAggregator.cs} (56%) rename GoogleTestAdapter/Core/TestResults/{ResultCodeTestsReporter.cs => ExitCodeTestsReporter.cs} (55%) rename GoogleTestAdapter/Core/TestResults/{IResultCodeTestsAggregator.cs => IExitCodeTestsAggregator.cs} (82%) create mode 100644 GoogleTestAdapter/Core/TestResults/IExitCodeTestsReporter.cs delete mode 100644 GoogleTestAdapter/Core/TestResults/IResultCodeTestsReporter.cs diff --git a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj index 7c1363fe2..a43bf9364 100644 --- a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj +++ b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj @@ -96,10 +96,10 @@ - + - + diff --git a/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTests.cs b/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTests.cs index 015701d18..84f4935ef 100644 --- a/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTests.cs +++ b/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTests.cs @@ -158,19 +158,19 @@ public void GetTestsFromExecutable_SampleTestsDebug_FindsTestsWithLocation() [TestMethod] [TestCategory(Integration)] - public void GetTestsFromExecutable_SampleTestsDebugWithResultCodeTest_FindsTestsWithLocationAndResultCodeTest() + public void GetTestsFromExecutable_SampleTestsDebugWithExitCodeTest_FindsTestsWithLocationAndExitCodeTest() { - string testCaseName = "ResultCode"; - MockOptions.Setup(o => o.ReturnCodeTestCase).Returns(testCaseName); + string testCaseName = "ExitCode"; + MockOptions.Setup(o => o.ExitCodeTestCase).Returns(testCaseName); var testCases = FindTests(TestResources.Tests_DebugX86, TestResources.NrOfTests + 1); string finalName = Path.GetFileName(TestResources.Tests_DebugX86).Replace(".", "_") + "." + testCaseName; - var resultCodeTestCase = testCases.Single(tc => tc.FullyQualifiedName == finalName); - resultCodeTestCase.DisplayName.Should().Be(finalName); - resultCodeTestCase.Source.Should().Be(TestResources.Tests_DebugX86); - resultCodeTestCase.CodeFilePath.Should().BeEmpty(); - resultCodeTestCase.LineNumber.Should().Be(0); + var exitCodeTestCase = testCases.Single(tc => tc.FullyQualifiedName == finalName); + exitCodeTestCase.DisplayName.Should().Be(finalName); + exitCodeTestCase.Source.Should().Be(TestResources.Tests_DebugX86); + exitCodeTestCase.CodeFilePath.Should().BeEmpty(); + exitCodeTestCase.LineNumber.Should().Be(0); MockLogger.Verify(l => l.DebugInfo(It.Is(msg => msg.Contains("Exit code") && msg.Contains("ignored"))), Times.Once); } diff --git a/GoogleTestAdapter/Core.Tests/GoogleTestExecutorTests.cs b/GoogleTestAdapter/Core.Tests/GoogleTestExecutorTests.cs index 4f9ba1b43..be14e7e95 100644 --- a/GoogleTestAdapter/Core.Tests/GoogleTestExecutorTests.cs +++ b/GoogleTestAdapter/Core.Tests/GoogleTestExecutorTests.cs @@ -43,9 +43,9 @@ private void AssertDurationsFileIsCreated(bool parallelExecution) MockOptions.Setup(o => o.SolutionDir).Returns(TestResources.SampleTestsSolutionDir); var collectingReporter = new FakeFrameworkReporter(); - var resultCodeTestsAggregator = new ResultCodeTestsAggregator(); - var resultCodeTestsReporter = new ResultCodeTestsReporter(MockFrameworkReporter.Object, resultCodeTestsAggregator, MockOptions.Object, MockLogger.Object); - var testExecutor = new GoogleTestExecutor(TestEnvironment.Logger, TestEnvironment.Options, ProcessExecutorFactory, resultCodeTestsReporter); + var exitCodeTestsAggregator = new ExitCodeTestsAggregator(); + var exitCodeTestsReporter = new ExitCodeTestsReporter(MockFrameworkReporter.Object, exitCodeTestsAggregator, MockOptions.Object, MockLogger.Object); + var testExecutor = new GoogleTestExecutor(TestEnvironment.Logger, TestEnvironment.Options, ProcessExecutorFactory, exitCodeTestsReporter); testExecutor.RunTests(TestDataCreator.AllTestCasesExceptLoadTests, collectingReporter,false); sampleTestsDurationsFile.AsFileInfo() diff --git a/GoogleTestAdapter/Core.Tests/TestResults/ResultCodeTestsAggregatorTests.cs b/GoogleTestAdapter/Core.Tests/TestResults/ExitCodeTestsAggregatorTests.cs similarity index 88% rename from GoogleTestAdapter/Core.Tests/TestResults/ResultCodeTestsAggregatorTests.cs rename to GoogleTestAdapter/Core.Tests/TestResults/ExitCodeTestsAggregatorTests.cs index 9b882f25c..0f40adc3a 100644 --- a/GoogleTestAdapter/Core.Tests/TestResults/ResultCodeTestsAggregatorTests.cs +++ b/GoogleTestAdapter/Core.Tests/TestResults/ExitCodeTestsAggregatorTests.cs @@ -10,7 +10,7 @@ namespace GoogleTestAdapter.TestResults { [TestClass] - public class ResultCodeTestsAggregatorTests + public class ExitCodeTestsAggregatorTests { [TestMethod] [TestCategory(Unit)] @@ -34,7 +34,7 @@ public void ComputeAggregatedResults_SingleInput_InputIsReturned() [TestMethod] [TestCategory(Unit)] - public void ComputeAggregatedResults_TwoInputsWithSameExecutable_ResultCodeIsAggregatedCorrectly() + public void ComputeAggregatedResults_TwoInputsWithSameExecutable_ExitCodeIsAggregatedCorrectly() { var allResults = new List { @@ -52,12 +52,12 @@ public void ComputeAggregatedResults_TwoInputsWithSameExecutableAllSkip_SkipIsAg { var allResults = new List { - new ExecutableResult("Foo", resultCodeSkip: true), - new ExecutableResult("Foo", resultCodeSkip: true) + new ExecutableResult("Foo", exitCodeSkip: true), + new ExecutableResult("Foo", exitCodeSkip: true) }; var results = GetAggregatedResults(allResults).ToList(); - results.Single().Should().BeEquivalentTo(new ExecutableResult("Foo", resultCodeSkip: true)); + results.Single().Should().BeEquivalentTo(new ExecutableResult("Foo", exitCodeSkip: true)); } [TestMethod] @@ -66,7 +66,7 @@ public void ComputeAggregatedResults_TwoInputsWithSameExecutableOneSkip_SkipIsAg { var allResults = new List { - new ExecutableResult("Foo", resultCodeSkip: true), + new ExecutableResult("Foo", exitCodeSkip: true), new ExecutableResult("Foo") }; var results = GetAggregatedResults(allResults).ToList(); @@ -80,12 +80,12 @@ public void ComputeAggregatedResults_TwoInputsOneWithOutput_OutputAggregatedCorr { var allResults = new List { - new ExecutableResult("Foo", resultCodeOutput: new List {"Some output"}), + new ExecutableResult("Foo", exitCodeOutput: new List {"Some output"}), new ExecutableResult("Foo") }; var results = GetAggregatedResults(allResults).ToList(); - results.Single().Should().BeEquivalentTo(new ExecutableResult("Foo", resultCodeOutput: new List {"Some output"})); + results.Single().Should().BeEquivalentTo(new ExecutableResult("Foo", exitCodeOutput: new List {"Some output"})); } [TestMethod] @@ -121,7 +121,7 @@ public void ComputeAggregatedResults_ThreeInputsWithTwoExecutables_CompleteInput private IEnumerable GetAggregatedResults(IEnumerable allResults) { - var aggregator = new ResultCodeTestsAggregator(); + var aggregator = new ExitCodeTestsAggregator(); return aggregator.ComputeAggregatedResults(allResults); } } diff --git a/GoogleTestAdapter/Core.Tests/TestResults/ResultCodeTestsReporterTests.cs b/GoogleTestAdapter/Core.Tests/TestResults/ExitCodeTestsReporterTests.cs similarity index 71% rename from GoogleTestAdapter/Core.Tests/TestResults/ResultCodeTestsReporterTests.cs rename to GoogleTestAdapter/Core.Tests/TestResults/ExitCodeTestsReporterTests.cs index 28d8e8b65..7b4c6e8a7 100644 --- a/GoogleTestAdapter/Core.Tests/TestResults/ResultCodeTestsReporterTests.cs +++ b/GoogleTestAdapter/Core.Tests/TestResults/ExitCodeTestsReporterTests.cs @@ -11,36 +11,36 @@ namespace GoogleTestAdapter.TestResults { [TestClass] - public class ResultCodeTestsReporterTests : TestsBase + public class ExitCodeTestsReporterTests : TestsBase { - private readonly Mock _mockAggregator = new Mock(); - private ResultCodeTestsReporter _reporter; + private readonly Mock _mockAggregator = new Mock(); + private ExitCodeTestsReporter _reporter; - private const string ResultCodeTestCaseName = nameof(ResultCodeTestCaseName); + private const string ExitCodeTestCaseName = nameof(ExitCodeTestCaseName); [TestInitialize] public override void SetUp() { base.SetUp(); - MockOptions.Setup(o => o.ReturnCodeTestCase).Returns(ResultCodeTestCaseName); + MockOptions.Setup(o => o.ExitCodeTestCase).Returns(ExitCodeTestCaseName); _mockAggregator.Reset(); - _reporter = new ResultCodeTestsReporter(MockFrameworkReporter.Object, _mockAggregator.Object, MockOptions.Object, MockLogger.Object); + _reporter = new ExitCodeTestsReporter(MockFrameworkReporter.Object, _mockAggregator.Object, MockOptions.Object, MockLogger.Object); } [TestMethod] [TestCategory(Unit)] - public void ReportResultCodeTestCases_EmptyInput_EmptyResult() + public void ReportExitCodeTestCases_EmptyInput_EmptyResult() { - MockOptions.Setup(o => o.ReturnCodeTestCase).Returns(""); + MockOptions.Setup(o => o.ExitCodeTestCase).Returns(""); _mockAggregator.Setup(a => a.ComputeAggregatedResults(It.IsAny>())).Returns( new List { new ExecutableResult("Foo") }); - _reporter.ReportResultCodeTestCases(null, false); + _reporter.ReportExitCodeTestCases(null, false); MockFrameworkReporter .Verify(r => r.ReportTestResults(It.IsAny>()), Times.Never); @@ -48,14 +48,14 @@ public void ReportResultCodeTestCases_EmptyInput_EmptyResult() [TestMethod] [TestCategory(Unit)] - public void ReportResultCodeTestCases_Pass_CorrectResult() + public void ReportExitCodeTestCases_Pass_CorrectResult() { _mockAggregator.Setup(a => a.ComputeAggregatedResults(It.IsAny>())).Returns( new List { new ExecutableResult("Foo") }); - _reporter.ReportResultCodeTestCases(null, false); + _reporter.ReportExitCodeTestCases(null, false); MockFrameworkReporter .Verify(r => r.ReportTestResults(It.Is>( @@ -65,14 +65,14 @@ public void ReportResultCodeTestCases_Pass_CorrectResult() [TestMethod] [TestCategory(Unit)] - public void ReportResultCodeTestCases_PassWithOutput_CorrectResult() + public void ReportExitCodeTestCases_PassWithOutput_CorrectResult() { _mockAggregator.Setup(a => a.ComputeAggregatedResults(It.IsAny>())).Returns( new List { - new ExecutableResult("Foo", resultCodeOutput: new List {"Output 1", "", "Output 2"}) + new ExecutableResult("Foo", exitCodeOutput: new List {"Output 1", "", "Output 2"}) }); - _reporter.ReportResultCodeTestCases(null, false); + _reporter.ReportExitCodeTestCases(null, false); MockFrameworkReporter .Verify(r => r.ReportTestResults(It.Is>( @@ -82,14 +82,14 @@ public void ReportResultCodeTestCases_PassWithOutput_CorrectResult() [TestMethod] [TestCategory(Unit)] - public void ReportResultCodeTestCases_Fail_CorrectResult() + public void ReportExitCodeTestCases_Fail_CorrectResult() { _mockAggregator.Setup(a => a.ComputeAggregatedResults(It.IsAny>())).Returns( new List { new ExecutableResult("Foo", 1) }); - _reporter.ReportResultCodeTestCases(null, false); + _reporter.ReportExitCodeTestCases(null, false); MockFrameworkReporter .Verify(r => r.ReportTestResults(It.Is>( @@ -99,14 +99,14 @@ public void ReportResultCodeTestCases_Fail_CorrectResult() [TestMethod] [TestCategory(Unit)] - public void ReportResultCodeTestCases_FailWithOutput_CorrectResult() + public void ReportExitCodeTestCases_FailWithOutput_CorrectResult() { _mockAggregator.Setup(a => a.ComputeAggregatedResults(It.IsAny>())).Returns( new List { - new ExecutableResult("Foo", 1, resultCodeOutput: new List {"Output 1", "", "Output 2"}) + new ExecutableResult("Foo", 1, exitCodeOutput: new List {"Output 1", "", "Output 2"}) }); - _reporter.ReportResultCodeTestCases(null, false); + _reporter.ReportExitCodeTestCases(null, false); MockFrameworkReporter .Verify(r => r.ReportTestResults(It.Is>( @@ -116,15 +116,15 @@ public void ReportResultCodeTestCases_FailWithOutput_CorrectResult() [TestMethod] [TestCategory(Unit)] - public void ReportResultCodeTestCases_PassAndSkip_CorrectResult() + public void ReportExitCodeTestCases_PassAndSkip_CorrectResult() { _mockAggregator.Setup(a => a.ComputeAggregatedResults(It.IsAny>())).Returns( new List { - new ExecutableResult("Foo", resultCodeSkip: true) + new ExecutableResult("Foo", exitCodeSkip: true) }); - _reporter.ReportResultCodeTestCases(null, false); + _reporter.ReportExitCodeTestCases(null, false); MockFrameworkReporter .Verify(r => r.ReportTestResults(It.Is>( @@ -134,15 +134,15 @@ public void ReportResultCodeTestCases_PassAndSkip_CorrectResult() [TestMethod] [TestCategory(Unit)] - public void ReportResultCodeTestCases_FailAndSkip_CorrectResult() + public void ReportExitCodeTestCases_FailAndSkip_CorrectResult() { _mockAggregator.Setup(a => a.ComputeAggregatedResults(It.IsAny>())).Returns( new List { - new ExecutableResult("Foo", 1, resultCodeSkip: true) + new ExecutableResult("Foo", 1, exitCodeSkip: true) }); - _reporter.ReportResultCodeTestCases(null, false); + _reporter.ReportExitCodeTestCases(null, false); MockFrameworkReporter .Verify(r => r.ReportTestResults(It.Is>( @@ -152,7 +152,7 @@ public void ReportResultCodeTestCases_FailAndSkip_CorrectResult() [TestMethod] [TestCategory(Unit)] - public void ReportResultCodeTestCases_PassButNoOutput_WarningIsLogged() + public void ReportExitCodeTestCases_PassButNoOutput_WarningIsLogged() { MockOptions.Setup(o => o.UseNewTestExecutionFramework).Returns(false); _mockAggregator.Setup(a => a.ComputeAggregatedResults(It.IsAny>())).Returns( @@ -161,14 +161,14 @@ public void ReportResultCodeTestCases_PassButNoOutput_WarningIsLogged() new ExecutableResult("Foo") }); - _reporter.ReportResultCodeTestCases(null, true); + _reporter.ReportExitCodeTestCases(null, true); MockLogger.Verify(l => l.LogWarning(It.Is(msg => msg.Contains("collected") && msg.Contains(SettingsWrapper.OptionUseNewTestExecutionFramework))), Times.Once); } [TestMethod] [TestCategory(Unit)] - public void ReportResultCodeTestCases_FailButNoOutput_WarningIsLogged() + public void ReportExitCodeTestCases_FailButNoOutput_WarningIsLogged() { MockOptions.Setup(o => o.UseNewTestExecutionFramework).Returns(false); _mockAggregator.Setup(a => a.ComputeAggregatedResults(It.IsAny>())).Returns( @@ -177,7 +177,7 @@ public void ReportResultCodeTestCases_FailButNoOutput_WarningIsLogged() new ExecutableResult("Foo", 1) }); - _reporter.ReportResultCodeTestCases(null, true); + _reporter.ReportExitCodeTestCases(null, true); MockLogger.Verify(l => l.LogWarning(It.Is(msg => msg.Contains("collected") && msg.Contains(SettingsWrapper.OptionUseNewTestExecutionFramework))), Times.Once); } @@ -186,8 +186,8 @@ private static bool CheckResult(TestResult result, string executable, TestOutcom { return result.TestCase.Source == executable && - result.DisplayName == $"{executable}.{ResultCodeTestCaseName}" && - result.TestCase.FullyQualifiedName == $"{executable}.{ResultCodeTestCaseName}" && + result.DisplayName == $"{executable}.{ExitCodeTestCaseName}" && + result.TestCase.FullyQualifiedName == $"{executable}.{ExitCodeTestCaseName}" && result.Outcome == outcome && errorMessageParts.All(p => result.ErrorMessage.Contains(p)); } diff --git a/GoogleTestAdapter/Core.Tests/TestResults/StreamingStandardOutputTestResultParserTests.cs b/GoogleTestAdapter/Core.Tests/TestResults/StreamingStandardOutputTestResultParserTests.cs index 3ecc547c9..f7f561cf6 100644 --- a/GoogleTestAdapter/Core.Tests/TestResults/StreamingStandardOutputTestResultParserTests.cs +++ b/GoogleTestAdapter/Core.Tests/TestResults/StreamingStandardOutputTestResultParserTests.cs @@ -333,7 +333,7 @@ public void GetTestResults_OutputWithConsoleOutput_ConsoleOutputIsIgnored() [TestMethod] [TestCategory(Unit)] - public void GetTestResults_OutputWithEmptyResultCode_NoResultCodeOutputIsParsed() + public void GetTestResults_OutputWithEmptyExitCode_NoExitCodeOutputIsParsed() { string[] consoleOutput = { @"[==========] Running 1 tests from 1 test case.", @@ -348,8 +348,8 @@ public void GetTestResults_OutputWithEmptyResultCode_NoResultCodeOutputIsParsed( @"[==========] 3 tests from 1 test case ran. (36 ms total)", @"[ PASSED ] 1 test.", @"", - StreamingStandardOutputTestResultParser.GtaResultCodeOutputBegin, - StreamingStandardOutputTestResultParser.GtaResultCodeOutputEnd, + StreamingStandardOutputTestResultParser.GtaExitCodeOutputBegin, + StreamingStandardOutputTestResultParser.GtaExitCodeOutputEnd, }; var cases = GetTestCases(); @@ -357,12 +357,12 @@ public void GetTestResults_OutputWithEmptyResultCode_NoResultCodeOutputIsParsed( consoleOutput.ToList().ForEach(parser.ReportLine); parser.Flush(); - parser.ResultCodeOutput.Should().BeEmpty(); + parser.ExitCodeOutput.Should().BeEmpty(); } [TestMethod] [TestCategory(Unit)] - public void GetTestResults_OutputWithResultCode_ResultCodeOutputIsParsed() + public void GetTestResults_OutputWithExitCode_ExitCodeOutputIsParsed() { string[] consoleOutput = { @"[==========] Running 1 tests from 1 test case.", @@ -377,9 +377,9 @@ public void GetTestResults_OutputWithResultCode_ResultCodeOutputIsParsed() @"[==========] 3 tests from 1 test case ran. (36 ms total)", @"[ PASSED ] 1 test.", @"", - StreamingStandardOutputTestResultParser.GtaResultCodeOutputBegin, + StreamingStandardOutputTestResultParser.GtaExitCodeOutputBegin, @"Some test output", - StreamingStandardOutputTestResultParser.GtaResultCodeOutputEnd, + StreamingStandardOutputTestResultParser.GtaExitCodeOutputEnd, }; var cases = GetTestCases(); @@ -387,12 +387,12 @@ public void GetTestResults_OutputWithResultCode_ResultCodeOutputIsParsed() consoleOutput.ToList().ForEach(parser.ReportLine); parser.Flush(); - parser.ResultCodeOutput.Should().BeEquivalentTo("Some test output"); + parser.ExitCodeOutput.Should().BeEquivalentTo("Some test output"); } [TestMethod] [TestCategory(Unit)] - public void GetTestResults_OutputWithTwoLinesResultCode_ResultCodeOutputIsParsed() + public void GetTestResults_OutputWithTwoLinesExitCode_ExitCodeOutputIsParsed() { string[] consoleOutput = { @"[==========] Running 1 tests from 1 test case.", @@ -407,10 +407,10 @@ public void GetTestResults_OutputWithTwoLinesResultCode_ResultCodeOutputIsParsed @"[==========] 3 tests from 1 test case ran. (36 ms total)", @"[ PASSED ] 1 test.", @"", - StreamingStandardOutputTestResultParser.GtaResultCodeOutputBegin, + StreamingStandardOutputTestResultParser.GtaExitCodeOutputBegin, "Output 1", "Output 2", - StreamingStandardOutputTestResultParser.GtaResultCodeOutputEnd, + StreamingStandardOutputTestResultParser.GtaExitCodeOutputEnd, }; var cases = GetTestCases(); @@ -418,12 +418,12 @@ public void GetTestResults_OutputWithTwoLinesResultCode_ResultCodeOutputIsParsed consoleOutput.ToList().ForEach(parser.ReportLine); parser.Flush(); - parser.ResultCodeOutput.Should().BeEquivalentTo("Output 1", "Output 2"); + parser.ExitCodeOutput.Should().BeEquivalentTo("Output 1", "Output 2"); } [TestMethod] [TestCategory(Unit)] - public void GetTestResults_OutputWithTwoLinesResultCodeAndAdditionalOutput_ResultCodeOutputIsParsed() + public void GetTestResults_OutputWithTwoLinesExitCodeAndAdditionalOutput_ExitCodeOutputIsParsed() { string[] consoleOutput = { @"[==========] Running 1 tests from 1 test case.", @@ -438,10 +438,10 @@ public void GetTestResults_OutputWithTwoLinesResultCodeAndAdditionalOutput_Resul @"[==========] 3 tests from 1 test case ran. (36 ms total)", @"[ PASSED ] 1 test.", @"", - StreamingStandardOutputTestResultParser.GtaResultCodeOutputBegin, + StreamingStandardOutputTestResultParser.GtaExitCodeOutputBegin, "Output 1", "Output 2", - StreamingStandardOutputTestResultParser.GtaResultCodeOutputEnd, + StreamingStandardOutputTestResultParser.GtaExitCodeOutputEnd, "Some more output" }; var cases = GetTestCases(); @@ -450,12 +450,12 @@ public void GetTestResults_OutputWithTwoLinesResultCodeAndAdditionalOutput_Resul consoleOutput.ToList().ForEach(parser.ReportLine); parser.Flush(); - parser.ResultCodeOutput.Should().BeEquivalentTo("Output 1", "Output 2"); + parser.ExitCodeOutput.Should().BeEquivalentTo("Output 1", "Output 2"); } [TestMethod] [TestCategory(Unit)] - public void GetTestResults_OutputWithNoLinesResultCodeAndNoEnd_NoResultCodeOutputIsParsed() + public void GetTestResults_OutputWithNoLinesExitCodeAndNoEnd_NoExitCodeOutputIsParsed() { string[] consoleOutput = { @"[==========] Running 1 tests from 1 test case.", @@ -470,7 +470,7 @@ public void GetTestResults_OutputWithNoLinesResultCodeAndNoEnd_NoResultCodeOutpu @"[==========] 3 tests from 1 test case ran. (36 ms total)", @"[ PASSED ] 1 test.", @"", - StreamingStandardOutputTestResultParser.GtaResultCodeOutputBegin + StreamingStandardOutputTestResultParser.GtaExitCodeOutputBegin }; var cases = GetTestCases(); @@ -478,12 +478,12 @@ public void GetTestResults_OutputWithNoLinesResultCodeAndNoEnd_NoResultCodeOutpu consoleOutput.ToList().ForEach(parser.ReportLine); parser.Flush(); - parser.ResultCodeOutput.Should().BeEmpty(); + parser.ExitCodeOutput.Should().BeEmpty(); } [TestMethod] [TestCategory(Unit)] - public void GetTestResults_OutputWithTwoLinesResultCodeAndNoEnd_ResultCodeOutputIsParsed() + public void GetTestResults_OutputWithTwoLinesExitCodeAndNoEnd_ExitCodeOutputIsParsed() { string[] consoleOutput = { @"[==========] Running 1 tests from 1 test case.", @@ -498,7 +498,7 @@ public void GetTestResults_OutputWithTwoLinesResultCodeAndNoEnd_ResultCodeOutput @"[==========] 3 tests from 1 test case ran. (36 ms total)", @"[ PASSED ] 1 test.", @"", - StreamingStandardOutputTestResultParser.GtaResultCodeOutputBegin, + StreamingStandardOutputTestResultParser.GtaExitCodeOutputBegin, "Output 1", "Output 2", }; @@ -508,7 +508,7 @@ public void GetTestResults_OutputWithTwoLinesResultCodeAndNoEnd_ResultCodeOutput consoleOutput.ToList().ForEach(parser.ReportLine); parser.Flush(); - parser.ResultCodeOutput.Should().BeEquivalentTo("Output 1", "Output 2"); + parser.ExitCodeOutput.Should().BeEquivalentTo("Output 1", "Output 2"); } [TestMethod] diff --git a/GoogleTestAdapter/Core/Core.csproj b/GoogleTestAdapter/Core/Core.csproj index 63730bf5b..2c8018403 100644 --- a/GoogleTestAdapter/Core/Core.csproj +++ b/GoogleTestAdapter/Core/Core.csproj @@ -99,10 +99,10 @@ - - - - + + + + diff --git a/GoogleTestAdapter/Core/GoogleTestExecutor.cs b/GoogleTestAdapter/Core/GoogleTestExecutor.cs index 64a332f06..49c43f597 100644 --- a/GoogleTestAdapter/Core/GoogleTestExecutor.cs +++ b/GoogleTestAdapter/Core/GoogleTestExecutor.cs @@ -18,18 +18,18 @@ public class GoogleTestExecutor private readonly ILogger _logger; private readonly SettingsWrapper _settings; private readonly IDebuggedProcessExecutorFactory _processExecutorFactory; - private readonly IResultCodeTestsReporter _resultCodeTestsReporter; + private readonly IExitCodeTestsReporter _exitCodeTestsReporter; private readonly SchedulingAnalyzer _schedulingAnalyzer; private ITestRunner _runner; private bool _canceled; - public GoogleTestExecutor(ILogger logger, SettingsWrapper settings, IDebuggedProcessExecutorFactory processExecutorFactory, IResultCodeTestsReporter resultCodeTestsReporter) + public GoogleTestExecutor(ILogger logger, SettingsWrapper settings, IDebuggedProcessExecutorFactory processExecutorFactory, IExitCodeTestsReporter exitCodeTestsReporter) { _logger = logger; _settings = settings; _processExecutorFactory = processExecutorFactory; - _resultCodeTestsReporter = resultCodeTestsReporter; + _exitCodeTestsReporter = exitCodeTestsReporter; _schedulingAnalyzer = new SchedulingAnalyzer(logger); } @@ -50,7 +50,7 @@ public void RunTests(IEnumerable testCasesToRun, ITestFrameworkReporte _runner.RunTests(testCasesToRunAsArray, isBeingDebugged, _processExecutorFactory); - _resultCodeTestsReporter.ReportResultCodeTestCases(_runner.ExecutableResults, isBeingDebugged); + _exitCodeTestsReporter.ReportExitCodeTestCases(_runner.ExecutableResults, isBeingDebugged); if (_settings.ParallelTestExecution) _schedulingAnalyzer.PrintStatisticsToDebugOutput(); diff --git a/GoogleTestAdapter/Core/Runners/ITestRunner.cs b/GoogleTestAdapter/Core/Runners/ITestRunner.cs index b51bd936a..8d7275c18 100644 --- a/GoogleTestAdapter/Core/Runners/ITestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/ITestRunner.cs @@ -9,11 +9,11 @@ namespace GoogleTestAdapter.Runners public class ExecutableResult { public string Executable { get; } - public int ResultCode { get; } - public IReadOnlyList ResultCodeOutput { get; } - public bool ResultCodeSkip { get; } + public int ExitCode { get; } + public IReadOnlyList ExitCodeOutput { get; } + public bool ExitCodeSkip { get; } - public ExecutableResult(string executable, int resultCode = 0, IList resultCodeOutput = null, bool resultCodeSkip = false) + public ExecutableResult(string executable, int exitCode = 0, IList exitCodeOutput = null, bool exitCodeSkip = false) { if (string.IsNullOrWhiteSpace(executable)) { @@ -21,9 +21,9 @@ public ExecutableResult(string executable, int resultCode = 0, IList res } Executable = executable; - ResultCode = resultCode; - ResultCodeOutput = (IReadOnlyList) (resultCodeOutput ?? new List()); - ResultCodeSkip = resultCodeSkip; + ExitCode = exitCode; + ExitCodeOutput = (IReadOnlyList) (exitCodeOutput ?? new List()); + ExitCodeSkip = exitCodeSkip; } } diff --git a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs index b7c44319e..e901b587f 100644 --- a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs @@ -198,7 +198,7 @@ void OnNewOutputLine(string line) ? processExecutorFactory.CreateNativeDebuggingExecutor(printTestOutput, _logger) : processExecutorFactory.CreateFrameworkDebuggingExecutor(printTestOutput, _logger) : processExecutorFactory.CreateExecutor(printTestOutput, _logger); - int resultCode = _processExecutor.ExecuteCommandBlocking( + int exitCode = _processExecutor.ExecuteCommandBlocking( executable, arguments.CommandLine, workingDir, pathExtension, isTestOutputAvailable ? (Action) OnNewOutputLine : null); streamingParser.Flush(); @@ -206,8 +206,8 @@ void OnNewOutputLine(string line) if (printTestOutput) _logger.LogInfo($"{_threadName}<<<<<<<<<<<<<<< End of Output"); - ExecutableResults.Add(new ExecutableResult(executable, resultCode, streamingParser.ResultCodeOutput, - streamingParser.ResultCodeSkip)); + ExecutableResults.Add(new ExecutableResult(executable, exitCode, streamingParser.ExitCodeOutput, + streamingParser.ExitCodeSkip)); var consoleOutput = new List(); new TestDurationSerializer().UpdateTestDurations(streamingParser.TestResults); diff --git a/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs b/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs index 60bc4c4f1..922264f6b 100644 --- a/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs +++ b/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs @@ -45,7 +45,7 @@ public interface IGoogleTestAdapterSettings bool? ShowReleaseNotes { get; set; } bool? KillProcessesOnCancel { get; set; } bool? SkipOriginCheck { get; set; } - string ReturnCodeTestCase { get; set; } + string ExitCodeTestCase { get; set; } bool? UseNewTestExecutionFramework { get; set; } @@ -86,7 +86,7 @@ public static void GetUnsetValuesFrom(this IGoogleTestAdapterSettings self, IGoo self.ShowReleaseNotes = self.ShowReleaseNotes ?? other.ShowReleaseNotes; self.KillProcessesOnCancel = self.KillProcessesOnCancel ?? other.KillProcessesOnCancel; self.SkipOriginCheck = self.SkipOriginCheck ?? other.SkipOriginCheck; - self.ReturnCodeTestCase = self.ReturnCodeTestCase ?? other.ReturnCodeTestCase; + self.ExitCodeTestCase = self.ExitCodeTestCase ?? other.ExitCodeTestCase; self.UseNewTestExecutionFramework = self.UseNewTestExecutionFramework ?? other.UseNewTestExecutionFramework; diff --git a/GoogleTestAdapter/Core/Settings/RunSettings.cs b/GoogleTestAdapter/Core/Settings/RunSettings.cs index 7e5a4efe7..5ecc7a4b9 100644 --- a/GoogleTestAdapter/Core/Settings/RunSettings.cs +++ b/GoogleTestAdapter/Core/Settings/RunSettings.cs @@ -95,8 +95,8 @@ public RunSettings(string projectRegex) public bool? SkipOriginCheck { get; set; } public bool ShouldSerializeSkipOriginCheck() { return SkipOriginCheck != null; } - public string ReturnCodeTestCase { get; set; } - public bool ShouldSerializeReturnCodeTestCase() { return ReturnCodeTestCase != null; } + public string ExitCodeTestCase { get; set; } + public bool ShouldSerializeExitCodeTestCase() { return ExitCodeTestCase != null; } public virtual bool? UseNewTestExecutionFramework { get; set; } diff --git a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs index b43dcd954..04cd72f65 100644 --- a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs +++ b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs @@ -575,12 +575,12 @@ public string GetBatchForTestTeardown(string testDirectory, int threadId) public virtual bool SkipOriginCheck => _currentSettings.SkipOriginCheck ?? OptionSkipOriginCheckDefaultValue; - public const string OptionReturnCodeTestCase = "Exit code test case"; - public const string OptionReturnCodeTestCaseDefaultValue = ""; - public const string OptionReturnCodeTestCaseDescription = + public const string OptionExitCodeTestCase = "Exit code test case"; + public const string OptionExitCodeTestCaseDefaultValue = ""; + public const string OptionExitCodeTestCaseDescription = "If non-empty, an additional test case will be generated per test executable that passes if and only if the test executable returns exit code 0."; - public virtual string ReturnCodeTestCase => _currentSettings.ReturnCodeTestCase ?? OptionReturnCodeTestCaseDefaultValue; + public virtual string ExitCodeTestCase => _currentSettings.ExitCodeTestCase ?? OptionExitCodeTestCaseDefaultValue; #endregion diff --git a/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs b/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs index 551cac260..47956eb67 100644 --- a/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs +++ b/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs @@ -116,12 +116,12 @@ void OnReportOutputLine(string line) } } - if (!string.IsNullOrWhiteSpace(_settings.ReturnCodeTestCase)) + if (!string.IsNullOrWhiteSpace(_settings.ExitCodeTestCase)) { - var resultCodeTestCase = ResultCodeTestsReporter.CreateResultCodeTestCase(_settings, _executable); - testCases.Add(resultCodeTestCase); - reportTestCase?.Invoke(resultCodeTestCase); - _logger.DebugInfo($"Exit code of executable '{_executable}' is ignored for test discovery because option '{SettingsWrapper.OptionReturnCodeTestCase}' is set"); + var exitCodeTestCase = ExitCodeTestsReporter.CreateExitCodeTestCase(_settings, _executable); + testCases.Add(exitCodeTestCase); + reportTestCase?.Invoke(exitCodeTestCase); + _logger.DebugInfo($"Exit code of executable '{_executable}' is ignored for test discovery because option '{SettingsWrapper.OptionExitCodeTestCase}' is set"); } else if (!CheckProcessExitCode(processExitCode, standardOutput, workingDir, finalParams)) { diff --git a/GoogleTestAdapter/Core/TestResults/ResultCodeTestsAggregator.cs b/GoogleTestAdapter/Core/TestResults/ExitCodeTestsAggregator.cs similarity index 56% rename from GoogleTestAdapter/Core/TestResults/ResultCodeTestsAggregator.cs rename to GoogleTestAdapter/Core/TestResults/ExitCodeTestsAggregator.cs index 0a17a4d60..51e16a346 100644 --- a/GoogleTestAdapter/Core/TestResults/ResultCodeTestsAggregator.cs +++ b/GoogleTestAdapter/Core/TestResults/ExitCodeTestsAggregator.cs @@ -6,7 +6,7 @@ namespace GoogleTestAdapter.TestResults { - public class ResultCodeTestsAggregator : IResultCodeTestsAggregator + public class ExitCodeTestsAggregator : IExitCodeTestsAggregator { public IEnumerable ComputeAggregatedResults(IEnumerable allResults) { @@ -14,9 +14,9 @@ public IEnumerable ComputeAggregatedResults(IEnumerable r.Executable) .Select(results => new ExecutableResult( executable: results.Key, - resultCode: ComputeAggregatedResultCode(results), - resultCodeOutput: ComputeAggregatedOutput(results), - resultCodeSkip: results.All(r => r.ResultCodeSkip))); + exitCode: ComputeAggregatedExitCode(results), + exitCodeOutput: ComputeAggregatedOutput(results), + exitCodeSkip: results.All(r => r.ExitCodeSkip))); } private List ComputeAggregatedOutput(IEnumerable results) @@ -24,10 +24,10 @@ private List ComputeAggregatedOutput(IEnumerable resul var completeOutput = new List(); foreach (ExecutableResult result in results) { - if (result.ResultCodeOutput != null && result.ResultCodeOutput.Any(line => !string.IsNullOrWhiteSpace(line))) + if (result.ExitCodeOutput != null && result.ExitCodeOutput.Any(line => !string.IsNullOrWhiteSpace(line))) { completeOutput.Add(Environment.NewLine); - completeOutput.AddRange(result.ResultCodeOutput); + completeOutput.AddRange(result.ExitCodeOutput); } } @@ -40,13 +40,13 @@ private List ComputeAggregatedOutput(IEnumerable resul } [SuppressMessage("ReSharper", "PossibleMultipleEnumeration")] - private int ComputeAggregatedResultCode(IEnumerable results) + private int ComputeAggregatedExitCode(IEnumerable results) { - int minResultCode = results.Min(r => r.ResultCode); - int maxResultCode = results.Max(r => r.ResultCode); - return Math.Abs(maxResultCode) > Math.Abs(minResultCode) - ? maxResultCode - : minResultCode; + int minExitCode = results.Min(r => r.ExitCode); + int maxExitCode = results.Max(r => r.ExitCode); + return Math.Abs(maxExitCode) > Math.Abs(minExitCode) + ? maxExitCode + : minExitCode; } } } \ No newline at end of file diff --git a/GoogleTestAdapter/Core/TestResults/ResultCodeTestsReporter.cs b/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs similarity index 55% rename from GoogleTestAdapter/Core/TestResults/ResultCodeTestsReporter.cs rename to GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs index 789addc74..73ca63f0e 100644 --- a/GoogleTestAdapter/Core/TestResults/ResultCodeTestsReporter.cs +++ b/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs @@ -11,41 +11,41 @@ namespace GoogleTestAdapter.TestResults { - public class ResultCodeTestsReporter : IResultCodeTestsReporter + public class ExitCodeTestsReporter : IExitCodeTestsReporter { private readonly ITestFrameworkReporter _reporter; - private readonly IResultCodeTestsAggregator _resultCodeTestsAggregator; + private readonly IExitCodeTestsAggregator _exitCodeTestsAggregator; private readonly SettingsWrapper _settings; private readonly ILogger _logger; - public ResultCodeTestsReporter(ITestFrameworkReporter reporter, IResultCodeTestsAggregator resultCodeTestsAggregator, + public ExitCodeTestsReporter(ITestFrameworkReporter reporter, IExitCodeTestsAggregator exitCodeTestsAggregator, SettingsWrapper settings, ILogger logger) { _reporter = reporter; - _resultCodeTestsAggregator = resultCodeTestsAggregator; + _exitCodeTestsAggregator = exitCodeTestsAggregator; _settings = settings; _logger = logger; } - public static TestCase CreateResultCodeTestCase(SettingsWrapper settings, string executable) + public static TestCase CreateExitCodeTestCase(SettingsWrapper settings, string executable) { string filename = Path.GetFileName(executable) ?? throw new InvalidOperationException($"Can't get filename from executable '{executable}'"); - string testCaseName = $"{filename.Replace(".", "_")}.{settings.ReturnCodeTestCase}"; + string testCaseName = $"{filename.Replace(".", "_")}.{settings.ExitCodeTestCase}"; return new TestCase(testCaseName, executable, testCaseName, "", 0); } - public void ReportResultCodeTestCases(IEnumerable allResults, bool isBeingDebugged) + public void ReportExitCodeTestCases(IEnumerable allResults, bool isBeingDebugged) { - var aggregatedResults = _resultCodeTestsAggregator.ComputeAggregatedResults(allResults); + var aggregatedResults = _exitCodeTestsAggregator.ComputeAggregatedResults(allResults); bool printWarning = false; foreach (var executableResult in aggregatedResults) { _settings.ExecuteWithSettingsForExecutable(executableResult.Executable, _logger, () => { - if (!string.IsNullOrWhiteSpace(_settings.ReturnCodeTestCase)) + if (!string.IsNullOrWhiteSpace(_settings.ExitCodeTestCase)) { - ReportResultCodeTestResult(executableResult); + ReportExitCodeTestResult(executableResult); printWarning |= isBeingDebugged && !_settings.UseNewTestExecutionFramework; } }); @@ -58,54 +58,54 @@ public void ReportResultCodeTestCases(IEnumerable allResults, } } - private void ReportResultCodeTestResult(ExecutableResult executableResult) + private void ReportExitCodeTestResult(ExecutableResult executableResult) { - var resultCodeTestCase = CreateResultCodeTestCase(_settings, executableResult.Executable); - _reporter.ReportTestsStarted(resultCodeTestCase.Yield()); + var exitCodeTestCase = CreateExitCodeTestCase(_settings, executableResult.Executable); + _reporter.ReportTestsStarted(exitCodeTestCase.Yield()); TestResult testResult; - if (executableResult.ResultCode == 0) + if (executableResult.ExitCode == 0) { - testResult = CreatePassingResultCodeTestResult(resultCodeTestCase, executableResult); - if (executableResult.ResultCodeSkip) + testResult = CreatePassingExitCodeTestResult(exitCodeTestCase, executableResult); + if (executableResult.ExitCodeSkip) { testResult.Outcome = TestOutcome.Skipped; } } else { - testResult = CreateFailingResultCodeTestResult(resultCodeTestCase, executableResult, executableResult.ResultCode); + testResult = CreateFailingExitCodeTestResult(exitCodeTestCase, executableResult, executableResult.ExitCode); } _reporter.ReportTestResults(testResult.Yield()); } - private TestResult CreatePassingResultCodeTestResult(TestCase resultCodeTestCase, + private TestResult CreatePassingExitCodeTestResult(TestCase exitCodeTestCase, ExecutableResult executableResult) { var testResult = - StreamingStandardOutputTestResultParser.CreatePassedTestResult(resultCodeTestCase, + StreamingStandardOutputTestResultParser.CreatePassedTestResult(exitCodeTestCase, TimeSpan.Zero); - if (executableResult.ResultCodeOutput.Any()) + if (executableResult.ExitCodeOutput.Any()) { - testResult.ErrorMessage = string.Join(Environment.NewLine, executableResult.ResultCodeOutput); + testResult.ErrorMessage = string.Join(Environment.NewLine, executableResult.ExitCodeOutput); } return testResult; } - private TestResult CreateFailingResultCodeTestResult(TestCase resultCodeTestCase, ExecutableResult executableResult, - int resultCode) + private TestResult CreateFailingExitCodeTestResult(TestCase exitCodeTestCase, ExecutableResult executableResult, + int exitCode) { - string message = $"Exit code: {resultCode}"; - if (executableResult.ResultCodeOutput.Any()) + string message = $"Exit code: {exitCode}"; + if (executableResult.ExitCodeOutput.Any()) { message += $"{Environment.NewLine}{Environment.NewLine}"; - message += string.Join(Environment.NewLine, executableResult.ResultCodeOutput); + message += string.Join(Environment.NewLine, executableResult.ExitCodeOutput); } return StreamingStandardOutputTestResultParser - .CreateFailedTestResult(resultCodeTestCase, TimeSpan.Zero, message, ""); + .CreateFailedTestResult(exitCodeTestCase, TimeSpan.Zero, message, ""); } } } \ No newline at end of file diff --git a/GoogleTestAdapter/Core/TestResults/IResultCodeTestsAggregator.cs b/GoogleTestAdapter/Core/TestResults/IExitCodeTestsAggregator.cs similarity index 82% rename from GoogleTestAdapter/Core/TestResults/IResultCodeTestsAggregator.cs rename to GoogleTestAdapter/Core/TestResults/IExitCodeTestsAggregator.cs index a8a1404ba..7711d54f3 100644 --- a/GoogleTestAdapter/Core/TestResults/IResultCodeTestsAggregator.cs +++ b/GoogleTestAdapter/Core/TestResults/IExitCodeTestsAggregator.cs @@ -3,7 +3,7 @@ namespace GoogleTestAdapter.TestResults { - public interface IResultCodeTestsAggregator + public interface IExitCodeTestsAggregator { IEnumerable ComputeAggregatedResults(IEnumerable allResults); } diff --git a/GoogleTestAdapter/Core/TestResults/IExitCodeTestsReporter.cs b/GoogleTestAdapter/Core/TestResults/IExitCodeTestsReporter.cs new file mode 100644 index 000000000..539900615 --- /dev/null +++ b/GoogleTestAdapter/Core/TestResults/IExitCodeTestsReporter.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using GoogleTestAdapter.Runners; + +namespace GoogleTestAdapter.TestResults +{ + public interface IExitCodeTestsReporter + { + void ReportExitCodeTestCases(IEnumerable allResults, bool isBeingDebugged); + } +} \ No newline at end of file diff --git a/GoogleTestAdapter/Core/TestResults/IResultCodeTestsReporter.cs b/GoogleTestAdapter/Core/TestResults/IResultCodeTestsReporter.cs deleted file mode 100644 index 1a865c96f..000000000 --- a/GoogleTestAdapter/Core/TestResults/IResultCodeTestsReporter.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Collections.Generic; -using GoogleTestAdapter.Runners; - -namespace GoogleTestAdapter.TestResults -{ - public interface IResultCodeTestsReporter - { - void ReportResultCodeTestCases(IEnumerable allResults, bool isBeingDebugged); - } -} \ No newline at end of file diff --git a/GoogleTestAdapter/Core/TestResults/StreamingStandardOutputTestResultParser.cs b/GoogleTestAdapter/Core/TestResults/StreamingStandardOutputTestResultParser.cs index b7cad441a..5743b4d17 100644 --- a/GoogleTestAdapter/Core/TestResults/StreamingStandardOutputTestResultParser.cs +++ b/GoogleTestAdapter/Core/TestResults/StreamingStandardOutputTestResultParser.cs @@ -17,9 +17,9 @@ public class StreamingStandardOutputTestResultParser private const string Passed = "[ OK ]"; private const string Skipped = "[ SKIPPED ]"; - public const string GtaResultCodeOutputBegin = "GTA_RESULT_CODE_OUTPUT_BEGIN"; - public const string GtaResultCodeOutputEnd = "GTA_RESULT_CODE_OUTPUT_END"; - public const string GtaResultCodeSkip = "GTA_RESULT_CODE_SKIP"; + public const string GtaExitCodeOutputBegin = "GTA_EXIT_CODE_OUTPUT_BEGIN"; + public const string GtaExitCodeOutputEnd = "GTA_EXIT_CODE_OUTPUT_END"; + public const string GtaExitCodeSkip = "GTA_EXIT_CODE_SKIP"; public const string CrashText = "!! This test has probably CRASHED !!"; @@ -35,15 +35,15 @@ public class StreamingStandardOutputTestResultParser public TestCase CrashedTestCase { get; private set; } public IList TestResults { get; } = new List(); - public IList ResultCodeOutput { get; } = new List(); - public bool ResultCodeSkip { get; private set; } = false; + public IList ExitCodeOutput { get; } = new List(); + public bool ExitCodeSkip { get; private set; } = false; private readonly List _testCasesRun; private readonly ILogger _logger; private readonly ITestFrameworkReporter _reporter; private readonly List _consoleOutput = new List(); - private bool _isParsingResultCodeOutput; + private bool _isParsingExitCodeOutput; static StreamingStandardOutputTestResultParser() { @@ -80,7 +80,7 @@ public void ReportLine(string line) private void DoReportLine(string line) { - if (IsRunLine(line) || line.StartsWith(GtaResultCodeOutputBegin)) + if (IsRunLine(line) || line.StartsWith(GtaExitCodeOutputBegin)) { if (_consoleOutput.Count > 0) { @@ -94,22 +94,22 @@ private void DoReportLine(string line) } else { - _isParsingResultCodeOutput = true; + _isParsingExitCodeOutput = true; return; } } - if (line.StartsWith(GtaResultCodeOutputEnd)) + if (line.StartsWith(GtaExitCodeOutputEnd)) { - _consoleOutput.ForEach(l => ResultCodeOutput.Add(l)); + _consoleOutput.ForEach(l => ExitCodeOutput.Add(l)); _consoleOutput.Clear(); - _isParsingResultCodeOutput = false; + _isParsingExitCodeOutput = false; return; } - if (line.StartsWith(GtaResultCodeSkip)) + if (line.StartsWith(GtaExitCodeSkip)) { - ResultCodeSkip = true; + ExitCodeSkip = true; return; } @@ -120,10 +120,10 @@ public void Flush() { if (_consoleOutput.Count > 0) { - if (_isParsingResultCodeOutput) + if (_isParsingExitCodeOutput) { - _consoleOutput.ForEach(l => ResultCodeOutput.Add(l)); - _isParsingResultCodeOutput = false; + _consoleOutput.ForEach(l => ExitCodeOutput.Add(l)); + _isParsingExitCodeOutput = false; } else { diff --git a/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings b/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings index b42d41ced..40b9d756e 100644 --- a/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings +++ b/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings @@ -29,7 +29,7 @@ true true false - + diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorParallelTests.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorParallelTests.cs index 00083b99f..f2eed73f2 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorParallelTests.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorParallelTests.cs @@ -161,15 +161,15 @@ public override void RunTests_WithoutPathExtension_ExecutionFails() } [TestMethod] - public override void RunTests_ResultCodeTest_PassingTestResultIsProduced() + public override void RunTests_ExitCodeTest_PassingTestResultIsProduced() { - base.RunTests_ResultCodeTest_PassingTestResultIsProduced(); + base.RunTests_ExitCodeTest_PassingTestResultIsProduced(); } [TestMethod] - public override void RunTests_ResultCodeTest_FailingTestResultIsProduced() + public override void RunTests_ExitCodeTest_FailingTestResultIsProduced() { - base.RunTests_ResultCodeTest_FailingTestResultIsProduced(); + base.RunTests_ExitCodeTest_FailingTestResultIsProduced(); } [TestMethod] diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests.cs index 88fc86618..5c10c442e 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests.cs @@ -184,15 +184,15 @@ public override void RunTests_WithoutPathExtension_ExecutionFails() } [TestMethod] - public override void RunTests_ResultCodeTest_PassingTestResultIsProduced() + public override void RunTests_ExitCodeTest_PassingTestResultIsProduced() { - base.RunTests_ResultCodeTest_PassingTestResultIsProduced(); + base.RunTests_ExitCodeTest_PassingTestResultIsProduced(); } [TestMethod] - public override void RunTests_ResultCodeTest_FailingTestResultIsProduced() + public override void RunTests_ExitCodeTest_FailingTestResultIsProduced() { - base.RunTests_ResultCodeTest_FailingTestResultIsProduced(); + base.RunTests_ExitCodeTest_FailingTestResultIsProduced(); } [TestMethod] diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs index 599205bf8..112769237 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs @@ -187,15 +187,15 @@ public override void RunTests_CancelingExecutor_StopsTestExecution() } [TestMethod] - public override void RunTests_ResultCodeTest_PassingTestResultIsProduced() + public override void RunTests_ExitCodeTest_PassingTestResultIsProduced() { - base.RunTests_ResultCodeTest_PassingTestResultIsProduced(); + base.RunTests_ExitCodeTest_PassingTestResultIsProduced(); } [TestMethod] - public override void RunTests_ResultCodeTest_FailingTestResultIsProduced() + public override void RunTests_ExitCodeTest_FailingTestResultIsProduced() { - base.RunTests_ResultCodeTest_FailingTestResultIsProduced(); + base.RunTests_ExitCodeTest_FailingTestResultIsProduced(); } [TestMethod] diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs index 664df8803..0be48a7ad 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs @@ -99,16 +99,16 @@ public virtual void RunTests_WorkingDir_IsSetCorrectly() [TestMethod] [TestCategory(Integration)] - public virtual void RunTests_ResultCodeTest_FailingTestResultIsProduced() + public virtual void RunTests_ExitCodeTest_FailingTestResultIsProduced() { - RunResultCodeTest("TestMath.AddFails", VsTestOutcome.Failed); + RunExitCodeTest("TestMath.AddFails", VsTestOutcome.Failed); } [TestMethod] [TestCategory(Integration)] - public virtual void RunTests_ResultCodeTest_PassingTestResultIsProduced() + public virtual void RunTests_ExitCodeTest_PassingTestResultIsProduced() { - RunResultCodeTest("TestMath.AddPasses", VsTestOutcome.Passed); + RunExitCodeTest("TestMath.AddPasses", VsTestOutcome.Passed); } [TestMethod] @@ -352,8 +352,8 @@ public virtual void MemoryLeakTests_PassingWithoutLeaksRelease_CorrectResult() private void RunMemoryLeakTest(string executable, string testCaseName, VsTestOutcome testOutcome, VsTestOutcome leakCheckOutcome, Func errorMessagePredicate) { - string resultCodeTestName = "MemoryLeakTest"; - MockOptions.Setup(o => o.ReturnCodeTestCase).Returns(resultCodeTestName); + string exitCodeTestName = "MemoryLeakTest"; + MockOptions.Setup(o => o.ExitCodeTestCase).Returns(exitCodeTestName); MockOptions.Setup(o => o.AdditionalTestExecutionParam).Returns("-is_run_by_gta"); var testCases = new GoogleTestDiscoverer(MockLogger.Object, TestEnvironment.Options, @@ -372,17 +372,17 @@ private void RunMemoryLeakTest(string executable, string testCaseName, VsTestOut MockFrameworkHandle.Verify(h => h.RecordResult(It.Is(result => result.TestCase.FullyQualifiedName.EndsWith("MemoryLeakTest") && result.Outcome == leakCheckOutcome - && (result.ErrorMessage == null || !result.ErrorMessage.Contains(StreamingStandardOutputTestResultParser.GtaResultCodeOutputBegin)) - && (result.ErrorMessage == null || !result.ErrorMessage.Contains(StreamingStandardOutputTestResultParser.GtaResultCodeOutputEnd)) + && (result.ErrorMessage == null || !result.ErrorMessage.Contains(StreamingStandardOutputTestResultParser.GtaExitCodeOutputBegin)) + && (result.ErrorMessage == null || !result.ErrorMessage.Contains(StreamingStandardOutputTestResultParser.GtaExitCodeOutputEnd)) && errorMessagePredicate(result.ErrorMessage) )), Times.Once); } - private void RunResultCodeTest(string testCaseName, VsTestOutcome outcome) + private void RunExitCodeTest(string testCaseName, VsTestOutcome outcome) { - string resultCodeTestName = "ResultCode"; - MockOptions.Setup(o => o.ReturnCodeTestCase).Returns(resultCodeTestName); + string exitCodeTestName = "ExitCode"; + MockOptions.Setup(o => o.ExitCodeTestCase).Returns(exitCodeTestName); TestCase testCase = TestDataCreator.GetTestCases(testCaseName).First(); @@ -396,14 +396,14 @@ private void RunResultCodeTest(string testCaseName, VsTestOutcome outcome) Times.Once); // ReSharper disable once PossibleNullReferenceException - string finalName = Path.GetFileName(testCase.Source).Replace(".", "_") + "." + resultCodeTestName; + string finalName = Path.GetFileName(testCase.Source).Replace(".", "_") + "." + exitCodeTestName; bool outputAvailable = MockOptions.Object.UseNewTestExecutionFramework || !MockRunContext.Object.IsBeingDebugged; Func errorMessagePredicate = outcome == VsTestOutcome.Failed ? result => result.ErrorMessage.Contains("Exit code: 1") && (!outputAvailable || result.ErrorMessage.Contains("The result code output")) - && !result.ErrorMessage.Contains(StreamingStandardOutputTestResultParser.GtaResultCodeOutputBegin) - && !result.ErrorMessage.Contains(StreamingStandardOutputTestResultParser.GtaResultCodeOutputEnd) + && !result.ErrorMessage.Contains(StreamingStandardOutputTestResultParser.GtaExitCodeOutputBegin) + && !result.ErrorMessage.Contains(StreamingStandardOutputTestResultParser.GtaExitCodeOutputEnd) && !result.ErrorMessage.Contains("Some more output") : (Func) (result => result.ErrorMessage == null || result.ErrorMessage.Contains("The result code output")); MockFrameworkHandle.Verify(h => h.RecordResult(It.Is(result => diff --git a/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd b/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd index b7012a803..8ddf7f113 100644 --- a/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd +++ b/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd @@ -77,7 +77,7 @@ Corresponds to option 'Use native debugging' - + Only for internal use diff --git a/GoogleTestAdapter/TestAdapter/TestExecutor.cs b/GoogleTestAdapter/TestAdapter/TestExecutor.cs index b24fecd09..2e9e41ea8 100644 --- a/GoogleTestAdapter/TestAdapter/TestExecutor.cs +++ b/GoogleTestAdapter/TestAdapter/TestExecutor.cs @@ -226,15 +226,15 @@ private void DoRunTests(ICollection testCasesToRun, IRunContext runCon var debuggerAttacher = new MessageBasedDebuggerAttacher(_settings.DebuggingNamedPipeId, _logger); var processExecutorFactory = new DebuggedProcessExecutorFactory(frameworkHandle, debuggerAttacher); - var resultCodeTestsAggregator = new ResultCodeTestsAggregator(); - var resultCodeTestsReporter = new ResultCodeTestsReporter(reporter, resultCodeTestsAggregator, _settings, _logger); + var exitCodeTestsAggregator = new ExitCodeTestsAggregator(); + var exitCodeTestsReporter = new ExitCodeTestsReporter(reporter, exitCodeTestsAggregator, _settings, _logger); lock (_lock) { if (_canceled) return; - _executor = new GoogleTestExecutor(_logger, _settings, processExecutorFactory, resultCodeTestsReporter); + _executor = new GoogleTestExecutor(_logger, _settings, processExecutorFactory, exitCodeTestsReporter); } _executor.RunTests(testCasesToRun, reporter, runContext.IsBeingDebugged); reporter.AllTestsFinished(); diff --git a/GoogleTestAdapter/Tests.Common/Tests/ProcessExecutorTests.cs b/GoogleTestAdapter/Tests.Common/Tests/ProcessExecutorTests.cs index 23cf1fc1b..375017f25 100644 --- a/GoogleTestAdapter/Tests.Common/Tests/ProcessExecutorTests.cs +++ b/GoogleTestAdapter/Tests.Common/Tests/ProcessExecutorTests.cs @@ -52,9 +52,9 @@ protected void Test_ExecuteProcessBlocking_SampleTests() protected void Test_WithSimpleCommand_ReturnsOutputOfCommand() { var output = new List(); - int returnCode = ProcessExecutor.ExecuteCommandBlocking("cmd.exe", "/C \"echo 2\"", ".", "", line => output.Add(line)); + int exitCode = ProcessExecutor.ExecuteCommandBlocking("cmd.exe", "/C \"echo 2\"", ".", "", line => output.Add(line)); - returnCode.Should().Be(0); + exitCode.Should().Be(0); output.Should().ContainSingle(); output.Should().HaveElementAt(0, "2"); } diff --git a/GoogleTestAdapter/Tests.Common/TestsBase.cs b/GoogleTestAdapter/Tests.Common/TestsBase.cs index 05806b0b7..00100701f 100644 --- a/GoogleTestAdapter/Tests.Common/TestsBase.cs +++ b/GoogleTestAdapter/Tests.Common/TestsBase.cs @@ -92,7 +92,7 @@ public static void SetupOptions(Mock mockOptions) mockOptions.Setup(o => o.WorkingDir).Returns(SettingsWrapper.OptionWorkingDirDefaultValue); mockOptions.Setup(o => o.KillProcessesOnCancel).Returns(SettingsWrapper.OptionKillProcessesOnCancelDefaultValue); mockOptions.Setup(o => o.SkipOriginCheck).Returns(SettingsWrapper.OptionSkipOriginCheckDefaultValue); - mockOptions.Setup(o => o.ReturnCodeTestCase).Returns(SettingsWrapper.OptionReturnCodeTestCaseDefaultValue); + mockOptions.Setup(o => o.ExitCodeTestCase).Returns(SettingsWrapper.OptionExitCodeTestCaseDefaultValue); mockOptions.Setup(o => o.UseNewTestExecutionFramework).Returns(true); diff --git a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs index 5e2795f35..433b57edb 100644 --- a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs @@ -240,7 +240,7 @@ private RunSettings GetRunSettingsFromOptionPages() BatchForTestTeardown = _generalOptions.BatchForTestTeardown, KillProcessesOnCancel = _generalOptions.KillProcessesOnCancel, SkipOriginCheck = _generalOptions.SkipOriginCheck, - ReturnCodeTestCase = _generalOptions.ReturnCodeTestCase, + ExitCodeTestCase = _generalOptions.ExitCodeTestCase, CatchExceptions = _googleTestOptions.CatchExceptions, BreakOnFailure = _googleTestOptions.BreakOnFailure, diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs index e9be7bcdb..61370fca1 100644 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs @@ -244,14 +244,14 @@ public bool SkipOriginCheck private bool _skipOriginCheck = SettingsWrapper.OptionSkipOriginCheckDefaultValue; [Category(SettingsWrapper.CategoryMiscName)] - [DisplayName(SettingsWrapper.OptionReturnCodeTestCase)] - [Description(SettingsWrapper.OptionReturnCodeTestCaseDescription)] - public string ReturnCodeTestCase + [DisplayName(SettingsWrapper.OptionExitCodeTestCase)] + [Description(SettingsWrapper.OptionExitCodeTestCaseDescription)] + public string ExitCodeTestCase { - get { return _returnCodeTestCase; } - set { SetAndNotify(ref _returnCodeTestCase, value); } + get { return _exitCodeTestCase; } + set { SetAndNotify(ref _exitCodeTestCase, value); } } - private string _returnCodeTestCase = SettingsWrapper.OptionReturnCodeTestCaseDefaultValue; + private string _exitCodeTestCase = SettingsWrapper.OptionExitCodeTestCaseDefaultValue; #endregion } diff --git a/README.md b/README.md index fc82e7dab..c51d219d8 100644 --- a/README.md +++ b/README.md @@ -111,9 +111,9 @@ Note that traits are assigned in an additive manner within each phase, and in an If option *Exit code test case* is non-empty, an additional test case will be generated per text executable, and that test case will pass if and only if the test executable's exit code is 0. This allows to reflect some additional result as a test case; for instance, the test executable might be built such that it performs memory leak detection at shutdown; the result of that check can then be seen within VS as the result of the according additional test. To increase usefulness of the additional tests, a couple of tokens can used as part of a test executable's output; if GTA sees theses tokens, it will act accordingly: -* `GTA_RESULT_CODE_OUTPUT_BEGIN`: This token will make GTA capture the following output and add it to the additional test case as error message. -* `GTA_RESULT_CODE_OUTPUT_END`: This token will stop GTA from adding the following output to the error message. If it is not provided, GTA will capture the complete remaining output as error message of the additional test. -* `GTA_RESULT_CODE_SKIP`: This token will make the additional test case have outcome *Skipped* if the test executable returns with exit code 0. This can e.g. be useful if a particular check is only perfomed in Debug mode. +* `GTA_EXIT_CODE_OUTPUT_BEGIN`: This token will make GTA capture the following output and add it to the additional test case as error message. +* `GTA_EXIT_CODE_OUTPUT_END`: This token will stop GTA from adding the following output to the error message. If it is not provided, GTA will capture the complete remaining output as error message of the additional test. +* `GTA_EXIT_CODE_SKIP`: This token will make the additional test case have outcome *Skipped* if the test executable returns with exit code 0. This can e.g. be useful if a particular check is only perfomed in Debug mode. Note that when running tests in parallel, a test executable might be run more than once by GTA. In this case, the exit codes and respective outputs of a test exectutable are aggregated as follows: * The exit code reported will be the one with the greatest absolute value; e.g., if the exit codes have been -2, 0, and 1, the reported exit code will be -2. @@ -123,7 +123,7 @@ Note that when running tests in parallel, a test executable might be run more th An example usage of the *Exit code test case* can be found as part of the SampleTests solution: [Project *MemoryLeakTests*](https://github.com/csoltenborn/GoogleTestAdapter/tree/master/SampleTests/MemoryLeakTests) makes use of MS' memory leak detection facilities and reports the results to VS via the described mechanism. Things to be noted: * The mechanism is enabled for the project by means of GTA's [solution settings](https://github.com/csoltenborn/GoogleTestAdapter/blob/master/SampleTests/SampleTests.gta.runsettings). * To make sure that the test executable behaves as a normal gtest executable when not run via GTA, a command line parameter `-is_run_by_gta` is passed to it via the *Additional test execution parameters* option (again provided via the solution settings). This allows the test executable to just return the result of gtests' `RUN_ALL_TESTS()` macro if run outside GTA, and to return the result of leak detetion otherwise (i.e., return 0 if and only if no leaks have been found). In case of the provided implementation for leak detection, this means to always return with exit code 0 in the `main()` method, since the leak detection code will actively call `exit(1)` if leaks are found. -* Since leak detection is only perfomed when the executable is compiled with Debug configuration, the main method makes use of the `GTA_RESULT_CODE_SKIP` and `GTA_RESULT_CODE_OUTPUT_BEGIN` tokens to make sure the test is reported as skipped in that setting, and to additionally produce some meaningful output. +* Since leak detection is only perfomed when the executable is compiled with Debug configuration, the main method makes use of the `GTA_EXIT_CODE_SKIP` and `GTA_EXIT_CODE_OUTPUT_BEGIN` tokens to make sure the test is reported as skipped in that setting, and to additionally produce some meaningful output. * Finally, note that Google Test as of V1.8.1 [uses some memory allocation](https://github.com/google/googletest/pull/1142) which is recognized by MS' leak detection mechanism as a leak (although it isn't), in particular for failing assertions. Some of these "false positives" have been fixed with the linked issue, but there appear to be more. If you run into such problems, please report them against the [Google Test repository](https://github.com/google/googletest). #### Running tests from command line with `VSTest.Console.exe` diff --git a/SampleTests/LeakCheckTests/LeakCheckTests.cpp b/SampleTests/LeakCheckTests/LeakCheckTests.cpp index fac565a03..361f1a95f 100644 --- a/SampleTests/LeakCheckTests/LeakCheckTests.cpp +++ b/SampleTests/LeakCheckTests/LeakCheckTests.cpp @@ -80,7 +80,7 @@ namespace if (::wcsncmp(message, szStartDumpString, LENGTHOF(szStartDumpString) - 1) == 0) { if (is_run_by_gta) - std::cout << "GTA_RESULT_CODE_OUTPUT_BEGIN\n"; + std::cout << "GTA_EXIT_CODE_OUTPUT_BEGIN\n"; std::wcout << std::wstring(message) << "\n"; @@ -132,8 +132,8 @@ int main(int argc, char** argv) #ifndef _DEBUG if (is_run_by_gta) { - std::cout << "GTA_RESULT_CODE_SKIP\n"; - std::cout << "GTA_RESULT_CODE_OUTPUT_BEGIN\n"; + std::cout << "GTA_EXIT_CODE_SKIP\n"; + std::cout << "GTA_EXIT_CODE_OUTPUT_BEGIN\n"; std::cout << "Memory leak detection is only performed if compiled with Debug configuration.\n"; } #endif diff --git a/SampleTests/SampleTests.gta.runsettings b/SampleTests/SampleTests.gta.runsettings index 176d82c38..c17fd267d 100644 --- a/SampleTests/SampleTests.gta.runsettings +++ b/SampleTests/SampleTests.gta.runsettings @@ -17,7 +17,7 @@ 60 - MemoryLeakTest + MemoryLeakTest -is_run_by_gta diff --git a/SampleTests/Tests/Main.cpp b/SampleTests/Tests/Main.cpp index 9612d79b2..479a80448 100644 --- a/SampleTests/Tests/Main.cpp +++ b/SampleTests/Tests/Main.cpp @@ -33,9 +33,9 @@ int main(int argc, char ** argv) ::testing::InitGoogleTest(&argc, argv); int result = RUN_ALL_TESTS(); - std::cout << "GTA_RESULT_CODE_OUTPUT_BEGIN\n"; + std::cout << "GTA_EXIT_CODE_OUTPUT_BEGIN\n"; std::cout << "The result code output\n"; - std::cout << "GTA_RESULT_CODE_OUTPUT_END\n"; + std::cout << "GTA_EXIT_CODE_OUTPUT_END\n"; std::cout << "Some more output\n"; return result; From f4fab03fa7ec8d332cf8a7d42adfc66b451f4653 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sun, 24 Feb 2019 14:58:20 +0100 Subject: [PATCH 11/81] test output is (only) printed by process executors (except framework-based debugging) --- .../ProcessExecution/DotNetProcessExecutor.cs | 16 +- .../Core/Runners/SequentialTestRunner.cs | 10 +- .../Core/TestCases/TestCaseFactory.cs | 2 +- .../TestAdapter.Tests.csproj | 1 + .../TestExecutorParallelTests.cs | 10 +- .../TestExecutorSequentialTests.cs | 8 +- ...cutorSequentialTests_FrameworkDebugging.cs | 8 +- ...ExecutorSequentialTests_NativeDebugging.cs | 191 ++++++++++++++++++ .../TestExecutorTestsBase.cs | 36 +++- .../FrameworkDebuggedProcessExecutor.cs | 3 +- .../NativeDebuggedProcessExecutor.cs | 13 +- GoogleTestAdapter/TestAdapter/TestExecutor.cs | 8 +- 12 files changed, 279 insertions(+), 27 deletions(-) create mode 100644 GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_NativeDebugging.cs diff --git a/GoogleTestAdapter/Core/ProcessExecution/DotNetProcessExecutor.cs b/GoogleTestAdapter/Core/ProcessExecution/DotNetProcessExecutor.cs index 5dbca375d..d3d06c4f8 100644 --- a/GoogleTestAdapter/Core/ProcessExecution/DotNetProcessExecutor.cs +++ b/GoogleTestAdapter/Core/ProcessExecution/DotNetProcessExecutor.cs @@ -16,6 +16,17 @@ public class DotNetProcessExecutor : IProcessExecutor private Process _process; + public static void LogStartOfOutput(ILogger logger, string command, string parameters) + { + logger.LogInfo( + ">>>>>>>>>>>>>>> Output of command '" + command + " " + parameters + "'"); + } + + public static void LogEndOfOutput(ILogger logger) + { + logger.LogInfo("<<<<<<<<<<<<<<< End of Output"); + } + public DotNetProcessExecutor(bool printTestOutput, ILogger logger) { _printTestOutput = printTestOutput; @@ -67,8 +78,7 @@ void HandleEvent(string line, AutoResetEvent autoResetEvent) if (_printTestOutput) { - _logger.LogInfo( - ">>>>>>>>>>>>>>> Output of command '" + command + " " + parameters + "'"); + LogStartOfOutput(_logger, command, parameters); } _process.Start(); @@ -81,7 +91,7 @@ void HandleEvent(string line, AutoResetEvent autoResetEvent) { if (_printTestOutput) { - _logger.LogInfo("<<<<<<<<<<<<<<< End of Output"); + LogEndOfOutput(_logger); } return _process.ExitCode; } diff --git a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs index fc6a6c64d..8459412ac 100644 --- a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs @@ -172,17 +172,11 @@ private List RunTestExecutable(string executable, string workingDir, Com !_settings.ParallelTestExecution && isTestOutputAvailable; - if (printTestOutput) - _logger.LogInfo( - $"{_threadName}>>>>>>>>>>>>>>> Output of command '" + executable + " " + arguments.CommandLine + "'"); - void OnNewOutputLine(string line) { try { if (!_canceled) streamingParser.ReportLine(line); - - if (printTestOutput) _logger.LogInfo(line); } catch (TestRunCanceledException e) { @@ -196,14 +190,12 @@ void OnNewOutputLine(string line) ? processExecutorFactory.CreateNativeDebuggingExecutor(printTestOutput, _logger) : processExecutorFactory.CreateFrameworkDebuggingExecutor(printTestOutput, _logger) : processExecutorFactory.CreateExecutor(printTestOutput, _logger); + _processExecutor.ExecuteCommandBlocking( executable, arguments.CommandLine, workingDir, pathExtension, isTestOutputAvailable ? (Action) OnNewOutputLine : null); streamingParser.Flush(); - if (printTestOutput) - _logger.LogInfo($"{_threadName}<<<<<<<<<<<<<<< End of Output"); - var consoleOutput = new List(); new TestDurationSerializer().UpdateTestDurations(streamingParser.TestResults); _logger.DebugInfo( diff --git a/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs b/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs index 5a37f461a..be839f5b0 100644 --- a/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs +++ b/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs @@ -197,7 +197,7 @@ private TestCase CreateTestCase(TestCaseDescriptor descriptor, TestCaseLocation return testCase; } - _logger.LogWarning($"Could not find source location for test {descriptor.FullyQualifiedName}"); + _logger.LogWarning($"Could not find source location for test {descriptor.FullyQualifiedName}, executable: {_executable}"); return CreateTestCase(descriptor); } diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj b/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj index e3ec4d04d..012e4e190 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj +++ b/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj @@ -99,6 +99,7 @@ + diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorParallelTests.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorParallelTests.cs index 3ae650f83..26ddb7d67 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorParallelTests.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorParallelTests.cs @@ -51,7 +51,7 @@ public void RunTests_ParallelTestExecution_SpeedsUpTestExecution() MockOptions.Setup(o => o.ParallelTestExecution).Returns(false); Stopwatch stopwatch = new Stopwatch(); - TestExecutor executor = new TestExecutor(TestEnvironment.Logger, TestEnvironment.Options); + TestExecutor executor = new TestExecutor(TestEnvironment.Logger, TestEnvironment.Options, MockDebuggerAttacher.Object); IEnumerable testsToRun = TestResources.LongRunningTests_ReleaseX86.Yield(); stopwatch.Start(); executor.RunTests(testsToRun, MockRunContext.Object, MockFrameworkHandle.Object); @@ -61,7 +61,7 @@ public void RunTests_ParallelTestExecution_SpeedsUpTestExecution() MockOptions.Setup(o => o.ParallelTestExecution).Returns(true); MockOptions.Setup(o => o.MaxNrOfThreads).Returns(Environment.ProcessorCount); - executor = new TestExecutor(TestEnvironment.Logger, TestEnvironment.Options); + executor = new TestExecutor(TestEnvironment.Logger, TestEnvironment.Options, MockDebuggerAttacher.Object); testsToRun = TestResources.LongRunningTests_ReleaseX86.Yield(); stopwatch.Restart(); executor.RunTests(testsToRun, MockRunContext.Object, MockFrameworkHandle.Object); @@ -112,6 +112,12 @@ public override void RunTests_StaticallyLinkedX64Tests_CorrectTestResults() base.RunTests_StaticallyLinkedX64Tests_CorrectTestResults(); } + [TestMethod] + public override void RunTests_StaticallyLinkedX64Tests_OutputIsPrintedAtMostOnce() + { + base.RunTests_StaticallyLinkedX64Tests_OutputIsPrintedAtMostOnce(); + } + [TestMethod] public override void RunTests_HardCrashingX86Tests_CorrectTestResults() { diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests.cs index 5f803d43e..1d1cf5db7 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests.cs @@ -65,7 +65,7 @@ private void DoRunCancelingTests(bool killProcesses, int lower) testCasesToRun.Should().HaveCount(2); var stopwatch = new Stopwatch(); - var executor = new TestExecutor(TestEnvironment.Logger, TestEnvironment.Options); + var executor = new TestExecutor(TestEnvironment.Logger, TestEnvironment.Options, MockDebuggerAttacher.Object); var canceller = new Thread(() => { @@ -119,6 +119,12 @@ public override void RunTests_ExternallyLinkedX64_CorrectTestResults() public override void RunTests_StaticallyLinkedX64Tests_CorrectTestResults() { base.RunTests_StaticallyLinkedX64Tests_CorrectTestResults(); + } + + [TestMethod] + public override void RunTests_StaticallyLinkedX64Tests_OutputIsPrintedAtMostOnce() + { + base.RunTests_StaticallyLinkedX64Tests_OutputIsPrintedAtMostOnce(); } [TestMethod] diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs index 752492f1c..57da5832c 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs @@ -72,7 +72,7 @@ public override void RunTests_CrashingX86Tests_CorrectTestResults() [TestCategory(TestMetadata.TestCategories.Integration)] public override void RunTests_HardCrashingX86Tests_CorrectTestResults() { - TestExecutor executor = new TestExecutor(TestEnvironment.Logger, TestEnvironment.Options); + TestExecutor executor = new TestExecutor(TestEnvironment.Logger, TestEnvironment.Options, MockDebuggerAttacher.Object); executor.RunTests(TestResources.CrashingTests_DebugX86.Yield(), MockRunContext.Object, MockFrameworkHandle.Object); // test crashes, no info available if debugged via framework @@ -109,6 +109,12 @@ public override void RunTests_StaticallyLinkedX64Tests_CorrectTestResults() base.RunTests_StaticallyLinkedX64Tests_CorrectTestResults(); } + [TestMethod] + public override void RunTests_StaticallyLinkedX64Tests_OutputIsPrintedAtMostOnce() + { + base.RunTests_StaticallyLinkedX64Tests_OutputIsPrintedAtMostOnce(); + } + [TestMethod] [TestCategory(TestMetadata.TestCategories.Integration)] public override void RunTests_StaticallyLinkedX86Tests_CorrectTestResults() diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_NativeDebugging.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_NativeDebugging.cs new file mode 100644 index 000000000..89a728515 --- /dev/null +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_NativeDebugging.cs @@ -0,0 +1,191 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using GoogleTestAdapter.Helpers; +using GoogleTestAdapter.Tests.Common; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; + +namespace GoogleTestAdapter.TestAdapter +{ + [TestClass] + public class TestExecutorSequentialTests_NativeDebugging : TestExecutorSequentialTests + { + [TestInitialize] + public override void SetUp() + { + base.SetUp(); + MockOptions.Setup(o => o.UseNewTestExecutionFramework).Returns(true); + + MockRunContext.Setup(c => c.IsBeingDebugged).Returns(true); + SetUpMockFrameworkHandle(); + } + + protected override void SetUpMockFrameworkHandle() + { + MockFrameworkHandle.Setup( + h => h.LaunchProcessWithDebuggerAttached( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny>())) + .Returns((string filePath, + string workingDirectory, + string arguments, + IDictionary environmentVariables) => + { + var processStartInfo = new ProcessStartInfo(filePath, arguments) + { + WorkingDirectory = workingDirectory, + UseShellExecute = false, + CreateNoWindow = true + }; + foreach (var kvp in environmentVariables) + { + processStartInfo.EnvironmentVariables[kvp.Key] = kvp.Value; + } + + var process = new Process {StartInfo = processStartInfo}; + if (!process.Start()) + throw new Exception("WTF!"); + return process.Id; + }); + } + + [TestMethod] + [TestCategory(TestMetadata.TestCategories.Integration)] + public override void RunTests_CrashingX64Tests_CorrectTestResults() + { + base.RunTests_CrashingX64Tests_CorrectTestResults(); + } + + [TestMethod] + [TestCategory(TestMetadata.TestCategories.Integration)] + public override void RunTests_CrashingX86Tests_CorrectTestResults() + { + base.RunTests_CrashingX86Tests_CorrectTestResults(); + } + + [TestMethod] + [TestCategory(TestMetadata.TestCategories.Integration)] + public override void RunTests_HardCrashingX86Tests_CorrectTestResults() + { + base.RunTests_HardCrashingX86Tests_CorrectTestResults(); + } + + #region Method stubs for code coverage + + [TestMethod] + [TestCategory(TestMetadata.TestCategories.Integration)] + public override void RunTests_ExternallyLinkedX64_CorrectTestResults() + { + base.RunTests_ExternallyLinkedX64_CorrectTestResults(); + } + + [TestMethod] + [TestCategory(TestMetadata.TestCategories.Integration)] + public override void RunTests_ExternallyLinkedX86TestsInDebugMode_CorrectTestResults() + { + base.RunTests_ExternallyLinkedX86TestsInDebugMode_CorrectTestResults(); + } + + [TestMethod] + [TestCategory(TestMetadata.TestCategories.Integration)] + public override void RunTests_ExternallyLinkedX86Tests_CorrectTestResults() + { + base.RunTests_ExternallyLinkedX86Tests_CorrectTestResults(); + } + + [TestMethod] + [TestCategory(TestMetadata.TestCategories.Integration)] + public override void RunTests_StaticallyLinkedX64Tests_CorrectTestResults() + { + base.RunTests_StaticallyLinkedX64Tests_CorrectTestResults(); + } + + [TestMethod] + public override void RunTests_StaticallyLinkedX64Tests_OutputIsPrintedAtMostOnce() + { + base.RunTests_StaticallyLinkedX64Tests_OutputIsPrintedAtMostOnce(); + } + + [TestMethod] + [TestCategory(TestMetadata.TestCategories.Integration)] + public override void RunTests_StaticallyLinkedX86Tests_CorrectTestResults() + { + base.RunTests_StaticallyLinkedX86Tests_CorrectTestResults(); + } + + [TestMethod] + [TestCategory(TestMetadata.TestCategories.Integration)] + public override void RunTests_TestDirectoryViaUserParams_IsPassedViaCommandLineArg() + { + base.RunTests_TestDirectoryViaUserParams_IsPassedViaCommandLineArg(); + } + + [TestMethod] + [TestCategory(TestMetadata.TestCategories.Integration)] + public override void RunTests_WithNonexistingSetupBatch_LogsError() + { + base.RunTests_WithNonexistingSetupBatch_LogsError(); + } + + [TestMethod] + [TestCategory(TestMetadata.TestCategories.Integration)] + public override void RunTests_WithPathExtension_ExecutionOk() + { + base.RunTests_WithPathExtension_ExecutionOk(); + } + + [TestMethod] + [TestCategory(TestMetadata.TestCategories.Integration)] + public override void RunTests_WithSetupAndTeardownBatchesWhereSetupFails_LogsWarning() + { + base.RunTests_WithSetupAndTeardownBatchesWhereSetupFails_LogsWarning(); + } + + [TestMethod] + [TestCategory(TestMetadata.TestCategories.Integration)] + public override void RunTests_WithSetupAndTeardownBatchesWhereTeardownFails_LogsWarning() + { + base.RunTests_WithSetupAndTeardownBatchesWhereTeardownFails_LogsWarning(); + } + + [TestMethod] + [TestCategory(TestMetadata.TestCategories.Integration)] + public override void RunTests_WithoutBatches_NoLogging() + { + base.RunTests_WithoutBatches_NoLogging(); + } + + [TestMethod] + [TestCategory(TestMetadata.TestCategories.Integration)] + public override void RunTests_WithoutPathExtension_ExecutionFails() + { + base.RunTests_WithoutPathExtension_ExecutionFails(); + } + + [TestMethod] + [TestCategory(TestMetadata.TestCategories.Integration)] + public override void RunTests_WorkingDir_IsSetCorrectly() + { + base.RunTests_WorkingDir_IsSetCorrectly(); + } + + [TestMethod] + [TestCategory(TestMetadata.TestCategories.Integration)] + public override void RunTests_CancelingExecutorAndKillProcesses_StopsTestExecutionFaster() + { + base.RunTests_CancelingExecutorAndKillProcesses_StopsTestExecutionFaster(); + } + + [TestMethod] + [TestCategory(TestMetadata.TestCategories.Integration)] + public override void RunTests_CancelingExecutor_StopsTestExecution() + { + base.RunTests_CancelingExecutor_StopsTestExecution(); + } + + #endregion + } +} \ No newline at end of file diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs index 12f9f9973..6855d494d 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs @@ -7,6 +7,7 @@ using GoogleTestAdapter.Runners; using GoogleTestAdapter.Model; using GoogleTestAdapter.Settings; +using GoogleTestAdapter.TestAdapter.ProcessExecution; using GoogleTestAdapter.Tests.Common; using VsTestCase = Microsoft.VisualStudio.TestPlatform.ObjectModel.TestCase; using VsTestResult = Microsoft.VisualStudio.TestPlatform.ObjectModel.TestResult; @@ -17,6 +18,8 @@ namespace GoogleTestAdapter.TestAdapter { public abstract class TestExecutorTestsBase : TestAdapterTestsBase { + protected readonly Mock MockDebuggerAttacher = new Mock(); + private readonly bool _parallelTestExecution; private readonly int _maxNrOfThreads; @@ -48,11 +51,14 @@ public override void SetUp() MockOptions.Setup(o => o.ParallelTestExecution).Returns(_parallelTestExecution); MockOptions.Setup(o => o.MaxNrOfThreads).Returns(_maxNrOfThreads); + + MockDebuggerAttacher.Reset(); + MockDebuggerAttacher.Setup(a => a.AttachDebugger(It.IsAny())).Returns(true); } private void RunAndVerifySingleTest(TestCase testCase, VsTestOutcome expectedOutcome) { - TestExecutor executor = new TestExecutor(TestEnvironment.Logger, TestEnvironment.Options); + TestExecutor executor = new TestExecutor(TestEnvironment.Logger, TestEnvironment.Options, MockDebuggerAttacher.Object); executor.RunTests(testCase.ToVsTestCase().Yield(), MockRunContext.Object, MockFrameworkHandle.Object); foreach (VsTestOutcome outcome in Enum.GetValues(typeof(VsTestOutcome))) @@ -134,11 +140,31 @@ public virtual void RunTests_StaticallyLinkedX64Tests_CorrectTestResults() RunAndVerifyTests(TestResources.Tests_ReleaseX64, TestResources.NrOfPassingTests, TestResources.NrOfFailingTests, 0); } + [TestMethod] + [TestCategory(Integration)] + public virtual void RunTests_StaticallyLinkedX64Tests_OutputIsPrintedAtMostOnce() + { + MockOptions.Setup(o => o.PrintTestOutput).Returns(true); + MockOptions.Setup(o => o.DebugMode).Returns(false); + + RunAndVerifyTests(TestResources.Tests_ReleaseX64, TestResources.NrOfPassingTests, TestResources.NrOfFailingTests, 0); + + bool isTestOutputAvailable = + !MockOptions.Object.ParallelTestExecution && + (MockOptions.Object.UseNewTestExecutionFramework || !MockRunContext.Object.IsBeingDebugged); + int nrOfExpectedLines = isTestOutputAvailable ? 1 : 0; + + MockLogger.Verify(l => l.LogInfo(It.Is(line => line == "[----------] Global test environment set-up.")), Times.Exactly(nrOfExpectedLines)); + + MockLogger.Verify(l => l.LogInfo(It.Is(line => line.StartsWith(">>>>>>>>>>>>>>> Output of command"))), Times.Exactly(nrOfExpectedLines)); + MockLogger.Verify(l => l.LogInfo(It.Is(line => line.StartsWith("<<<<<<<<<<<<<<< End of Output"))), Times.Exactly(nrOfExpectedLines)); + } + [TestMethod] [TestCategory(Integration)] public virtual void RunTests_HardCrashingX86Tests_CorrectTestResults() { - TestExecutor executor = new TestExecutor(TestEnvironment.Logger, TestEnvironment.Options); + TestExecutor executor = new TestExecutor(TestEnvironment.Logger, TestEnvironment.Options, MockDebuggerAttacher.Object); executor.RunTests(TestResources.CrashingTests_DebugX86.Yield(), MockRunContext.Object, MockFrameworkHandle.Object); CheckMockInvocations(1, 2, 0, 3); @@ -227,7 +253,7 @@ public virtual void RunTests_WithPathExtension_ExecutionOk() string targetExe = TestDataCreator.GetPathExtensionExecutable(baseDir); MockOptions.Setup(o => o.PathExtension).Returns(SettingsWrapper.ExecutableDirPlaceholder + @"\..\dll"); - var executor = new TestExecutor(TestEnvironment.Logger, TestEnvironment.Options); + var executor = new TestExecutor(TestEnvironment.Logger, TestEnvironment.Options, MockDebuggerAttacher.Object); executor.RunTests(targetExe.Yield(), MockRunContext.Object, MockFrameworkHandle.Object); MockFrameworkHandle.Verify(h => h.RecordResult(It.Is(tr => tr.Outcome == VsTestOutcome.Passed)), Times.Once); @@ -249,7 +275,7 @@ public virtual void RunTests_WithoutPathExtension_ExecutionFails() { string targetExe = TestDataCreator.GetPathExtensionExecutable(baseDir); - var executor = new TestExecutor(TestEnvironment.Logger, TestEnvironment.Options); + var executor = new TestExecutor(TestEnvironment.Logger, TestEnvironment.Options, MockDebuggerAttacher.Object); executor.RunTests(targetExe.Yield(), MockRunContext.Object, MockFrameworkHandle.Object); MockFrameworkHandle.Verify(h => h.RecordResult(It.IsAny()), Times.Never); @@ -263,7 +289,7 @@ public virtual void RunTests_WithoutPathExtension_ExecutionFails() protected void RunAndVerifyTests(string executable, int nrOfPassedTests, int nrOfFailedTests, int nrOfUnexecutedTests, int nrOfSkippedTests = 0, bool checkNoErrorsLogged = true) { - TestExecutor executor = new TestExecutor(TestEnvironment.Logger, TestEnvironment.Options); + TestExecutor executor = new TestExecutor(TestEnvironment.Logger, TestEnvironment.Options, MockDebuggerAttacher.Object); executor.RunTests(executable.Yield(), MockRunContext.Object, MockFrameworkHandle.Object); if (checkNoErrorsLogged) diff --git a/GoogleTestAdapter/TestAdapter/ProcessExecution/FrameworkDebuggedProcessExecutor.cs b/GoogleTestAdapter/TestAdapter/ProcessExecution/FrameworkDebuggedProcessExecutor.cs index e0783ae7c..62ae82d0a 100644 --- a/GoogleTestAdapter/TestAdapter/ProcessExecution/FrameworkDebuggedProcessExecutor.cs +++ b/GoogleTestAdapter/TestAdapter/ProcessExecution/FrameworkDebuggedProcessExecutor.cs @@ -4,6 +4,7 @@ using GoogleTestAdapter.Common; using GoogleTestAdapter.Helpers; using GoogleTestAdapter.ProcessExecution.Contracts; +using GoogleTestAdapter.Settings; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter; namespace GoogleTestAdapter.TestAdapter.ProcessExecution @@ -43,7 +44,7 @@ public int ExecuteCommandBlocking(string command, string parameters, string work if (_printTestOutput) { _logger.DebugInfo( - "Note that due to restrictions of the VsTest framework, the test executable's output can not be displayed in the test console when debugging tests!"); + $"Note that due to restrictions of the VsTest framework, the test executable's output can not be displayed in the test console when debugging tests. Use '{SettingsWrapper.OptionUseNewTestExecutionFramework}' option to overcome this problem.'"); } _processId = _frameworkHandle.LaunchProcessWithDebuggerAttached(command, workingDir, parameters, envVariables); diff --git a/GoogleTestAdapter/TestAdapter/ProcessExecution/NativeDebuggedProcessExecutor.cs b/GoogleTestAdapter/TestAdapter/ProcessExecution/NativeDebuggedProcessExecutor.cs index ce8ee2394..379413dc5 100644 --- a/GoogleTestAdapter/TestAdapter/ProcessExecution/NativeDebuggedProcessExecutor.cs +++ b/GoogleTestAdapter/TestAdapter/ProcessExecution/NativeDebuggedProcessExecutor.cs @@ -13,6 +13,7 @@ using System.Text; using GoogleTestAdapter.Common; using GoogleTestAdapter.Helpers; +using GoogleTestAdapter.ProcessExecution; using GoogleTestAdapter.ProcessExecution.Contracts; using Microsoft.Win32.SafeHandles; @@ -121,6 +122,11 @@ internal static int ExecuteCommandBlocking( logger.LogError($"Could not attach debugger to process {processInfo.dwProcessId}"); } + if (printTestOutput) + { + DotNetProcessExecutor.LogStartOfOutput(logger, command, parameters); + } + ResumeThread(thread); using (var reader = new StreamReader(pipeStream, Encoding.Default)) @@ -140,8 +146,13 @@ internal static int ExecuteCommandBlocking( WaitForSingleObject(process, INFINITE); + if (printTestOutput) + { + DotNetProcessExecutor.LogEndOfOutput(logger); + } + int exitCode; - if(!GetExitCodeProcess(process, out exitCode)) + if (!GetExitCodeProcess(process, out exitCode)) throw new Win32Exception(Marshal.GetLastWin32Error(), "Could not get exit code of process"); return exitCode; diff --git a/GoogleTestAdapter/TestAdapter/TestExecutor.cs b/GoogleTestAdapter/TestAdapter/TestExecutor.cs index 103b6e017..d4125d7c7 100644 --- a/GoogleTestAdapter/TestAdapter/TestExecutor.cs +++ b/GoogleTestAdapter/TestAdapter/TestExecutor.cs @@ -28,17 +28,19 @@ public partial class TestExecutor : ITestExecutor private ILogger _logger; private SettingsWrapper _settings; + private readonly IDebuggerAttacher _debuggerAttacher; private GoogleTestExecutor _executor; private bool _canceled; // ReSharper disable once UnusedMember.Global - public TestExecutor() : this(null, null) { } + public TestExecutor() : this(null, null, null) { } - public TestExecutor(ILogger logger, SettingsWrapper settings) + public TestExecutor(ILogger logger, SettingsWrapper settings, IDebuggerAttacher debuggerAttacher) { _logger = logger; _settings = settings; + _debuggerAttacher = debuggerAttacher; } @@ -223,7 +225,7 @@ private void DoRunTests(ICollection testCasesToRun, IRunContext runCon bool isRunningInsideVisualStudio = !string.IsNullOrEmpty(runContext.SolutionDirectory); var reporter = new VsTestFrameworkReporter(frameworkHandle, isRunningInsideVisualStudio, _logger); - var debuggerAttacher = new MessageBasedDebuggerAttacher(_settings.DebuggingNamedPipeId, _logger); + var debuggerAttacher = _debuggerAttacher ?? new MessageBasedDebuggerAttacher(_settings.DebuggingNamedPipeId, _logger); var processExecutorFactory = new DebuggedProcessExecutorFactory(frameworkHandle, debuggerAttacher); lock (_lock) From 9f889f03fe851cd74413449c6e73097b96232d07 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sun, 24 Feb 2019 15:58:58 +0100 Subject: [PATCH 12/81] preparing release --- GoogleTestAdapter/Packaging.GTA/VsPackage.nuspec | 2 +- .../VsPackage.GTA/GoogleTestExtensionOptionsPage.cs | 3 +++ GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/Donations.cs | 5 ++++- GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/History.cs | 3 ++- .../VsPackage.GTA/Resources/ReleaseNotes/0.14.4.md | 4 ++++ GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj | 3 +++ README.md | 8 ++++---- appveyor.yml | 2 +- 8 files changed, 22 insertions(+), 8 deletions(-) create mode 100644 GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.14.4.md diff --git a/GoogleTestAdapter/Packaging.GTA/VsPackage.nuspec b/GoogleTestAdapter/Packaging.GTA/VsPackage.nuspec index 973a73e08..e93874d28 100644 --- a/GoogleTestAdapter/Packaging.GTA/VsPackage.nuspec +++ b/GoogleTestAdapter/Packaging.GTA/VsPackage.nuspec @@ -2,7 +2,7 @@ GoogleTestAdapter - 0.14.3 + 0.14.4 Google Test Adapter Christian Soltenborn Christian Soltenborn diff --git a/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs index c55eb1689..0a9bb2989 100644 --- a/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs @@ -48,6 +48,9 @@ private void TryDisplayReleaseNotesIfNecessary() Version formerlyInstalledVersion = versionProvider.FormerlyInstalledVersion; Version currentVersion = versionProvider.CurrentVersion; + formerlyInstalledVersion = new Version(0, 14, 0); + currentVersion = new Version(0, 14, 4); + versionProvider.UpdateLastVersion(); //if ((_generalOptions.ShowReleaseNotes || History.ForceShowReleaseNotes(formerlyInstalledVersion)) && diff --git a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/Donations.cs b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/Donations.cs index d4e57f152..ac70ff074 100644 --- a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/Donations.cs +++ b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/Donations.cs @@ -13,10 +13,13 @@ public static class Donations Therefore, if you would like to appreciate development and support of Google Test Adapter, please consider to [donate!](https://github.com/csoltenborn/GoogleTestAdapter#donations) Thanks in advance...

+Update (2/24/2019): This is most likely the final version with support for VS2012. No more donations so far - I guess I have reached my potential (allthough not my donation goals), so I'm not going to annoy you any further. Thanks once more to the donators - I've really appreciated it! +
+
Update (2/5/2019): I have again received some (and quite generous) donations - thanks a lot to Treb and Sebastian! Still not at my donation goal, though... If you happen to work with GTA in a professional manner (e.g. in a company which uses GTA to execute the C++ tests, be it within Visual Studio or on the build server), may I ask you to reconsider donating? If you need some more motivation, note that my birthday was just a couple of days ago ;-)

-Update (2/5/2019): Welcome again to my donation weekly soap :-) Responds to my last request for donations were quite a bit better and included some rather generous ones, but still a way to go until my donation goals are met. Thanks a lot to Yehuda, Walter, Thomas, Lewis, Greg, and my colleague Benedikt! I loved to hear that GTA just works for you and is indeed quite helpful. +Update (12/16/2019): Welcome again to my donation weekly soap :-) Responds to my last request for donations were quite a bit better and included some rather generous ones, but still a way to go until my donation goals are met. Thanks a lot to Yehuda, Walter, Thomas, Lewis, Greg, and my colleague Benedikt! I loved to hear that GTA just works for you and is indeed quite helpful.

Update (12/09/2018): Given the fact that I have a couple of thousands users, I must admit that I have been unpleasantly surprised by the amount of donations I received (thanks, Tim and diff --git a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/History.cs b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/History.cs index 3a29c663e..2b25e1d76 100644 --- a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/History.cs +++ b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/History.cs @@ -64,7 +64,8 @@ static History() { new Version(0, 14, 0), new DateTime(2018, 12, 9) }, { new Version(0, 14, 1), new DateTime(2018, 12, 10) }, { new Version(0, 14, 2), new DateTime(2018, 12, 16) }, - { new Version(0, 14, 3), new DateTime(2019, 2, 5) } + { new Version(0, 14, 3), new DateTime(2019, 2, 5) }, + { new Version(0, 14, 4), new DateTime(2019, 2, 24) } }; } diff --git a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.14.4.md b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.14.4.md new file mode 100644 index 000000000..d5ecfdd70 --- /dev/null +++ b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.14.4.md @@ -0,0 +1,4 @@ +**Announcement:** Microsoft has decided to force VS extensions to make use of [asynchronous package loading](https://blogs.msdn.microsoft.com/visualstudio/2018/05/16/improving-the-responsiveness-of-critical-scenarios-by-updating-auto-load-behavior-for-extensions/). Since they only provide backwards compatibility for this down to VS2013, 0.14.* will be **the last version with support for VS2012**. Support for asynchronous package loading will be added in the next version of GTA. + +Changes in this version: +* bugfix: depending on the configuration, lines of test output might have been printed twice ([#268](https://github.com/csoltenborn/GoogleTestAdapter/issues/268)) \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj b/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj index 0a1b07c37..e44e1b219 100644 --- a/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj +++ b/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj @@ -224,6 +224,9 @@ PreserveNewest + + PreserveNewest + diff --git a/README.md b/README.md index 9a365d6eb..db3508b74 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [![Build status](https://ci.appveyor.com/api/projects/status/8hdgmdy1ogqi606j/branch/master?svg=true)](https://ci.appveyor.com/project/csoltenborn/googletestadapter-u1cxh/branch/master) [![Code coverage](https://codecov.io/gh/csoltenborn/GoogleTestAdapter/branch/master/graph/badge.svg)](https://codecov.io/gh/csoltenborn/GoogleTestAdapter) -[![Visual Studio Marketplace downloads](https://img.shields.io/badge/vs_marketplace-112k-blue.svg)](https://marketplace.visualstudio.com/items?itemName=ChristianSoltenborn.GoogleTestAdapter) +[![Visual Studio Marketplace downloads](https://img.shields.io/badge/vs_marketplace-117k-blue.svg)](https://marketplace.visualstudio.com/items?itemName=ChristianSoltenborn.GoogleTestAdapter) [![NuGet downloads](https://img.shields.io/nuget/dt/GoogleTestAdapter.svg?colorB=0c7dbe&label=nuget)](https://www.nuget.org/packages/GoogleTestAdapter) @@ -49,19 +49,19 @@ Please note that I will see your donations as appreciation of my work so far and #### Installation -[![Download from Visual Studio Marketplace](https://img.shields.io/badge/vs_marketplace-v0.14.3-blue.svg)](https://marketplace.visualstudio.com/items?itemName=ChristianSoltenborn.GoogleTestAdapter) +[![Download from Visual Studio Marketplace](https://img.shields.io/badge/vs_marketplace-v0.14.4-blue.svg)](https://marketplace.visualstudio.com/items?itemName=ChristianSoltenborn.GoogleTestAdapter) [![Download from NuGet](https://img.shields.io/nuget/vpre/GoogleTestAdapter.svg?colorB=0c7dbe&label=nuget)](https://www.nuget.org/packages/GoogleTestAdapter) [![Download from GitHub](https://img.shields.io/github/release/csoltenborn/GoogleTestAdapter/all.svg?colorB=0c7dbe&label=github)](https://github.com/csoltenborn/GoogleTestAdapter/releases) Google Test Adapter can be installed in three ways: * Install through the Visual Studio Marketplace at *Tools/Extensions and Updates* - search for *Google Test Adapter*. -* Download and launch the VSIX installer from either the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=ChristianSoltenborn.GoogleTestAdapter) or [GitHub](https://github.com/csoltenborn/GoogleTestAdapter/releases/download/v0.14.3/GoogleTestAdapter-0.14.3.vsix) +* Download and launch the VSIX installer from either the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=ChristianSoltenborn.GoogleTestAdapter) or [GitHub](https://github.com/csoltenborn/GoogleTestAdapter/releases/download/v0.14.4/GoogleTestAdapter-0.14.4.vsix) * Add a NuGet dependency to the [Google test adapter nuget package](https://www.nuget.org/packages/GoogleTestAdapter/) to your Google Test projects. Note, however, that Visual Studio integration is limited this way: VS can discover and run tests, but no debugging, options or toolbar will be available; configuration is only possible through solution config files (see below). After restarting VS, your tests will be displayed in the Test Explorer at build completion time. If no or not all tests show up, have a look at the [trouble shooting section](#trouble_shooting). -Note that due to Microsoft requiring VS extensions to support [asynchronous package loading](https://blogs.msdn.microsoft.com/visualstudio/2018/05/16/improving-the-responsiveness-of-critical-scenarios-by-updating-auto-load-behavior-for-extensions/), the last version of Google Test Adapter which supports Visual Studio 2012 is [0.14.3](https://github.com/csoltenborn/GoogleTestAdapter/releases/tag/v0.14.3). +Note that due to Microsoft requiring VS extensions to support [asynchronous package loading](https://blogs.msdn.microsoft.com/visualstudio/2018/05/16/improving-the-responsiveness-of-critical-scenarios-by-updating-auto-load-behavior-for-extensions/), the last version of Google Test Adapter which supports Visual Studio 2012 is [0.14.4](https://github.com/csoltenborn/GoogleTestAdapter/releases/tag/v0.14.4). #### Configuration diff --git a/appveyor.yml b/appveyor.yml index f3334644d..7a9406204 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 0.14.3.{build} +version: 0.14.4.{build} os: - Visual Studio 2017 configuration: Release From 5f694b8d964d1befb5abe394f7d7c7616b6d3b65 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sun, 24 Feb 2019 17:37:45 +0100 Subject: [PATCH 13/81] some more changes for next version --- .../source.extension.vsixmanifest | 4 ++-- .../Framework/VSTestFrameworkReporter.cs | 2 +- .../TestAdapter/Framework/VsVersion.cs | 19 ++++++++++++++++++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/GoogleTestAdapter/Packaging.GTA/source.extension.vsixmanifest b/GoogleTestAdapter/Packaging.GTA/source.extension.vsixmanifest index d26420a88..cbd4155ad 100644 --- a/GoogleTestAdapter/Packaging.GTA/source.extension.vsixmanifest +++ b/GoogleTestAdapter/Packaging.GTA/source.extension.vsixmanifest @@ -28,7 +28,7 @@ - - + + diff --git a/GoogleTestAdapter/TestAdapter/Framework/VSTestFrameworkReporter.cs b/GoogleTestAdapter/TestAdapter/Framework/VSTestFrameworkReporter.cs index 4f890bfdd..846d07646 100644 --- a/GoogleTestAdapter/TestAdapter/Framework/VSTestFrameworkReporter.cs +++ b/GoogleTestAdapter/TestAdapter/Framework/VSTestFrameworkReporter.cs @@ -95,7 +95,7 @@ public void ReportTestResults(IEnumerable testResults) private bool TestReportingNeedsToBeThrottled() { - return VsVersionUtils.GetVisualStudioVersion(_logger) != VsVersion.VS2017; + return VsVersionUtils.GetVisualStudioVersion(_logger).NeedsToBeThrottled(); } private void ReportTestResult(TestResult testResult) diff --git a/GoogleTestAdapter/TestAdapter/Framework/VsVersion.cs b/GoogleTestAdapter/TestAdapter/Framework/VsVersion.cs index ac69651a3..a5c4330fe 100644 --- a/GoogleTestAdapter/TestAdapter/Framework/VsVersion.cs +++ b/GoogleTestAdapter/TestAdapter/Framework/VsVersion.cs @@ -14,7 +14,7 @@ namespace GoogleTestAdapter.TestAdapter.Framework [SuppressMessage("ReSharper", "InconsistentNaming")] public enum VsVersion { - Unknown = -1, VS2012 = 0, VS2012_1 = 11, VS2013 = 12, VS2015 = 14, VS2017 = 15 + Unknown = -1, VS2012 = 0, VS2012_1 = 11, VS2013 = 12, VS2015 = 14, VS2017 = 15, VS2019 = 16 } public static class VsVersionExtensions @@ -34,10 +34,27 @@ public static int Year(this VsVersion version) return 2015; case VsVersion.VS2017: return 2017; + case VsVersion.VS2019: + return 2019; default: throw new InvalidOperationException(); } } + + public static bool NeedsToBeThrottled(this VsVersion version) + { + switch (version) + { + case VsVersion.Unknown: + case VsVersion.VS2012: + case VsVersion.VS2012_1: + case VsVersion.VS2013: + case VsVersion.VS2015: + return true; + default: + return false; + } + } } public static class VsVersionUtils From 4b402fbb3b7514f2dc2d61f75fe93a655c45cb7a Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sun, 24 Feb 2019 18:44:56 +0100 Subject: [PATCH 14/81] removed debug code --- .../VsPackage.GTA/GoogleTestExtensionOptionsPage.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs index 0a9bb2989..c55eb1689 100644 --- a/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs @@ -48,9 +48,6 @@ private void TryDisplayReleaseNotesIfNecessary() Version formerlyInstalledVersion = versionProvider.FormerlyInstalledVersion; Version currentVersion = versionProvider.CurrentVersion; - formerlyInstalledVersion = new Version(0, 14, 0); - currentVersion = new Version(0, 14, 4); - versionProvider.UpdateLastVersion(); //if ((_generalOptions.ShowReleaseNotes || History.ForceShowReleaseNotes(formerlyInstalledVersion)) && From 4a29651d0eff72e26e19fdca632d04fa786c2dc5 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Mon, 25 Feb 2019 21:32:40 +0100 Subject: [PATCH 15/81] added some debug output --- GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs b/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs index 73ca63f0e..160772a78 100644 --- a/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs +++ b/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs @@ -45,8 +45,9 @@ public void ReportExitCodeTestCases(IEnumerable allResults, bo { if (!string.IsNullOrWhiteSpace(_settings.ExitCodeTestCase)) { - ReportExitCodeTestResult(executableResult); + var testResult = ReportExitCodeTestResult(executableResult); printWarning |= isBeingDebugged && !_settings.UseNewTestExecutionFramework; + _logger.DebugInfo($"Reported exit code test {testResult.DisplayName} for executable {executableResult.Executable}"); } }); } @@ -58,7 +59,7 @@ public void ReportExitCodeTestCases(IEnumerable allResults, bo } } - private void ReportExitCodeTestResult(ExecutableResult executableResult) + private TestResult ReportExitCodeTestResult(ExecutableResult executableResult) { var exitCodeTestCase = CreateExitCodeTestCase(_settings, executableResult.Executable); _reporter.ReportTestsStarted(exitCodeTestCase.Yield()); @@ -78,6 +79,7 @@ private void ReportExitCodeTestResult(ExecutableResult executableResult) } _reporter.ReportTestResults(testResult.Yield()); + return testResult; } private TestResult CreatePassingExitCodeTestResult(TestCase exitCodeTestCase, From c94c07f8558d63c51227268eabe080b36fe860b7 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Mon, 25 Feb 2019 15:54:18 +0100 Subject: [PATCH 16/81] updated FluentAssertions and Moq --- GoogleTestAdapter/Core.Tests/Core.Tests.csproj | 13 ++++++++----- GoogleTestAdapter/Core.Tests/packages.config | 7 ++++--- .../DiaResolver.Tests/DiaResolver.Tests.csproj | 13 ++++++++----- GoogleTestAdapter/DiaResolver.Tests/packages.config | 7 ++++--- .../TestAdapter.Tests/TestAdapter.Tests.csproj | 10 +++++----- .../TestAdapter.Tests/packages.config.tt | 9 +++++---- GoogleTestAdapter/Tests.Common/Tests.Common.csproj | 13 ++++++++----- GoogleTestAdapter/Tests.Common/packages.config | 7 ++++--- .../VsPackage.GTA.Tests.Unit.csproj | 13 ++++++++----- .../VsPackage.GTA.Tests.Unit/packages.config | 7 ++++--- .../VsPackage.Tests.Generated.csproj | 4 ++-- .../VsPackage.Tests.Generated/packages.config | 2 +- .../VsPackage.Tests/VsPackage.Tests.csproj | 4 ++-- .../VsPackage.Tests/packages.config.tt | 4 +--- 14 files changed, 64 insertions(+), 49 deletions(-) diff --git a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj index a43bf9364..594e8c1ff 100644 --- a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj +++ b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj @@ -46,17 +46,20 @@ ..\..\NuGetPackages\Castle.Core.4.3.1\lib\net45\Castle.Core.dll - - ..\..\NuGetPackages\FluentAssertions.5.4.2\lib\net45\FluentAssertions.dll + + ..\..\NuGetPackages\FluentAssertions.5.6.0\lib\net45\FluentAssertions.dll - ..\..\NuGetPackages\Moq.4.10.0\lib\net45\Moq.dll + ..\..\NuGetPackages\Moq.4.10.1\lib\net45\Moq.dll - - ..\..\NuGetPackages\System.Threading.Tasks.Extensions.4.3.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll + + ..\..\NuGetPackages\System.Runtime.CompilerServices.Unsafe.4.5.0\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll + + + ..\..\NuGetPackages\System.Threading.Tasks.Extensions.4.5.1\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll ..\..\NuGetPackages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll diff --git a/GoogleTestAdapter/Core.Tests/packages.config b/GoogleTestAdapter/Core.Tests/packages.config index 952b56480..14e0587be 100644 --- a/GoogleTestAdapter/Core.Tests/packages.config +++ b/GoogleTestAdapter/Core.Tests/packages.config @@ -1,10 +1,11 @@  - + - + - + + \ No newline at end of file diff --git a/GoogleTestAdapter/DiaResolver.Tests/DiaResolver.Tests.csproj b/GoogleTestAdapter/DiaResolver.Tests/DiaResolver.Tests.csproj index 64490c248..e2cd316dc 100644 --- a/GoogleTestAdapter/DiaResolver.Tests/DiaResolver.Tests.csproj +++ b/GoogleTestAdapter/DiaResolver.Tests/DiaResolver.Tests.csproj @@ -43,17 +43,20 @@ ..\..\NuGetPackages\Castle.Core.4.3.1\lib\net45\Castle.Core.dll - - ..\..\NuGetPackages\FluentAssertions.5.4.2\lib\net45\FluentAssertions.dll + + ..\..\NuGetPackages\FluentAssertions.5.6.0\lib\net45\FluentAssertions.dll - ..\..\NuGetPackages\Moq.4.10.0\lib\net45\Moq.dll + ..\..\NuGetPackages\Moq.4.10.1\lib\net45\Moq.dll - - ..\..\NuGetPackages\System.Threading.Tasks.Extensions.4.3.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll + + ..\..\NuGetPackages\System.Runtime.CompilerServices.Unsafe.4.5.0\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll + + + ..\..\NuGetPackages\System.Threading.Tasks.Extensions.4.5.1\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll ..\..\NuGetPackages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll diff --git a/GoogleTestAdapter/DiaResolver.Tests/packages.config b/GoogleTestAdapter/DiaResolver.Tests/packages.config index 6c5585477..4758e5cb6 100644 --- a/GoogleTestAdapter/DiaResolver.Tests/packages.config +++ b/GoogleTestAdapter/DiaResolver.Tests/packages.config @@ -1,10 +1,11 @@  - + - + - + + \ No newline at end of file diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj b/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj index 012e4e190..2774fbe69 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj +++ b/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj @@ -64,16 +64,16 @@ ..\..\NuGetPackages\Castle.Core.4.3.1\lib\net45\Castle.Core.dll - - ..\..\NuGetPackages\FluentAssertions.5.4.2\lib\net45\FluentAssertions.dll + + ..\..\NuGetPackages\FluentAssertions.5.6.0\lib\net45\FluentAssertions.dll - ..\..\NuGetPackages\Moq.4.10.0\lib\net45\Moq.dll + ..\..\NuGetPackages\Moq.4.10.1\lib\net45\Moq.dll - - ..\..\NuGetPackages\System.Threading.Tasks.Extensions.4.3.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll + + ..\..\NuGetPackages\System.Threading.Tasks.Extensions.4.5.1\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll ..\..\NuGetPackages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll diff --git a/GoogleTestAdapter/TestAdapter.Tests/packages.config.tt b/GoogleTestAdapter/TestAdapter.Tests/packages.config.tt index ff5694aec..62619cdda 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/packages.config.tt +++ b/GoogleTestAdapter/TestAdapter.Tests/packages.config.tt @@ -4,13 +4,14 @@ - + - - + + + <# if (TestAdapterFlavor == "GTA") { #> - + <# } else if (TestAdapterFlavor == "TAfGT") { #> <# } #> diff --git a/GoogleTestAdapter/Tests.Common/Tests.Common.csproj b/GoogleTestAdapter/Tests.Common/Tests.Common.csproj index a2bf38328..b3471a02d 100644 --- a/GoogleTestAdapter/Tests.Common/Tests.Common.csproj +++ b/GoogleTestAdapter/Tests.Common/Tests.Common.csproj @@ -46,20 +46,23 @@ ..\..\NuGetPackages\Castle.Core.4.3.1\lib\net45\Castle.Core.dll - - ..\..\NuGetPackages\FluentAssertions.5.4.2\lib\net45\FluentAssertions.dll + + ..\..\NuGetPackages\FluentAssertions.5.6.0\lib\net45\FluentAssertions.dll ..\..\NuGetPackages\Microsoft.TestPlatform.ObjectModel.11.0.1\lib\net35\Microsoft.VisualStudio.TestPlatform.ObjectModel.dll - ..\..\NuGetPackages\Moq.4.10.0\lib\net45\Moq.dll + ..\..\NuGetPackages\Moq.4.10.1\lib\net45\Moq.dll - - ..\..\NuGetPackages\System.Threading.Tasks.Extensions.4.3.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll + + ..\..\NuGetPackages\System.Runtime.CompilerServices.Unsafe.4.5.0\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll + + + ..\..\NuGetPackages\System.Threading.Tasks.Extensions.4.5.1\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll ..\..\NuGetPackages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll diff --git a/GoogleTestAdapter/Tests.Common/packages.config b/GoogleTestAdapter/Tests.Common/packages.config index 184a78bc3..ca6bd939e 100644 --- a/GoogleTestAdapter/Tests.Common/packages.config +++ b/GoogleTestAdapter/Tests.Common/packages.config @@ -1,11 +1,12 @@  - + - - + + + \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/VsPackage.GTA.Tests.Unit.csproj b/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/VsPackage.GTA.Tests.Unit.csproj index 3a0e8e2c4..f58053537 100644 --- a/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/VsPackage.GTA.Tests.Unit.csproj +++ b/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/VsPackage.GTA.Tests.Unit.csproj @@ -44,8 +44,8 @@ ..\..\NuGetPackages\Castle.Core.4.3.1\lib\net45\Castle.Core.dll - - ..\..\NuGetPackages\FluentAssertions.5.4.2\lib\net45\FluentAssertions.dll + + ..\..\NuGetPackages\FluentAssertions.5.6.0\lib\net45\FluentAssertions.dll @@ -55,13 +55,16 @@ $(NuGetPackages)Microsoft.VisualStudio.TestWindow.Interfaces.11.0.61030\lib\net45\Microsoft.VisualStudio.TestWindow.Interfaces.dll - ..\..\NuGetPackages\Moq.4.10.0\lib\net45\Moq.dll + ..\..\NuGetPackages\Moq.4.10.1\lib\net45\Moq.dll + + ..\..\NuGetPackages\System.Runtime.CompilerServices.Unsafe.4.5.0\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll + - - ..\..\NuGetPackages\System.Threading.Tasks.Extensions.4.3.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll + + ..\..\NuGetPackages\System.Threading.Tasks.Extensions.4.5.1\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll ..\..\NuGetPackages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll diff --git a/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/packages.config b/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/packages.config index fe888c0aa..d03687704 100644 --- a/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/packages.config +++ b/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/packages.config @@ -1,11 +1,12 @@  - + - - + + + \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.Tests.Generated/VsPackage.Tests.Generated.csproj b/GoogleTestAdapter/VsPackage.Tests.Generated/VsPackage.Tests.Generated.csproj index 41f7e4886..55d62ec0b 100644 --- a/GoogleTestAdapter/VsPackage.Tests.Generated/VsPackage.Tests.Generated.csproj +++ b/GoogleTestAdapter/VsPackage.Tests.Generated/VsPackage.Tests.Generated.csproj @@ -36,8 +36,8 @@ 4 - - ..\..\NuGetPackages\FluentAssertions.5.4.2\lib\net45\FluentAssertions.dll + + ..\..\NuGetPackages\FluentAssertions.5.6.0\lib\net45\FluentAssertions.dll diff --git a/GoogleTestAdapter/VsPackage.Tests.Generated/packages.config b/GoogleTestAdapter/VsPackage.Tests.Generated/packages.config index 17283114d..fb10e0025 100644 --- a/GoogleTestAdapter/VsPackage.Tests.Generated/packages.config +++ b/GoogleTestAdapter/VsPackage.Tests.Generated/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.Tests/VsPackage.Tests.csproj b/GoogleTestAdapter/VsPackage.Tests/VsPackage.Tests.csproj index 1f8cd3738..f16d46aea 100644 --- a/GoogleTestAdapter/VsPackage.Tests/VsPackage.Tests.csproj +++ b/GoogleTestAdapter/VsPackage.Tests/VsPackage.Tests.csproj @@ -39,8 +39,8 @@ ..\..\NuGetPackages\Castle.Core.4.3.1\lib\net45\Castle.Core.dll - - ..\..\NuGetPackages\FluentAssertions.5.4.2\lib\net45\FluentAssertions.dll + + ..\..\NuGetPackages\FluentAssertions.5.6.0\lib\net45\FluentAssertions.dll diff --git a/GoogleTestAdapter/VsPackage.Tests/packages.config.tt b/GoogleTestAdapter/VsPackage.Tests/packages.config.tt index e68fb8e1c..dff895a5d 100644 --- a/GoogleTestAdapter/VsPackage.Tests/packages.config.tt +++ b/GoogleTestAdapter/VsPackage.Tests/packages.config.tt @@ -4,10 +4,8 @@ - + - - <# if (TestAdapterFlavor == "GTA") { #> From b48a1a877a7f0367f3170089cc60c860040cea4e Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Mon, 25 Feb 2019 18:22:51 +0100 Subject: [PATCH 17/81] updated some dependencies on System libraries --- GoogleTestAdapter/Core.Tests/Core.Tests.csproj | 10 +++++----- GoogleTestAdapter/Core.Tests/packages.config | 6 +++--- .../DiaResolver.Tests/DiaResolver.Tests.csproj | 10 +++++----- GoogleTestAdapter/DiaResolver.Tests/packages.config | 6 +++--- .../TestAdapter.Tests/TestAdapter.Tests.csproj | 9 ++++++--- GoogleTestAdapter/TestAdapter.Tests/packages.config.tt | 6 +++--- GoogleTestAdapter/Tests.Common/Tests.Common.csproj | 10 +++++----- GoogleTestAdapter/Tests.Common/packages.config | 6 +++--- .../VsPackage.GTA.Tests.Unit.csproj | 10 +++++----- .../VsPackage.GTA.Tests.Unit/packages.config | 6 +++--- .../VsPackage.Tests.Generated.csproj | 4 ++-- .../VsPackage.Tests.Generated/packages.config | 2 +- .../VsPackage.Tests/VsPackage.Tests.csproj | 4 ++-- GoogleTestAdapter/VsPackage.Tests/packages.config.tt | 2 +- 14 files changed, 47 insertions(+), 44 deletions(-) diff --git a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj index 594e8c1ff..70a6db79b 100644 --- a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj +++ b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj @@ -55,14 +55,14 @@ - - ..\..\NuGetPackages\System.Runtime.CompilerServices.Unsafe.4.5.0\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll + + ..\..\NuGetPackages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll - ..\..\NuGetPackages\System.Threading.Tasks.Extensions.4.5.1\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll + ..\..\NuGetPackages\System.Threading.Tasks.Extensions.4.5.2\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll - - ..\..\NuGetPackages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll + + ..\..\NuGetPackages\System.ValueTuple.4.5.0\lib\netstandard1.0\System.ValueTuple.dll diff --git a/GoogleTestAdapter/Core.Tests/packages.config b/GoogleTestAdapter/Core.Tests/packages.config index 14e0587be..c82825cc2 100644 --- a/GoogleTestAdapter/Core.Tests/packages.config +++ b/GoogleTestAdapter/Core.Tests/packages.config @@ -5,7 +5,7 @@ - - - + + + \ No newline at end of file diff --git a/GoogleTestAdapter/DiaResolver.Tests/DiaResolver.Tests.csproj b/GoogleTestAdapter/DiaResolver.Tests/DiaResolver.Tests.csproj index e2cd316dc..d560ff353 100644 --- a/GoogleTestAdapter/DiaResolver.Tests/DiaResolver.Tests.csproj +++ b/GoogleTestAdapter/DiaResolver.Tests/DiaResolver.Tests.csproj @@ -52,14 +52,14 @@ - - ..\..\NuGetPackages\System.Runtime.CompilerServices.Unsafe.4.5.0\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll + + ..\..\NuGetPackages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll - ..\..\NuGetPackages\System.Threading.Tasks.Extensions.4.5.1\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll + ..\..\NuGetPackages\System.Threading.Tasks.Extensions.4.5.2\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll - - ..\..\NuGetPackages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll + + ..\..\NuGetPackages\System.ValueTuple.4.5.0\lib\netstandard1.0\System.ValueTuple.dll diff --git a/GoogleTestAdapter/DiaResolver.Tests/packages.config b/GoogleTestAdapter/DiaResolver.Tests/packages.config index 4758e5cb6..b9f419743 100644 --- a/GoogleTestAdapter/DiaResolver.Tests/packages.config +++ b/GoogleTestAdapter/DiaResolver.Tests/packages.config @@ -5,7 +5,7 @@ - - - + + + \ No newline at end of file diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj b/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj index 2774fbe69..fa2fcd559 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj +++ b/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj @@ -72,11 +72,14 @@ + + ..\..\NuGetPackages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll + - ..\..\NuGetPackages\System.Threading.Tasks.Extensions.4.5.1\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll + ..\..\NuGetPackages\System.Threading.Tasks.Extensions.4.5.2\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll - - ..\..\NuGetPackages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll + + ..\..\NuGetPackages\System.ValueTuple.4.5.0\lib\netstandard1.0\System.ValueTuple.dll diff --git a/GoogleTestAdapter/TestAdapter.Tests/packages.config.tt b/GoogleTestAdapter/TestAdapter.Tests/packages.config.tt index 62619cdda..1d63e2c6c 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/packages.config.tt +++ b/GoogleTestAdapter/TestAdapter.Tests/packages.config.tt @@ -7,9 +7,9 @@ - - - + + + <# if (TestAdapterFlavor == "GTA") { #> <# } else if (TestAdapterFlavor == "TAfGT") { #> diff --git a/GoogleTestAdapter/Tests.Common/Tests.Common.csproj b/GoogleTestAdapter/Tests.Common/Tests.Common.csproj index b3471a02d..9fbdb2bb2 100644 --- a/GoogleTestAdapter/Tests.Common/Tests.Common.csproj +++ b/GoogleTestAdapter/Tests.Common/Tests.Common.csproj @@ -58,14 +58,14 @@ - - ..\..\NuGetPackages\System.Runtime.CompilerServices.Unsafe.4.5.0\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll + + ..\..\NuGetPackages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll - ..\..\NuGetPackages\System.Threading.Tasks.Extensions.4.5.1\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll + ..\..\NuGetPackages\System.Threading.Tasks.Extensions.4.5.2\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll - - ..\..\NuGetPackages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll + + ..\..\NuGetPackages\System.ValueTuple.4.5.0\lib\netstandard1.0\System.ValueTuple.dll diff --git a/GoogleTestAdapter/Tests.Common/packages.config b/GoogleTestAdapter/Tests.Common/packages.config index ca6bd939e..82b401a63 100644 --- a/GoogleTestAdapter/Tests.Common/packages.config +++ b/GoogleTestAdapter/Tests.Common/packages.config @@ -5,8 +5,8 @@ - - - + + + \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/VsPackage.GTA.Tests.Unit.csproj b/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/VsPackage.GTA.Tests.Unit.csproj index f58053537..b85a50a1f 100644 --- a/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/VsPackage.GTA.Tests.Unit.csproj +++ b/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/VsPackage.GTA.Tests.Unit.csproj @@ -59,15 +59,15 @@ - - ..\..\NuGetPackages\System.Runtime.CompilerServices.Unsafe.4.5.0\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll + + ..\..\NuGetPackages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll - ..\..\NuGetPackages\System.Threading.Tasks.Extensions.4.5.1\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll + ..\..\NuGetPackages\System.Threading.Tasks.Extensions.4.5.2\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll - - ..\..\NuGetPackages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll + + ..\..\NuGetPackages\System.ValueTuple.4.5.0\lib\netstandard1.0\System.ValueTuple.dll diff --git a/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/packages.config b/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/packages.config index d03687704..3eda5c295 100644 --- a/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/packages.config +++ b/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/packages.config @@ -6,7 +6,7 @@ - - - + + + \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.Tests.Generated/VsPackage.Tests.Generated.csproj b/GoogleTestAdapter/VsPackage.Tests.Generated/VsPackage.Tests.Generated.csproj index 55d62ec0b..d7eaee637 100644 --- a/GoogleTestAdapter/VsPackage.Tests.Generated/VsPackage.Tests.Generated.csproj +++ b/GoogleTestAdapter/VsPackage.Tests.Generated/VsPackage.Tests.Generated.csproj @@ -41,8 +41,8 @@ - - ..\..\NuGetPackages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll + + ..\..\NuGetPackages\System.ValueTuple.4.5.0\lib\netstandard1.0\System.ValueTuple.dll diff --git a/GoogleTestAdapter/VsPackage.Tests.Generated/packages.config b/GoogleTestAdapter/VsPackage.Tests.Generated/packages.config index fb10e0025..66a2dc8a9 100644 --- a/GoogleTestAdapter/VsPackage.Tests.Generated/packages.config +++ b/GoogleTestAdapter/VsPackage.Tests.Generated/packages.config @@ -2,5 +2,5 @@ - + \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.Tests/VsPackage.Tests.csproj b/GoogleTestAdapter/VsPackage.Tests/VsPackage.Tests.csproj index f16d46aea..cee638150 100644 --- a/GoogleTestAdapter/VsPackage.Tests/VsPackage.Tests.csproj +++ b/GoogleTestAdapter/VsPackage.Tests/VsPackage.Tests.csproj @@ -112,8 +112,8 @@ - - ..\..\NuGetPackages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll + + ..\..\NuGetPackages\System.ValueTuple.4.5.0\lib\netstandard1.0\System.ValueTuple.dll diff --git a/GoogleTestAdapter/VsPackage.Tests/packages.config.tt b/GoogleTestAdapter/VsPackage.Tests/packages.config.tt index dff895a5d..5f4efb3c9 100644 --- a/GoogleTestAdapter/VsPackage.Tests/packages.config.tt +++ b/GoogleTestAdapter/VsPackage.Tests/packages.config.tt @@ -6,7 +6,7 @@ - + <# if (TestAdapterFlavor == "GTA") { #> From df5a6b66df1c0b46c83d8bb5368c36cc508da605 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Tue, 26 Feb 2019 06:21:14 +0100 Subject: [PATCH 18/81] re-added packagesconfig files for now (although generated) --- .../TestAdapter.Tests/packages.config | 11 ++++++++ GoogleTestAdapter/TestAdapter/packages.config | 27 +++++++++++++++++++ .../VsPackage.Tests/packages.config | 24 +++++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 GoogleTestAdapter/TestAdapter.Tests/packages.config create mode 100644 GoogleTestAdapter/TestAdapter/packages.config create mode 100644 GoogleTestAdapter/VsPackage.Tests/packages.config diff --git a/GoogleTestAdapter/TestAdapter.Tests/packages.config b/GoogleTestAdapter/TestAdapter.Tests/packages.config new file mode 100644 index 000000000..08e97a3be --- /dev/null +++ b/GoogleTestAdapter/TestAdapter.Tests/packages.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/GoogleTestAdapter/TestAdapter/packages.config b/GoogleTestAdapter/TestAdapter/packages.config new file mode 100644 index 000000000..198dd5a43 --- /dev/null +++ b/GoogleTestAdapter/TestAdapter/packages.config @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.Tests/packages.config b/GoogleTestAdapter/VsPackage.Tests/packages.config new file mode 100644 index 000000000..dd65cfaa6 --- /dev/null +++ b/GoogleTestAdapter/VsPackage.Tests/packages.config @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 044b48cade61d334a0d669b158749f5701aaa182 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Tue, 26 Feb 2019 06:36:48 +0100 Subject: [PATCH 19/81] added more debug output --- .../Core/ProcessExecution/DotNetProcessExecutor.cs | 3 +++ .../ProcessExecution/FrameworkDebuggedProcessExecutor.cs | 1 + .../ProcessExecution/NativeDebuggedProcessExecutor.cs | 5 +++-- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/GoogleTestAdapter/Core/ProcessExecution/DotNetProcessExecutor.cs b/GoogleTestAdapter/Core/ProcessExecution/DotNetProcessExecutor.cs index d3d06c4f8..f30b2d8ca 100644 --- a/GoogleTestAdapter/Core/ProcessExecution/DotNetProcessExecutor.cs +++ b/GoogleTestAdapter/Core/ProcessExecution/DotNetProcessExecutor.cs @@ -93,9 +93,12 @@ void HandleEvent(string line, AutoResetEvent autoResetEvent) { LogEndOfOutput(_logger); } + + _logger.DebugInfo($"Executable {command} returned with exit code {_process.ExitCode}"); return _process.ExitCode; } + _logger.DebugInfo($"Executable {command} did not return properly, using return code {int.MaxValue}"); return int.MaxValue; } } diff --git a/GoogleTestAdapter/TestAdapter/ProcessExecution/FrameworkDebuggedProcessExecutor.cs b/GoogleTestAdapter/TestAdapter/ProcessExecution/FrameworkDebuggedProcessExecutor.cs index 62ae82d0a..0fee516bd 100644 --- a/GoogleTestAdapter/TestAdapter/ProcessExecution/FrameworkDebuggedProcessExecutor.cs +++ b/GoogleTestAdapter/TestAdapter/ProcessExecution/FrameworkDebuggedProcessExecutor.cs @@ -56,6 +56,7 @@ public int ExecuteCommandBlocking(string command, string parameters, string work waiter.WaitForExit(); } + _logger.DebugInfo($"Executable {command} returned with exit code {waiter.ProcessExitCode}"); return waiter.ProcessExitCode; } diff --git a/GoogleTestAdapter/TestAdapter/ProcessExecution/NativeDebuggedProcessExecutor.cs b/GoogleTestAdapter/TestAdapter/ProcessExecution/NativeDebuggedProcessExecutor.cs index 379413dc5..b61951de0 100644 --- a/GoogleTestAdapter/TestAdapter/ProcessExecution/NativeDebuggedProcessExecutor.cs +++ b/GoogleTestAdapter/TestAdapter/ProcessExecution/NativeDebuggedProcessExecutor.cs @@ -38,8 +38,9 @@ public int ExecuteCommandBlocking(string command, string parameters, string work { try { - return NativeMethods.ExecuteCommandBlocking(command, parameters, workingDir, pathExtension, _debuggerAttacher, _logger, _printTestOutput, reportOutputLine, processId => _processId = processId); - + int exitCode = NativeMethods.ExecuteCommandBlocking(command, parameters, workingDir, pathExtension, _debuggerAttacher, _logger, _printTestOutput, reportOutputLine, processId => _processId = processId); + _logger.DebugInfo($"Executable {command} returned with exit code {exitCode}"); + return exitCode; } catch (Win32Exception ex) { From 815e4234c4bf1773afa6f5e5120ee52695d2d54f Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Tue, 26 Feb 2019 06:42:41 +0100 Subject: [PATCH 20/81] consoldated some NuGet packages --- GoogleTestAdapter/TestAdapter.Tests/packages.config | 9 +++++---- GoogleTestAdapter/VsPackage.Tests/VsPackage.Tests.csproj | 9 +++++++++ GoogleTestAdapter/VsPackage.Tests/packages.config | 9 +++++---- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/GoogleTestAdapter/TestAdapter.Tests/packages.config b/GoogleTestAdapter/TestAdapter.Tests/packages.config index 08e97a3be..a2b919a99 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/packages.config +++ b/GoogleTestAdapter/TestAdapter.Tests/packages.config @@ -1,11 +1,12 @@  - + - - - + + + + \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.Tests/VsPackage.Tests.csproj b/GoogleTestAdapter/VsPackage.Tests/VsPackage.Tests.csproj index cee638150..eddee26ff 100644 --- a/GoogleTestAdapter/VsPackage.Tests/VsPackage.Tests.csproj +++ b/GoogleTestAdapter/VsPackage.Tests/VsPackage.Tests.csproj @@ -107,11 +107,20 @@ $(NuGetPackages)Microsoft.VisualStudio.Validation.14.1.111\lib\net45\Microsoft.VisualStudio.Validation.dll True + + ..\..\NuGetPackages\Moq.4.10.1\lib\net45\Moq.dll + + + ..\..\NuGetPackages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll + + + ..\..\NuGetPackages\System.Threading.Tasks.Extensions.4.5.2\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll + ..\..\NuGetPackages\System.ValueTuple.4.5.0\lib\netstandard1.0\System.ValueTuple.dll diff --git a/GoogleTestAdapter/VsPackage.Tests/packages.config b/GoogleTestAdapter/VsPackage.Tests/packages.config index dd65cfaa6..986378f41 100644 --- a/GoogleTestAdapter/VsPackage.Tests/packages.config +++ b/GoogleTestAdapter/VsPackage.Tests/packages.config @@ -1,11 +1,8 @@  - + - - - @@ -21,4 +18,8 @@ + + + + \ No newline at end of file From cfad23c46b6548980f0f0f337fa3910e7413990b Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Tue, 26 Feb 2019 06:50:22 +0100 Subject: [PATCH 21/81] switched order of components in exit code test name for better grouping --- GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTests.cs | 2 +- .../Core.Tests/TestResults/ExitCodeTestsReporterTests.cs | 4 ++-- GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs | 2 +- GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTests.cs b/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTests.cs index 84f4935ef..58a18ba72 100644 --- a/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTests.cs +++ b/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTests.cs @@ -165,7 +165,7 @@ public void GetTestsFromExecutable_SampleTestsDebugWithExitCodeTest_FindsTestsWi var testCases = FindTests(TestResources.Tests_DebugX86, TestResources.NrOfTests + 1); - string finalName = Path.GetFileName(TestResources.Tests_DebugX86).Replace(".", "_") + "." + testCaseName; + string finalName = testCaseName + "." + Path.GetFileName(TestResources.Tests_DebugX86).Replace(".", "_"); var exitCodeTestCase = testCases.Single(tc => tc.FullyQualifiedName == finalName); exitCodeTestCase.DisplayName.Should().Be(finalName); exitCodeTestCase.Source.Should().Be(TestResources.Tests_DebugX86); diff --git a/GoogleTestAdapter/Core.Tests/TestResults/ExitCodeTestsReporterTests.cs b/GoogleTestAdapter/Core.Tests/TestResults/ExitCodeTestsReporterTests.cs index 7b4c6e8a7..033f1f26b 100644 --- a/GoogleTestAdapter/Core.Tests/TestResults/ExitCodeTestsReporterTests.cs +++ b/GoogleTestAdapter/Core.Tests/TestResults/ExitCodeTestsReporterTests.cs @@ -186,8 +186,8 @@ private static bool CheckResult(TestResult result, string executable, TestOutcom { return result.TestCase.Source == executable && - result.DisplayName == $"{executable}.{ExitCodeTestCaseName}" && - result.TestCase.FullyQualifiedName == $"{executable}.{ExitCodeTestCaseName}" && + result.DisplayName == $"{ExitCodeTestCaseName}.{executable}" && + result.TestCase.FullyQualifiedName == $"{ExitCodeTestCaseName}.{executable}" && result.Outcome == outcome && errorMessageParts.All(p => result.ErrorMessage.Contains(p)); } diff --git a/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs b/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs index 160772a78..882646d4d 100644 --- a/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs +++ b/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs @@ -30,7 +30,7 @@ public ExitCodeTestsReporter(ITestFrameworkReporter reporter, IExitCodeTestsAggr public static TestCase CreateExitCodeTestCase(SettingsWrapper settings, string executable) { string filename = Path.GetFileName(executable) ?? throw new InvalidOperationException($"Can't get filename from executable '{executable}'"); - string testCaseName = $"{filename.Replace(".", "_")}.{settings.ExitCodeTestCase}"; + string testCaseName = $"{settings.ExitCodeTestCase}.{filename.Replace(".", "_")}"; return new TestCase(testCaseName, executable, testCaseName, "", 0); } diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs index bd8ebd384..715b18387 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs @@ -396,7 +396,7 @@ private void RunMemoryLeakTest(string executable, string testCaseName, VsTestOut Times.Once); MockFrameworkHandle.Verify(h => h.RecordResult(It.Is(result => - result.TestCase.FullyQualifiedName.EndsWith("MemoryLeakTest") + result.TestCase.FullyQualifiedName.StartsWith("MemoryLeakTest") && result.Outcome == leakCheckOutcome && (result.ErrorMessage == null || !result.ErrorMessage.Contains(StreamingStandardOutputTestResultParser.GtaExitCodeOutputBegin)) && (result.ErrorMessage == null || !result.ErrorMessage.Contains(StreamingStandardOutputTestResultParser.GtaExitCodeOutputEnd)) @@ -422,7 +422,7 @@ private void RunExitCodeTest(string testCaseName, VsTestOutcome outcome) Times.Once); // ReSharper disable once PossibleNullReferenceException - string finalName = Path.GetFileName(testCase.Source).Replace(".", "_") + "." + exitCodeTestName; + string finalName = exitCodeTestName + "." + Path.GetFileName(testCase.Source).Replace(".", "_"); bool outputAvailable = MockOptions.Object.UseNewTestExecutionFramework || !MockRunContext.Object.IsBeingDebugged; Func errorMessagePredicate = outcome == VsTestOutcome.Failed From 80fb3b0fdd2b496de8bd456e1d862f97c72c66a8 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Tue, 26 Feb 2019 21:08:49 +0100 Subject: [PATCH 22/81] exit code tests have main method as source location --- .../Core.Tests/GoogleTestDiscovererTests.cs | 4 +- .../TestCases/TestCaseResolverTests.cs | 4 +- .../Core/TestCases/TestCaseFactory.cs | 12 ++--- .../Core/TestCases/TestCaseResolver.cs | 54 ++++++++++++++----- .../Core/TestResults/ExitCodeTestsReporter.cs | 8 ++- .../TestExecutorTestsBase.cs | 4 ++ .../Tests.Common/TestResources.cs | 6 +-- .../Tests/ProcessExecutorTests.cs | 2 +- ...soleDllTests__List_TestsOf_SampleTests.txt | 1 + ...eDllTests__List_TestsOf_SampleTests170.txt | 1 + ...tionProjectSettings_Coverage_Isolation.xml | 25 ++++++++- ...tionProjectSettings_Coverage_Isolation.xml | 29 +++++++++- SampleTests/Tests/MainMethodTest.cpp | 25 +++++++++ SampleTests/Tests/Tests.vcxproj | 1 + SampleTests/Tests/Tests.vcxproj.filters | 3 ++ SampleTests/Tests_1.7.0/Tests_1.7.0.vcxproj | 1 + .../Tests_1.7.0/Tests_1.7.0.vcxproj.filters | 3 ++ 17 files changed, 150 insertions(+), 33 deletions(-) create mode 100644 SampleTests/Tests/MainMethodTest.cpp diff --git a/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTests.cs b/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTests.cs index 58a18ba72..e6500b1fe 100644 --- a/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTests.cs +++ b/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTests.cs @@ -169,8 +169,8 @@ public void GetTestsFromExecutable_SampleTestsDebugWithExitCodeTest_FindsTestsWi var exitCodeTestCase = testCases.Single(tc => tc.FullyQualifiedName == finalName); exitCodeTestCase.DisplayName.Should().Be(finalName); exitCodeTestCase.Source.Should().Be(TestResources.Tests_DebugX86); - exitCodeTestCase.CodeFilePath.Should().BeEmpty(); - exitCodeTestCase.LineNumber.Should().Be(0); + exitCodeTestCase.CodeFilePath.Should().Contain(@"sampletests\tests\main.cpp"); + exitCodeTestCase.LineNumber.Should().Be(8); MockLogger.Verify(l => l.DebugInfo(It.Is(msg => msg.Contains("Exit code") && msg.Contains("ignored"))), Times.Once); } diff --git a/GoogleTestAdapter/Core.Tests/TestCases/TestCaseResolverTests.cs b/GoogleTestAdapter/Core.Tests/TestCases/TestCaseResolverTests.cs index 5e6cc7624..4c20f3686 100644 --- a/GoogleTestAdapter/Core.Tests/TestCases/TestCaseResolverTests.cs +++ b/GoogleTestAdapter/Core.Tests/TestCases/TestCaseResolverTests.cs @@ -72,8 +72,8 @@ private void AssertCorrectTestLocationIsFound(string suite, uint line) $"{suite}.Test", TestCaseDescriptor.TestTypes.Simple); var signatures = new MethodSignatureCreator().GetTestMethodSignatures(descriptor); - var resolver = new TestCaseResolver(TestResources.Tests_ReleaseX64, "", "".Yield(), - new DefaultDiaResolverFactory(), true, _fakeLogger); + var resolver = new TestCaseResolver(TestResources.Tests_ReleaseX64, + new DefaultDiaResolverFactory(), MockOptions.Object, _fakeLogger); var testCaseLocation = resolver.FindTestCaseLocation(signatures.ToList()); diff --git a/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs b/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs index 3de3ea3eb..c8cb95da8 100644 --- a/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs +++ b/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs @@ -43,13 +43,7 @@ public IList CreateTestCases(Action reportTestCase = null) var standardOutput = new List(); var testCases = new List(); - var resolver = new TestCaseResolver( - _executable, - _settings.GetPathExtension(_executable), - _settings.GetAdditionalPdbs(_executable), - _diaResolverFactory, - _settings.ParseSymbolInformation, - _logger); + var resolver = new TestCaseResolver(_executable, _diaResolverFactory, _settings, _logger); var suite2TestCases = new Dictionary>(); var parser = new StreamingListTestsParser(_settings.TestNameSeparator); @@ -71,7 +65,9 @@ public IList CreateTestCases(Action reportTestCase = null) ISet testCasesOfSuite; if (!suite2TestCases.TryGetValue(args.TestCaseDescriptor.Suite, out testCasesOfSuite)) + { suite2TestCases.Add(args.TestCaseDescriptor.Suite, testCasesOfSuite = new HashSet()); + } testCasesOfSuite.Add(testCase); }; @@ -118,7 +114,7 @@ void OnReportOutputLine(string line) if (!string.IsNullOrWhiteSpace(_settings.ExitCodeTestCase)) { - var exitCodeTestCase = ExitCodeTestsReporter.CreateExitCodeTestCase(_settings, _executable); + var exitCodeTestCase = ExitCodeTestsReporter.CreateExitCodeTestCase(_settings, _executable, resolver.MainMethodLocation); testCases.Add(exitCodeTestCase); reportTestCase?.Invoke(exitCodeTestCase); _logger.DebugInfo($"Exit code of executable '{_executable}' is ignored for test discovery because option '{SettingsWrapper.OptionExitCodeTestCase}' is set"); diff --git a/GoogleTestAdapter/Core/TestCases/TestCaseResolver.cs b/GoogleTestAdapter/Core/TestCases/TestCaseResolver.cs index dd5cc87fb..75490e07b 100644 --- a/GoogleTestAdapter/Core/TestCases/TestCaseResolver.cs +++ b/GoogleTestAdapter/Core/TestCases/TestCaseResolver.cs @@ -7,6 +7,7 @@ using GoogleTestAdapter.DiaResolver; using GoogleTestAdapter.Helpers; using GoogleTestAdapter.Model; +using GoogleTestAdapter.Settings; using MethodSignature = GoogleTestAdapter.TestCases.MethodSignatureCreator.MethodSignature; namespace GoogleTestAdapter.TestCases @@ -19,9 +20,8 @@ public class TestCaseResolver private const string TraitAppendix = "_GTA_TRAIT"; private readonly string _executable; - private readonly string _pathExtension; - private readonly IEnumerable _additionalPdbs; private readonly IDiaResolverFactory _diaResolverFactory; + private readonly SettingsWrapper _settings; private readonly ILogger _logger; private readonly List _allTestMethodSymbols = new List(); @@ -30,17 +30,16 @@ public class TestCaseResolver private bool _loadedSymbolsFromAdditionalPdbs; private bool _loadedSymbolsFromImports; - public TestCaseResolver(string executable, string pathExtension, IEnumerable additionalPdbs, IDiaResolverFactory diaResolverFactory, bool parseSymbolInformation, ILogger logger) + public TestCaseResolver(string executable, IDiaResolverFactory diaResolverFactory, SettingsWrapper settings, ILogger logger) { _executable = executable; - _pathExtension = pathExtension; - _additionalPdbs = additionalPdbs; _diaResolverFactory = diaResolverFactory; + _settings = settings; _logger = logger; - if (parseSymbolInformation) + if (_settings.ParseSymbolInformation) { - AddSymbolsFromBinary(executable); + AddSymbolsFromBinary(executable, true); } else { @@ -49,6 +48,8 @@ public TestCaseResolver(string executable, string pathExtension, IEnumerable testMethodSignatures) { TestCaseLocation result = DoFindTestCaseLocation(testMethodSignatures); @@ -69,7 +70,7 @@ public TestCaseLocation FindTestCaseLocation(List testMethodSig private void LoadSymbolsFromAdditionalPdbs() { - foreach (var pdbPattern in _additionalPdbs) + foreach (var pdbPattern in _settings.GetAdditionalPdbs(_executable)) { var matchingFiles = Utils.GetMatchingFiles(pdbPattern, _logger); if (matchingFiles.Length == 0) @@ -100,19 +101,19 @@ private void LoadSymbolsFromImports() } } - private void AddSymbolsFromBinary(string binary) + private void AddSymbolsFromBinary(string binary, bool resolveMainMethod = false) { - string pdb = PdbLocator.FindPdbFile(binary, _pathExtension, _logger); + string pdb = PdbLocator.FindPdbFile(binary, _settings.GetPathExtension(_executable), _logger); if (pdb == null) { _logger.DebugWarning($"No .pdb file found for '{binary}'"); return; } - AddSymbolsFromBinary(binary, pdb); + AddSymbolsFromBinary(binary, pdb, resolveMainMethod); } - private void AddSymbolsFromBinary(string binary, string pdb) + private void AddSymbolsFromBinary(string binary, string pdb, bool resolveMainMethod = false) { using (IDiaResolver diaResolver = _diaResolverFactory.Create(binary, pdb, _logger)) { @@ -120,8 +121,12 @@ private void AddSymbolsFromBinary(string binary, string pdb) { _allTestMethodSymbols.AddRange(diaResolver.GetFunctions("*" + GoogleTestConstants.TestBodySignature)); _allTraitSymbols.AddRange(diaResolver.GetFunctions("*" + TraitAppendix)); - _logger.DebugInfo($"Found {_allTestMethodSymbols.Count} test method symbols and {_allTraitSymbols.Count} trait symbols in binary {binary}, pdb {pdb}"); + + if (resolveMainMethod) + { + MainMethodLocation = ResolveMainMethod(diaResolver); + } } catch (Exception e) { @@ -130,6 +135,29 @@ private void AddSymbolsFromBinary(string binary, string pdb) } } + private TestCaseLocation ResolveMainMethod(IDiaResolver diaResolver) + { + var mainSymbols = new List(); + mainSymbols.AddRange(diaResolver.GetFunctions("main")); + + if (!string.IsNullOrWhiteSpace(_settings.ExitCodeTestCase)) + { + if (mainSymbols.Count == 0) + { + _logger.DebugWarning( + $"Could not find any main method for executable {_executable} - exit code test will not have source location"); + } + else if (mainSymbols.Count > 1) + { + _logger.DebugWarning( + $"Found more than one potential main method in executable {_executable} - exit code test might have wrong source location"); + } + } + + var location = mainSymbols.FirstOrDefault(); + return location != null ? ToTestCaseLocation(location) : null; + } + private TestCaseLocation DoFindTestCaseLocation(List testMethodSignatures) { var sourceFileLocation = _allTestMethodSymbols diff --git a/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs b/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs index 882646d4d..ca34f8ccb 100644 --- a/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs +++ b/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs @@ -8,6 +8,7 @@ using GoogleTestAdapter.Model; using GoogleTestAdapter.Runners; using GoogleTestAdapter.Settings; +using GoogleTestAdapter.TestCases; namespace GoogleTestAdapter.TestResults { @@ -27,11 +28,14 @@ public ExitCodeTestsReporter(ITestFrameworkReporter reporter, IExitCodeTestsAggr _logger = logger; } - public static TestCase CreateExitCodeTestCase(SettingsWrapper settings, string executable) + public static TestCase CreateExitCodeTestCase(SettingsWrapper settings, string executable, TestCaseLocation mainMethodLocation = null) { string filename = Path.GetFileName(executable) ?? throw new InvalidOperationException($"Can't get filename from executable '{executable}'"); string testCaseName = $"{settings.ExitCodeTestCase}.{filename.Replace(".", "_")}"; - return new TestCase(testCaseName, executable, testCaseName, "", 0); + string sourceFile = mainMethodLocation?.Sourcefile ?? ""; + int line = (int) (mainMethodLocation?.Line ?? 0); + + return new TestCase(testCaseName, executable, testCaseName, sourceFile, line); } public void ReportExitCodeTestCases(IEnumerable allResults, bool isBeingDebugged) diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs index 715b18387..0f8518b24 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs @@ -403,6 +403,8 @@ private void RunMemoryLeakTest(string executable, string testCaseName, VsTestOut && errorMessagePredicate(result.ErrorMessage) )), Times.Once); + + MockLogger.Verify(l => l.DebugWarning(It.Is(msg => msg.Contains("main method") && msg.Contains("exit code"))), Times.Never); } private void RunExitCodeTest(string testCaseName, VsTestOutcome outcome) @@ -446,6 +448,8 @@ private void RunExitCodeTest(string testCaseName, VsTestOutcome outcome) MockLogger.Verify(l => l.LogWarning(It.Is(msg => msg.Contains("Result code") && msg.Contains(SettingsWrapper.OptionUseNewTestExecutionFramework))), Times.Once); } + + MockLogger.Verify(l => l.DebugWarning(It.Is(msg => msg.Contains("main method") && msg.Contains("exit code"))), Times.Never); } } diff --git a/GoogleTestAdapter/Tests.Common/TestResources.cs b/GoogleTestAdapter/Tests.Common/TestResources.cs index 7242eef73..2b844d6c0 100644 --- a/GoogleTestAdapter/Tests.Common/TestResources.cs +++ b/GoogleTestAdapter/Tests.Common/TestResources.cs @@ -40,10 +40,10 @@ public static class TestResources public const string Tests_DebugX64 = SampleTestsBuildDir + @"Debug-x64\Tests_gta.exe"; public const string Tests_ReleaseX64 = SampleTestsBuildDir + @"Release-x64\Tests_gta.exe"; public const string Tests_ReleaseX64_Output = TestdataDir + @"Tests_gta_exe_output.txt"; - public const int NrOfTests = 107; + public const int NrOfTests = 108; public const int NrOfPassingTests = 53; - public const int NrOfFailingTests = 54; - public const int NrOfGtest170CompatibleTests = 103; + public const int NrOfFailingTests = 55; + public const int NrOfGtest170CompatibleTests = 104; public static readonly string LoadTests_ReleaseX86 = Path.Combine(SampleTestsBuildDir, @"Release\LoadTests_gta.exe"); public const string LoadTests_Generated = TestdataDir + @"LoadTests\GeneratedLoadTests_gta.exe"; diff --git a/GoogleTestAdapter/Tests.Common/Tests/ProcessExecutorTests.cs b/GoogleTestAdapter/Tests.Common/Tests/ProcessExecutorTests.cs index 375017f25..2334a55a9 100644 --- a/GoogleTestAdapter/Tests.Common/Tests/ProcessExecutorTests.cs +++ b/GoogleTestAdapter/Tests.Common/Tests/ProcessExecutorTests.cs @@ -46,7 +46,7 @@ protected void Test_ExecuteProcessBlocking_SampleTests() exitCode.Should().Be(1); output.Should().Contain(s => s.Contains("TestMath.AddPasses")); - output.Should().HaveCount(612); + output.Should().HaveCount(632); } protected void Test_WithSimpleCommand_ReturnsOutputOfCommand() diff --git a/GoogleTestAdapter/VsPackage.Tests.Generated/GoldenFiles/ConsoleDllTests__List_TestsOf_SampleTests.txt b/GoogleTestAdapter/VsPackage.Tests.Generated/GoldenFiles/ConsoleDllTests__List_TestsOf_SampleTests.txt index fea979489..8d86fe627 100644 --- a/GoogleTestAdapter/VsPackage.Tests.Generated/GoldenFiles/ConsoleDllTests__List_TestsOf_SampleTests.txt +++ b/GoogleTestAdapter/VsPackage.Tests.Generated/GoldenFiles/ConsoleDllTests__List_TestsOf_SampleTests.txt @@ -30,6 +30,7 @@ OutputHandling.OneLine abcd.t bbcd.t bcd.t +MainMethodTests.StupidMethod Namespace_Named.Test Namespace_Named_Named.Test Namespace_Named_Anon.Test diff --git a/GoogleTestAdapter/VsPackage.Tests.Generated/GoldenFiles/ConsoleDllTests__List_TestsOf_SampleTests170.txt b/GoogleTestAdapter/VsPackage.Tests.Generated/GoldenFiles/ConsoleDllTests__List_TestsOf_SampleTests170.txt index 453e10c35..8724e2cc5 100644 --- a/GoogleTestAdapter/VsPackage.Tests.Generated/GoldenFiles/ConsoleDllTests__List_TestsOf_SampleTests170.txt +++ b/GoogleTestAdapter/VsPackage.Tests.Generated/GoldenFiles/ConsoleDllTests__List_TestsOf_SampleTests170.txt @@ -30,6 +30,7 @@ TheFixture.Crash TheFixture.AddPassesWithTraits TheFixture.AddPassesWithTraits2 TheFixture.AddPassesWithTraits3 +MainMethodTests.StupidMethod Namespace_Named.Test Namespace_Named_Named.Test Namespace_Named_Anon.Test diff --git a/GoogleTestAdapter/VsPackage.Tests.Generated/GoldenFiles/ConsoleDllTests__SampleTests170_SolutionProjectSettings_Coverage_Isolation.xml b/GoogleTestAdapter/VsPackage.Tests.Generated/GoldenFiles/ConsoleDllTests__SampleTests170_SolutionProjectSettings_Coverage_Isolation.xml index b10ea1866..5928a68e2 100644 --- a/GoogleTestAdapter/VsPackage.Tests.Generated/GoldenFiles/ConsoleDllTests__SampleTests170_SolutionProjectSettings_Coverage_Isolation.xml +++ b/GoogleTestAdapter/VsPackage.Tests.Generated/GoldenFiles/ConsoleDllTests__SampleTests170_SolutionProjectSettings_Coverage_Isolation.xml @@ -137,6 +137,26 @@ Expected: 1 + + + + #1 - Value of: "" +Expected: "This is really a stupid choice for a method name" +#2 - Value of: main_namespace::main(0, 0) + Actual: 0 +Expected: 1 +#3 - Value of: "" +Expected: "This is another a stupid choice for a method name" +#4 - Value of: ::main() + Actual: 0 +Expected: 1 + at #1 - mainmethodtest.cpp:7 in $(Directory)\sampletests\tests\mainmethodtest.cpp:line 7 +at #2 - mainmethodtest.cpp:23 in $(Directory)\sampletests\tests\mainmethodtest.cpp:line 23 +at #3 - mainmethodtest.cpp:16 in $(Directory)\sampletests\tests\mainmethodtest.cpp:line 16 +at #4 - mainmethodtest.cpp:24 in $(Directory)\sampletests\tests\mainmethodtest.cpp:line 24 + + + @@ -680,6 +700,9 @@ Which is: "\xE4\xF6\xFC\xDF\xC4\xD6\xDC" + + + @@ -913,7 +936,7 @@ Which is: "\xE4\xF6\xFC\xDF\xC4\xD6\xDC" - + \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.Tests.Generated/GoldenFiles/ConsoleDllTests__SampleTests_SolutionProjectSettings_Coverage_Isolation.xml b/GoogleTestAdapter/VsPackage.Tests.Generated/GoldenFiles/ConsoleDllTests__SampleTests_SolutionProjectSettings_Coverage_Isolation.xml index fc114672f..164d44c23 100644 --- a/GoogleTestAdapter/VsPackage.Tests.Generated/GoldenFiles/ConsoleDllTests__SampleTests_SolutionProjectSettings_Coverage_Isolation.xml +++ b/GoogleTestAdapter/VsPackage.Tests.Generated/GoldenFiles/ConsoleDllTests__SampleTests_SolutionProjectSettings_Coverage_Isolation.xml @@ -149,6 +149,30 @@ Test failed: Something is wrong + + + + #1 - Expected equality of these values: + "This is really a stupid choice for a method name" + "" +#2 - Expected equality of these values: + 1 + main_namespace::main(0, 0) + Which is: 0 +#3 - Expected equality of these values: + "This is another a stupid choice for a method name" + "" +#4 - Expected equality of these values: + 1 + ::main() + Which is: 0 + at #1 - mainmethodtest.cpp:7 in $(Directory)\sampletests\tests\mainmethodtest.cpp:line 7 +at #2 - mainmethodtest.cpp:23 in $(Directory)\sampletests\tests\mainmethodtest.cpp:line 23 +at #3 - mainmethodtest.cpp:16 in $(Directory)\sampletests\tests\mainmethodtest.cpp:line 16 +at #4 - mainmethodtest.cpp:24 in $(Directory)\sampletests\tests\mainmethodtest.cpp:line 24 + + + @@ -741,6 +765,9 @@ at #2 - parameterizedtests.cpp:40 in $(Directory)\sampletests\tests\parameterize + + + @@ -974,7 +1001,7 @@ at #2 - parameterizedtests.cpp:40 in $(Directory)\sampletests\tests\parameterize - + \ No newline at end of file diff --git a/SampleTests/Tests/MainMethodTest.cpp b/SampleTests/Tests/MainMethodTest.cpp new file mode 100644 index 000000000..ef3f4d20e --- /dev/null +++ b/SampleTests/Tests/MainMethodTest.cpp @@ -0,0 +1,25 @@ +#include "gtest/gtest.h" + +namespace main_namespace +{ + int main(int argn, char** argv) + { + EXPECT_STREQ("This is really a stupid choice for a method name", ""); + return 0; + } +} + +namespace +{ + int main() + { + EXPECT_STREQ("This is another a stupid choice for a method name", ""); + return 0; + } +} + +TEST(MainMethodTests, StupidMethod) +{ + EXPECT_EQ(1, main_namespace::main(0, 0)); + EXPECT_EQ(1, ::main()); +} \ No newline at end of file diff --git a/SampleTests/Tests/Tests.vcxproj b/SampleTests/Tests/Tests.vcxproj index e013a12da..ee11257bf 100644 --- a/SampleTests/Tests/Tests.vcxproj +++ b/SampleTests/Tests/Tests.vcxproj @@ -152,6 +152,7 @@ + diff --git a/SampleTests/Tests/Tests.vcxproj.filters b/SampleTests/Tests/Tests.vcxproj.filters index 03907ded4..136f9d0af 100644 --- a/SampleTests/Tests/Tests.vcxproj.filters +++ b/SampleTests/Tests/Tests.vcxproj.filters @@ -45,6 +45,9 @@ Source Files + + Source Files + diff --git a/SampleTests/Tests_1.7.0/Tests_1.7.0.vcxproj b/SampleTests/Tests_1.7.0/Tests_1.7.0.vcxproj index 4e3b50c8d..4268d0514 100644 --- a/SampleTests/Tests_1.7.0/Tests_1.7.0.vcxproj +++ b/SampleTests/Tests_1.7.0/Tests_1.7.0.vcxproj @@ -168,6 +168,7 @@ + diff --git a/SampleTests/Tests_1.7.0/Tests_1.7.0.vcxproj.filters b/SampleTests/Tests_1.7.0/Tests_1.7.0.vcxproj.filters index 22ad6773a..4e4a87320 100644 --- a/SampleTests/Tests_1.7.0/Tests_1.7.0.vcxproj.filters +++ b/SampleTests/Tests_1.7.0/Tests_1.7.0.vcxproj.filters @@ -53,5 +53,8 @@ Source Files + + Source Files + \ No newline at end of file From 7220dd951e5f60f1d2441c72465b468768e7349e Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Thu, 28 Feb 2019 20:31:27 +0100 Subject: [PATCH 23/81] trying to fix VS2019 behavior by removing ProvideAutoLoad attribute --- .../VsPackage.Shared/GoogleTestExtensionOptionsPage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs index 324174654..8ef18780f 100644 --- a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs @@ -31,7 +31,7 @@ namespace GoogleTestAdapter.VsPackage [ProvideOptionPage(typeof(GeneralOptionsDialogPage), OptionsCategoryName, SettingsWrapper.PageGeneralName, 0, 0, true)] [ProvideOptionPage(typeof(ParallelizationOptionsDialogPage), OptionsCategoryName, SettingsWrapper.PageParallelizationName, 0, 0, true)] [ProvideOptionPage(typeof(GoogleTestOptionsDialogPage), OptionsCategoryName, SettingsWrapper.PageGoogleTestName, 0, 0, true)] - [Microsoft.VisualStudio.Shell.ProvideAutoLoad(UIContextGuids.SolutionExists)] +// [Microsoft.VisualStudio.Shell.ProvideAutoLoad(UIContextGuids.SolutionExists)] [ProvideMenuResource("Menus.ctmenu", 1)] public sealed partial class GoogleTestExtensionOptionsPage : Package, IGoogleTestExtensionOptionsPage, IAsyncLoadablePackageInitialize, IDisposable { From 2c85eee3c7c0cb9a61dc52f2e62acd8d31804ee1 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Fri, 1 Mar 2019 08:03:21 +0100 Subject: [PATCH 24/81] added PlaformToolset v142 to SampleTests projects --- SampleTests/CrashingTests/CrashingTests.vcxproj | 1 + SampleTests/DllDependentProject/DllDependentProject.vcxproj | 4 ++++ SampleTests/DllProject/DllProject.vcxproj | 4 ++++ SampleTests/LibProject/LibProject.vcxproj | 1 + SampleTests/LoadTests/LoadTests.vcxproj | 1 + SampleTests/LongRunningTests/LongRunningTests.vcxproj | 1 + SampleTests/Tests/Tests.vcxproj | 1 + SampleTests/Tests_1.7.0/Tests_1.7.0.vcxproj | 1 + 8 files changed, 14 insertions(+) diff --git a/SampleTests/CrashingTests/CrashingTests.vcxproj b/SampleTests/CrashingTests/CrashingTests.vcxproj index 6cc7f40de..769fb53ee 100644 --- a/SampleTests/CrashingTests/CrashingTests.vcxproj +++ b/SampleTests/CrashingTests/CrashingTests.vcxproj @@ -33,6 +33,7 @@ v120 v140 v141 + v142 Application diff --git a/SampleTests/DllDependentProject/DllDependentProject.vcxproj b/SampleTests/DllDependentProject/DllDependentProject.vcxproj index a986444ab..0c56c4bcf 100644 --- a/SampleTests/DllDependentProject/DllDependentProject.vcxproj +++ b/SampleTests/DllDependentProject/DllDependentProject.vcxproj @@ -36,6 +36,7 @@ v120 v140 v141 + v142 Unicode @@ -46,6 +47,7 @@ v120 v140 v141 + v142 true Unicode @@ -57,6 +59,7 @@ v120 v140 v141 + v142 Unicode @@ -67,6 +70,7 @@ v120 v140 v141 + v142 true Unicode diff --git a/SampleTests/DllProject/DllProject.vcxproj b/SampleTests/DllProject/DllProject.vcxproj index 0af1bcf6c..3cc89f9f5 100644 --- a/SampleTests/DllProject/DllProject.vcxproj +++ b/SampleTests/DllProject/DllProject.vcxproj @@ -35,6 +35,7 @@ v120 v140 v141 + v142 Unicode @@ -45,6 +46,7 @@ v120 v140 v141 + v142 true Unicode @@ -56,6 +58,7 @@ v120 v140 v141 + v142 Unicode @@ -66,6 +69,7 @@ v120 v140 v141 + v142 true Unicode diff --git a/SampleTests/LibProject/LibProject.vcxproj b/SampleTests/LibProject/LibProject.vcxproj index dc10a8684..8fa9fbd2f 100644 --- a/SampleTests/LibProject/LibProject.vcxproj +++ b/SampleTests/LibProject/LibProject.vcxproj @@ -33,6 +33,7 @@ v120 v140 v141 + v142 StaticLibrary diff --git a/SampleTests/LoadTests/LoadTests.vcxproj b/SampleTests/LoadTests/LoadTests.vcxproj index a8d3f2a93..97fe66984 100644 --- a/SampleTests/LoadTests/LoadTests.vcxproj +++ b/SampleTests/LoadTests/LoadTests.vcxproj @@ -54,6 +54,7 @@ v120 v140 v141 + v142 diff --git a/SampleTests/LongRunningTests/LongRunningTests.vcxproj b/SampleTests/LongRunningTests/LongRunningTests.vcxproj index 9bfabec8a..958b4be8c 100644 --- a/SampleTests/LongRunningTests/LongRunningTests.vcxproj +++ b/SampleTests/LongRunningTests/LongRunningTests.vcxproj @@ -53,6 +53,7 @@ v120 v140 v141 + v142 diff --git a/SampleTests/Tests/Tests.vcxproj b/SampleTests/Tests/Tests.vcxproj index e013a12da..87df9041b 100644 --- a/SampleTests/Tests/Tests.vcxproj +++ b/SampleTests/Tests/Tests.vcxproj @@ -32,6 +32,7 @@ v120 v140 v141 + v142 Application diff --git a/SampleTests/Tests_1.7.0/Tests_1.7.0.vcxproj b/SampleTests/Tests_1.7.0/Tests_1.7.0.vcxproj index 4e3b50c8d..0cdaf6687 100644 --- a/SampleTests/Tests_1.7.0/Tests_1.7.0.vcxproj +++ b/SampleTests/Tests_1.7.0/Tests_1.7.0.vcxproj @@ -33,6 +33,7 @@ v120 v140 v141 + v142 Application From 1afd2aba296e7aa44215833692f182b63d6113f3 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Fri, 1 Mar 2019 08:37:58 +0100 Subject: [PATCH 25/81] memory leak detection now also prints object dumps --- SampleTests/LeakCheckTests/LeakCheckTests.cpp | 46 +++++++++++++------ 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/SampleTests/LeakCheckTests/LeakCheckTests.cpp b/SampleTests/LeakCheckTests/LeakCheckTests.cpp index 361f1a95f..cbdabaab9 100644 --- a/SampleTests/LeakCheckTests/LeakCheckTests.cpp +++ b/SampleTests/LeakCheckTests/LeakCheckTests.cpp @@ -75,20 +75,38 @@ namespace int *returnValue ) { - // Detect when the memory leak dump is starting, and flag for special processing of leak reports. - const wchar_t szStartDumpString[] = L"Detected memory leaks!"; //CRT is hard coded to say "Detected memory leaks!\n" in the memory leak report - if (::wcsncmp(message, szStartDumpString, LENGTHOF(szStartDumpString) - 1) == 0) - { - if (is_run_by_gta) - std::cout << "GTA_EXIT_CODE_OUTPUT_BEGIN\n"; - - std::wcout << std::wstring(message) << "\n"; - - if (is_run_by_gta) - std::cout << "Note that due to some weaknesses of Google Test and the used memory leak detection technology, the leak detection results are only reliable if at least one real test is executed, and if all executed tests have passed.\n"; - - exit(1); - } + static bool reportingLeaks_ = false; + + // Detect when the memory leak dump is starting, and flag for special processing of leak reports. + const wchar_t szStartDumpString[] = L"Detected memory leaks!"; //CRT is hard coded to say "Detected memory leaks!\n" in the memory leak report + if (::wcsncmp(message, szStartDumpString, LENGTHOF(szStartDumpString) - 1) == 0) + { + if (is_run_by_gta) + std::cout << "GTA_EXIT_CODE_OUTPUT_BEGIN\n"; + + std::wcout << std::wstring(message); + + reportingLeaks_ = true; + return 0; + } + + // Detect when the memory leak dump is done, and then exit the process with an error code. + const wchar_t szDoneDumpString[] = L"Object dump complete."; //CRT is hard coded to say "Object dump complete.\n" in the memory leak report + if (::wcsncmp(message, szDoneDumpString, LENGTHOF(szDoneDumpString) - 1) == 0) + { + std::wcout << std::wstring(szDoneDumpString); + + if (is_run_by_gta) + std::cout << "\n\nNote that due to some weaknesses of Google Test and the used memory leak detection technology, the leak detection results are only reliable if at least one real test is executed, and if all executed tests have passed.\n"; + + exit(1); + } + + // decide if we want to print the message or not... + if (reportingLeaks_) + { + std::wcout << std::wstring(message); + } return 0; } From d5beb8c4431fb030e9390924ad3aabb5836b369f Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Fri, 1 Mar 2019 20:29:10 +0100 Subject: [PATCH 26/81] GTA_EXIT_CODE_SKIP can also be used if exit code != 0 --- .../TestResults/ExitCodeTestsReporterTests.cs | 2 +- ...mingStandardOutputTestResultParserTests.cs | 31 ++++++++++++ .../Core/TestResults/ExitCodeTestsReporter.cs | 48 ++++++++----------- .../TestExecutorTestsBase.cs | 14 ++++-- README.md | 2 +- 5 files changed, 63 insertions(+), 34 deletions(-) diff --git a/GoogleTestAdapter/Core.Tests/TestResults/ExitCodeTestsReporterTests.cs b/GoogleTestAdapter/Core.Tests/TestResults/ExitCodeTestsReporterTests.cs index 033f1f26b..dd6f29e27 100644 --- a/GoogleTestAdapter/Core.Tests/TestResults/ExitCodeTestsReporterTests.cs +++ b/GoogleTestAdapter/Core.Tests/TestResults/ExitCodeTestsReporterTests.cs @@ -146,7 +146,7 @@ public void ReportExitCodeTestCases_FailAndSkip_CorrectResult() MockFrameworkReporter .Verify(r => r.ReportTestResults(It.Is>( - results => CheckResult(results.Single(), "Foo", TestOutcome.Failed))), + results => CheckResult(results.Single(), "Foo", TestOutcome.Skipped))), Times.Once); } diff --git a/GoogleTestAdapter/Core.Tests/TestResults/StreamingStandardOutputTestResultParserTests.cs b/GoogleTestAdapter/Core.Tests/TestResults/StreamingStandardOutputTestResultParserTests.cs index f7f561cf6..5c2091c8f 100644 --- a/GoogleTestAdapter/Core.Tests/TestResults/StreamingStandardOutputTestResultParserTests.cs +++ b/GoogleTestAdapter/Core.Tests/TestResults/StreamingStandardOutputTestResultParserTests.cs @@ -511,6 +511,37 @@ public void GetTestResults_OutputWithTwoLinesExitCodeAndNoEnd_ExitCodeOutputIsPa parser.ExitCodeOutput.Should().BeEquivalentTo("Output 1", "Output 2"); } + [TestMethod] + [TestCategory(Unit)] + public void GetTestResults_OutputWithSkip_ExitCodeSkipIsTrue() + { + string[] consoleOutput = { + @"[==========] Running 1 tests from 1 test case.", + @"[----------] Global test environment set-up.", + @"[----------] 1 tests from TestMath", + @"[ RUN ] TestMath.AddPasses", + @"Some output produced by the exe", + @"[ OK ] TestMath.AddPasses(0 ms)", + @"[----------] 1 tests from TestMath(26 ms total)", + @"", + @"[----------] Global test environment tear-down", + @"[==========] 3 tests from 1 test case ran. (36 ms total)", + @"[ PASSED ] 1 test.", + @"", + StreamingStandardOutputTestResultParser.GtaExitCodeSkip, + StreamingStandardOutputTestResultParser.GtaExitCodeOutputBegin, + "Output 1", + "Output 2", + }; + var cases = GetTestCases(); + + var parser = new StreamingStandardOutputTestResultParser(cases, MockLogger.Object, MockFrameworkReporter.Object); + consoleOutput.ToList().ForEach(parser.ReportLine); + parser.Flush(); + + parser.ExitCodeSkip.Should().BeTrue(); + } + [TestMethod] [TestCategory(Unit)] public void GetTestResults_OutputWithPrefixingTest_BothTestsAreFound() diff --git a/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs b/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs index ca34f8ccb..e356826a7 100644 --- a/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs +++ b/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs @@ -68,50 +68,40 @@ private TestResult ReportExitCodeTestResult(ExecutableResult executableResult) var exitCodeTestCase = CreateExitCodeTestCase(_settings, executableResult.Executable); _reporter.ReportTestsStarted(exitCodeTestCase.Yield()); - TestResult testResult; - if (executableResult.ExitCode == 0) - { - testResult = CreatePassingExitCodeTestResult(exitCodeTestCase, executableResult); - if (executableResult.ExitCodeSkip) - { - testResult.Outcome = TestOutcome.Skipped; - } - } - else - { - testResult = CreateFailingExitCodeTestResult(exitCodeTestCase, executableResult, executableResult.ExitCode); - } + var testResult = CreateExitCodeTestResult(exitCodeTestCase, executableResult); _reporter.ReportTestResults(testResult.Yield()); return testResult; } - private TestResult CreatePassingExitCodeTestResult(TestCase exitCodeTestCase, - ExecutableResult executableResult) + private TestResult CreateExitCodeTestResult(TestCase exitCodeTestCase, ExecutableResult executableResult) { - var testResult = - StreamingStandardOutputTestResultParser.CreatePassedTestResult(exitCodeTestCase, - TimeSpan.Zero); - if (executableResult.ExitCodeOutput.Any()) + string message = ""; + + if (executableResult.ExitCode != 0) { - testResult.ErrorMessage = string.Join(Environment.NewLine, executableResult.ExitCodeOutput); + message += $"Exit code: {executableResult.ExitCode}"; } - return testResult; - } - - private TestResult CreateFailingExitCodeTestResult(TestCase exitCodeTestCase, ExecutableResult executableResult, - int exitCode) - { - string message = $"Exit code: {exitCode}"; if (executableResult.ExitCodeOutput.Any()) { - message += $"{Environment.NewLine}{Environment.NewLine}"; + if (!string.IsNullOrWhiteSpace(message)) + { + message += $"{Environment.NewLine}{Environment.NewLine}"; + } message += string.Join(Environment.NewLine, executableResult.ExitCodeOutput); } - return StreamingStandardOutputTestResultParser + var result = StreamingStandardOutputTestResultParser .CreateFailedTestResult(exitCodeTestCase, TimeSpan.Zero, message, ""); + + result.Outcome = executableResult.ExitCodeSkip + ? TestOutcome.Skipped + : executableResult.ExitCode == 0 + ? TestOutcome.Passed + : TestOutcome.Failed; + + return result; } } } \ No newline at end of file diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs index 0f8518b24..3d945182e 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Configuration; using System.IO; using System.Linq; using FluentAssertions; @@ -346,7 +348,7 @@ public virtual void MemoryLeakTests_FailingWithLeaks_CorrectResult() public virtual void MemoryLeakTests_PassingWithoutLeaks_CorrectResult() { RunMemoryLeakTest(TestResources.LeakCheckTests_DebugX86, "memory_leaks.passing", VsTestOutcome.Passed, VsTestOutcome.Passed, - msg => msg == null); + msg => msg == ""); } [TestMethod] @@ -356,7 +358,7 @@ public virtual void MemoryLeakTests_FailingWithoutLeaks_CorrectResult() try { RunMemoryLeakTest(TestResources.LeakCheckTests_DebugX86, "memory_leaks.failing", VsTestOutcome.Failed, VsTestOutcome.Passed, - msg => msg == null); + msg => msg == ""); } catch (MockException) { @@ -389,6 +391,12 @@ private void RunMemoryLeakTest(string executable, string testCaseName, VsTestOut var executor = new TestExecutor(TestEnvironment.Logger, TestEnvironment.Options, MockDebuggerAttacher.Object); executor.RunTests(testCase.Yield().Select(tc => tc.ToVsTestCase()), MockRunContext.Object, MockFrameworkHandle.Object); + var invocations = new List(); + foreach (var invocation in MockFrameworkHandle.Invocations) + { + invocations.Add(invocation); + } + MockFrameworkHandle.Verify(h => h.RecordResult(It.Is(result => result.TestCase.FullyQualifiedName == testCaseName && result.Outcome == testOutcome @@ -433,7 +441,7 @@ private void RunExitCodeTest(string testCaseName, VsTestOutcome outcome) && !result.ErrorMessage.Contains(StreamingStandardOutputTestResultParser.GtaExitCodeOutputBegin) && !result.ErrorMessage.Contains(StreamingStandardOutputTestResultParser.GtaExitCodeOutputEnd) && !result.ErrorMessage.Contains("Some more output") - : (Func) (result => result.ErrorMessage == null || result.ErrorMessage.Contains("The result code output")); + : (Func) (result => string.IsNullOrEmpty(result.ErrorMessage) || result.ErrorMessage.Contains("The result code output")); MockFrameworkHandle.Verify(h => h.RecordResult(It.Is(result => result.TestCase.FullyQualifiedName == finalName && result.Outcome == outcome diff --git a/README.md b/README.md index ababc6e9c..780481416 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ If option *Exit code test case* is non-empty, an additional test case will be ge To increase usefulness of the additional tests, a couple of tokens can used as part of a test executable's output; if GTA sees theses tokens, it will act accordingly: * `GTA_EXIT_CODE_OUTPUT_BEGIN`: This token will make GTA capture the following output and add it to the additional test case as error message. * `GTA_EXIT_CODE_OUTPUT_END`: This token will stop GTA from adding the following output to the error message. If it is not provided, GTA will capture the complete remaining output as error message of the additional test. -* `GTA_EXIT_CODE_SKIP`: This token will make the additional test case have outcome *Skipped* if the test executable returns with exit code 0. This can e.g. be useful if a particular check is only perfomed in Debug mode. +* `GTA_EXIT_CODE_SKIP`: This token will make the additional test case have outcome *Skipped*. This can e.g. be useful if a particular check is only perfomed in Debug mode, or to provide a general warning that something has gone wrong. Note that when running tests in parallel, a test executable might be run more than once by GTA. In this case, the exit codes and respective outputs of a test exectutable are aggregated as follows: * The exit code reported will be the one with the greatest absolute value; e.g., if the exit codes have been -2, 0, and 1, the reported exit code will be -2. From 70585fd71b470e39d6fb4bc8d249cb9204310c0f Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sat, 2 Mar 2019 17:53:22 +0100 Subject: [PATCH 27/81] improved output of memory leak example --- ...cutorSequentialTests_FrameworkDebugging.cs | 49 ++-- .../TestExecutorTestsBase.cs | 6 +- SampleTests/LeakCheckTests/LeakCheckTests.cpp | 242 +++++++++--------- 3 files changed, 159 insertions(+), 138 deletions(-) diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs index feb2080a4..98f6d6ca8 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs @@ -5,6 +5,8 @@ using GoogleTestAdapter.Tests.Common; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; +using VsTestOutcome = Microsoft.VisualStudio.TestPlatform.ObjectModel.TestOutcome; +using static GoogleTestAdapter.Tests.Common.TestMetadata.TestCategories; namespace GoogleTestAdapter.TestAdapter { @@ -53,7 +55,7 @@ protected override void SetUpMockFrameworkHandle() } [TestMethod] - [TestCategory(TestMetadata.TestCategories.Integration)] + [TestCategory(Integration)] public override void RunTests_CrashingX64Tests_CorrectTestResults() { // test crashes, no info available if debugged via framework @@ -61,7 +63,7 @@ public override void RunTests_CrashingX64Tests_CorrectTestResults() } [TestMethod] - [TestCategory(TestMetadata.TestCategories.Integration)] + [TestCategory(Integration)] public override void RunTests_CrashingX86Tests_CorrectTestResults() { // test crashes, no info available if debugged via framework @@ -69,7 +71,7 @@ public override void RunTests_CrashingX86Tests_CorrectTestResults() } [TestMethod] - [TestCategory(TestMetadata.TestCategories.Integration)] + [TestCategory(Integration)] public override void RunTests_HardCrashingX86Tests_CorrectTestResults() { TestExecutor executor = new TestExecutor(TestEnvironment.Logger, TestEnvironment.Options, MockDebuggerAttacher.Object); @@ -82,28 +84,28 @@ public override void RunTests_HardCrashingX86Tests_CorrectTestResults() #region Method stubs for code coverage [TestMethod] - [TestCategory(TestMetadata.TestCategories.Integration)] + [TestCategory(Integration)] public override void RunTests_ExternallyLinkedX64_CorrectTestResults() { base.RunTests_ExternallyLinkedX64_CorrectTestResults(); } [TestMethod] - [TestCategory(TestMetadata.TestCategories.Integration)] + [TestCategory(Integration)] public override void RunTests_ExternallyLinkedX86TestsInDebugMode_CorrectTestResults() { base.RunTests_ExternallyLinkedX86TestsInDebugMode_CorrectTestResults(); } [TestMethod] - [TestCategory(TestMetadata.TestCategories.Integration)] + [TestCategory(Integration)] public override void RunTests_ExternallyLinkedX86Tests_CorrectTestResults() { base.RunTests_ExternallyLinkedX86Tests_CorrectTestResults(); } [TestMethod] - [TestCategory(TestMetadata.TestCategories.Integration)] + [TestCategory(Integration)] public override void RunTests_StaticallyLinkedX64Tests_CorrectTestResults() { base.RunTests_StaticallyLinkedX64Tests_CorrectTestResults(); @@ -116,77 +118,77 @@ public override void RunTests_StaticallyLinkedX64Tests_OutputIsPrintedAtMostOnce } [TestMethod] - [TestCategory(TestMetadata.TestCategories.Integration)] + [TestCategory(Integration)] public override void RunTests_StaticallyLinkedX86Tests_CorrectTestResults() { base.RunTests_StaticallyLinkedX86Tests_CorrectTestResults(); } [TestMethod] - [TestCategory(TestMetadata.TestCategories.Integration)] + [TestCategory(Integration)] public override void RunTests_TestDirectoryViaUserParams_IsPassedViaCommandLineArg() { base.RunTests_TestDirectoryViaUserParams_IsPassedViaCommandLineArg(); } [TestMethod] - [TestCategory(TestMetadata.TestCategories.Integration)] + [TestCategory(Integration)] public override void RunTests_WithNonexistingSetupBatch_LogsError() { base.RunTests_WithNonexistingSetupBatch_LogsError(); } [TestMethod] - [TestCategory(TestMetadata.TestCategories.Integration)] + [TestCategory(Integration)] public override void RunTests_WithPathExtension_ExecutionOk() { base.RunTests_WithPathExtension_ExecutionOk(); } [TestMethod] - [TestCategory(TestMetadata.TestCategories.Integration)] + [TestCategory(Integration)] public override void RunTests_WithSetupAndTeardownBatchesWhereSetupFails_LogsWarning() { base.RunTests_WithSetupAndTeardownBatchesWhereSetupFails_LogsWarning(); } [TestMethod] - [TestCategory(TestMetadata.TestCategories.Integration)] + [TestCategory(Integration)] public override void RunTests_WithSetupAndTeardownBatchesWhereTeardownFails_LogsWarning() { base.RunTests_WithSetupAndTeardownBatchesWhereTeardownFails_LogsWarning(); } [TestMethod] - [TestCategory(TestMetadata.TestCategories.Integration)] + [TestCategory(Integration)] public override void RunTests_WithoutBatches_NoLogging() { base.RunTests_WithoutBatches_NoLogging(); } [TestMethod] - [TestCategory(TestMetadata.TestCategories.Integration)] + [TestCategory(Integration)] public override void RunTests_WithoutPathExtension_ExecutionFails() { base.RunTests_WithoutPathExtension_ExecutionFails(); } [TestMethod] - [TestCategory(TestMetadata.TestCategories.Integration)] + [TestCategory(Integration)] public override void RunTests_WorkingDir_IsSetCorrectly() { base.RunTests_WorkingDir_IsSetCorrectly(); } [TestMethod] - [TestCategory(TestMetadata.TestCategories.Integration)] + [TestCategory(Integration)] public override void RunTests_CancelingExecutorAndKillProcesses_StopsTestExecutionFaster() { base.RunTests_CancelingExecutorAndKillProcesses_StopsTestExecutionFaster(); } [TestMethod] - [TestCategory(TestMetadata.TestCategories.Integration)] + [TestCategory(Integration)] public override void RunTests_CancelingExecutor_StopsTestExecution() { base.RunTests_CancelingExecutor_StopsTestExecution(); @@ -205,9 +207,14 @@ public override void RunTests_ExitCodeTest_FailingTestResultIsProduced() } [TestMethod] + [TestCategory(Integration)] public override void MemoryLeakTests_FailingWithLeaks_CorrectResult() { - base.MemoryLeakTests_FailingWithLeaks_CorrectResult(); + bool outputAvailable = MockOptions.Object.UseNewTestExecutionFramework || + !MockRunContext.Object.IsBeingDebugged; + RunMemoryLeakTest(TestResources.LeakCheckTests_DebugX86, "memory_leaks.failing_and_leaking", VsTestOutcome.Failed, VsTestOutcome.Failed, + msg => msg.Contains("Exit code: 1") + && (!outputAvailable || msg.Contains("Detected memory leaks!"))); } [TestMethod] @@ -223,9 +230,11 @@ public override void MemoryLeakTests_PassingWithoutLeaksRelease_CorrectResult() } [TestMethod] + [TestCategory(Integration)] public override void MemoryLeakTests_PassingWithoutLeaks_CorrectResult() { - base.MemoryLeakTests_PassingWithoutLeaks_CorrectResult(); + RunMemoryLeakTest(TestResources.LeakCheckTests_DebugX86, "memory_leaks.passing", VsTestOutcome.Passed, VsTestOutcome.Passed, + msg => msg == ""); } [TestMethod] diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs index 3d945182e..ab48ffec5 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs @@ -338,7 +338,7 @@ public virtual void MemoryLeakTests_FailingWithLeaks_CorrectResult() { bool outputAvailable = MockOptions.Object.UseNewTestExecutionFramework || !MockRunContext.Object.IsBeingDebugged; - RunMemoryLeakTest(TestResources.LeakCheckTests_DebugX86, "memory_leaks.failing_and_leaking", VsTestOutcome.Failed, VsTestOutcome.Failed, + RunMemoryLeakTest(TestResources.LeakCheckTests_DebugX86, "memory_leaks.failing_and_leaking", VsTestOutcome.Failed, VsTestOutcome.Skipped, msg => msg.Contains("Exit code: 1") && (!outputAvailable || msg.Contains("Detected memory leaks!"))); } @@ -348,7 +348,7 @@ public virtual void MemoryLeakTests_FailingWithLeaks_CorrectResult() public virtual void MemoryLeakTests_PassingWithoutLeaks_CorrectResult() { RunMemoryLeakTest(TestResources.LeakCheckTests_DebugX86, "memory_leaks.passing", VsTestOutcome.Passed, VsTestOutcome.Passed, - msg => msg == ""); + msg => msg.Contains("No memory leaks have been found.")); } [TestMethod] @@ -378,7 +378,7 @@ public virtual void MemoryLeakTests_PassingWithoutLeaksRelease_CorrectResult() msg => !outputAvailable || msg.Contains("Memory leak detection is only performed if compiled with Debug configuration.")); } - private void RunMemoryLeakTest(string executable, string testCaseName, VsTestOutcome testOutcome, VsTestOutcome leakCheckOutcome, Func errorMessagePredicate) + protected void RunMemoryLeakTest(string executable, string testCaseName, VsTestOutcome testOutcome, VsTestOutcome leakCheckOutcome, Func errorMessagePredicate) { string exitCodeTestName = "MemoryLeakTest"; MockOptions.Setup(o => o.ExitCodeTestCase).Returns(exitCodeTestName); diff --git a/SampleTests/LeakCheckTests/LeakCheckTests.cpp b/SampleTests/LeakCheckTests/LeakCheckTests.cpp index cbdabaab9..74c12daf2 100644 --- a/SampleTests/LeakCheckTests/LeakCheckTests.cpp +++ b/SampleTests/LeakCheckTests/LeakCheckTests.cpp @@ -3,160 +3,172 @@ #include #include +bool is_run_by_gta = false; +int result_of_run_all_tests = 0; + // construct new singleton instance on first allocation, to perform memory leak reporting on destruction // construction is performed in overridden 'new' operator (see Common\stdafx.cpp) to ensure its initialized // before first allocation namespace gsi { - namespace diag - { - class EnableLeakCheck - { - public: - static void Initialize() - { - static EnableLeakCheck leakReporter; - } - private: - EnableLeakCheck() {} - ~EnableLeakCheck() - { - _CrtDumpMemoryLeaks(); - } - }; - } + namespace diag + { + class EnableLeakCheck + { + public: + static void Initialize() + { + static EnableLeakCheck leakReporter; + } + private: + EnableLeakCheck() {} + ~EnableLeakCheck() + { + _CrtDumpMemoryLeaks(); + +#ifdef _DEBUG + // exit point 1 - reached in Debug mode if no memory leaks have been found + std::cout << "No memory leaks have been found."; +#endif // _DEBUG + } + }; + } } void InitializeLeakCheck_() { - gsi::diag::EnableLeakCheck::Initialize(); + gsi::diag::EnableLeakCheck::Initialize(); } #undef new void* operator new(size_t size) //throw( std::bad_alloc ) { - InitializeLeakCheck_(); - return malloc(size); + InitializeLeakCheck_(); + return malloc(size); } void* operator new[](size_t const size) { - InitializeLeakCheck_(); - return operator new(size); + InitializeLeakCheck_(); + return operator new(size); } -bool is_run_by_gta = false; - - namespace { - template inline size_t lengthof(T const (&array)[N]) { return N; } - template struct lengthof_sizer - { - unsigned char count[N]; - }; - template< class T, int N > inline lengthof_sizer lengthof_get_sizer(T const (&array)[N]) { return lengthof_sizer(); } + template inline size_t lengthof(T const (&array)[N]) { return N; } + template struct lengthof_sizer + { + unsigned char count[N]; + }; + template< class T, int N > inline lengthof_sizer lengthof_get_sizer(T const (&array)[N]) { return lengthof_sizer(); } #define LENGTHOF( a ) sizeof( lengthof_get_sizer( a ).count ) - class ShutdownReportHook - { - public: - static void RegisterMemoryLeakAssertOnExit() - { - _CrtSetReportHookW2(_CRT_RPTHOOK_INSTALL, &RunHook_); - } - private: - static int RunHook_ - ( - int reportType, - wchar_t *message, - int *returnValue - ) - { - static bool reportingLeaks_ = false; - - // Detect when the memory leak dump is starting, and flag for special processing of leak reports. - const wchar_t szStartDumpString[] = L"Detected memory leaks!"; //CRT is hard coded to say "Detected memory leaks!\n" in the memory leak report - if (::wcsncmp(message, szStartDumpString, LENGTHOF(szStartDumpString) - 1) == 0) - { - if (is_run_by_gta) - std::cout << "GTA_EXIT_CODE_OUTPUT_BEGIN\n"; - - std::wcout << std::wstring(message); - - reportingLeaks_ = true; - return 0; - } - - // Detect when the memory leak dump is done, and then exit the process with an error code. - const wchar_t szDoneDumpString[] = L"Object dump complete."; //CRT is hard coded to say "Object dump complete.\n" in the memory leak report - if (::wcsncmp(message, szDoneDumpString, LENGTHOF(szDoneDumpString) - 1) == 0) - { - std::wcout << std::wstring(szDoneDumpString); - - if (is_run_by_gta) - std::cout << "\n\nNote that due to some weaknesses of Google Test and the used memory leak detection technology, the leak detection results are only reliable if at least one real test is executed, and if all executed tests have passed.\n"; - - exit(1); - } - - // decide if we want to print the message or not... - if (reportingLeaks_) - { - std::wcout << std::wstring(message); - } - - return 0; - } - }; + class ShutdownReportHook + { + public: + static void RegisterMemoryLeakAssertOnExit() + { + _CrtSetReportHookW2(_CRT_RPTHOOK_INSTALL, &RunHook_); + } + private: + static int RunHook_ + ( + int reportType, + wchar_t *message, + int *returnValue + ) + { + static bool reportingLeaks_ = false; + + // Detect when the memory leak dump is starting, and flag for special processing of leak reports. + const wchar_t szStartDumpString[] = L"Detected memory leaks!"; //CRT is hard coded to say "Detected memory leaks!\n" in the memory leak report + if (::wcsncmp(message, szStartDumpString, LENGTHOF(szStartDumpString) - 1) == 0) + { + reportingLeaks_ = true; + std::wcout << std::wstring(message); + + // TODO remove if gtest "memory leaks" have been fixed + if (result_of_run_all_tests != 0) + { + if (is_run_by_gta) + std::cout << "GTA_EXIT_CODE_SKIP\n"; + + std::cout << "\nNote that due to some weaknesses of Google Test and the used memory leak detection technology, the leak detection results are only reliable if at least one real test is executed, and if all executed tests have passed.\n\n"; + } + + return 0; + } + + // Detect when the memory leak dump is done, and then exit the process with an error code. + const wchar_t szDoneDumpString[] = L"Object dump complete."; //CRT is hard coded to say "Object dump complete.\n" in the memory leak report + if (::wcsncmp(message, szDoneDumpString, LENGTHOF(szDoneDumpString) - 1) == 0) + { + std::wcout << std::wstring(szDoneDumpString); + + // exit point 2 - reached in case of memory leaks (and at the end of the leak check output) + exit(1); + } + + // decide if we want to print the message or not... + if (reportingLeaks_) + { + std::wcout << std::wstring(message); + } + + return 0; + } + }; } struct InitCleanupOnExit { - InitCleanupOnExit() - { - std::atexit(&CleanupOnExit_); // Cleanup event sink on program shutdown. - } + InitCleanupOnExit() + { + std::atexit(&CleanupOnExit_); // Cleanup event sink on program shutdown. + } private: - static void CleanupOnExit_() - { - // Memory leaks reports happen on shutdown after this point, so force them to go out via stderr - // so any parent process will see it as an error. - ShutdownReportHook::RegisterMemoryLeakAssertOnExit(); - } + static void CleanupOnExit_() + { + // Memory leaks reports happen on shutdown after this point, so force them to go out via stderr + // so any parent process will see it as an error. + ShutdownReportHook::RegisterMemoryLeakAssertOnExit(); + } } gInitCleanupOnExit; int main(int argc, char** argv) { - std::string prefix("-is_run_by_gta"); - for (int i = 0; i < argc; i++) - { - if (strncmp(argv[i], prefix.c_str(), strlen(prefix.c_str())) == 0) - { - is_run_by_gta = true; - break; - } - } - - testing::InitGoogleTest(&argc, argv); - int returnValue = RUN_ALL_TESTS(); - -#ifndef _DEBUG - if (is_run_by_gta) - { - std::cout << "GTA_EXIT_CODE_SKIP\n"; - std::cout << "GTA_EXIT_CODE_OUTPUT_BEGIN\n"; - std::cout << "Memory leak detection is only performed if compiled with Debug configuration.\n"; - } + std::string prefix("-is_run_by_gta"); + for (int i = 0; i < argc; i++) + { + if (strncmp(argv[i], prefix.c_str(), strlen(prefix.c_str())) == 0) + { + is_run_by_gta = true; + break; + } + } + + testing::InitGoogleTest(&argc, argv); + result_of_run_all_tests = RUN_ALL_TESTS(); + + if (is_run_by_gta) + std::cout << "GTA_EXIT_CODE_OUTPUT_BEGIN\n"; + + #ifndef _DEBUG + if (is_run_by_gta) + { + std::cout << "GTA_EXIT_CODE_SKIP\n"; + std::cout << "Memory leak detection is only performed if compiled with Debug configuration.\n"; + } #endif - // memory leak detection will do exit(1) if memory leaks are found - // thus, return 0 if run by gta since otherwise, a returnValue != 0 would result in the memory leak test being flagged as failed - return is_run_by_gta ? 0 : returnValue; + // exit point 3 - reached if not in Debug mode + // memory leak detection will do exit(1) if memory leaks are found + // thus, return 0 if run by gta since otherwise, a returnValue != 0 would result in the memory leak test being flagged as failed + return is_run_by_gta ? 0 : result_of_run_all_tests; } \ No newline at end of file From 33c0073b939b7c1b6098fdc34e9a260c5095161c Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sun, 3 Mar 2019 09:11:30 +0100 Subject: [PATCH 28/81] =?UTF-8?q?refactored=20leak=20detection,=20improved?= =?UTF-8?q?=20docum=C3=A9ntation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 39 ++-- SampleTests/LeakCheckTests/LeakCheckTests.cpp | 174 ------------------ .../LeakCheckTests/LeakCheckTests.vcxproj | 8 +- .../LeakCheckTests.vcxproj.filters | 14 +- .../LeakCheckTests/gta_leak_detection.cpp | 171 +++++++++++++++++ .../LeakCheckTests/gta_leak_detection.h | 6 + .../{test_leak.cpp => leaking_tests.cpp} | 2 +- SampleTests/LeakCheckTests/main.cpp | 8 + 8 files changed, 227 insertions(+), 195 deletions(-) delete mode 100644 SampleTests/LeakCheckTests/LeakCheckTests.cpp create mode 100644 SampleTests/LeakCheckTests/gta_leak_detection.cpp create mode 100644 SampleTests/LeakCheckTests/gta_leak_detection.h rename SampleTests/LeakCheckTests/{test_leak.cpp => leaking_tests.cpp} (99%) create mode 100644 SampleTests/LeakCheckTests/main.cpp diff --git a/README.md b/README.md index 780481416..bcd1a7206 100644 --- a/README.md +++ b/README.md @@ -108,23 +108,32 @@ More precisely, traits are assigned to tests in three phases: Note that traits are assigned in an additive manner within each phase, and in an overriding manner between phases. For instance, if a test is assigned the traits *(Author,Foo)* and *(Author,Bar)* in phase 1, the test will have both traits. If the test is also assigned the trait *(Author,Baz)* in phases 2 or 3, it will only have that trait. See [test code](https://github.com/csoltenborn/GoogleTestAdapter/blob/master/GoogleTestAdapter/Core.Tests/AbstractGoogleTestDiscovererTraitTests.cs) for examples. #### Evaluating the test executable's exit code -If option *Exit code test case* is non-empty, an additional test case will be generated per text executable, and that test case will pass if and only if the test executable's exit code is 0. This allows to reflect some additional result as a test case; for instance, the test executable might be built such that it performs memory leak detection at shutdown; the result of that check can then be seen within VS as the result of the according additional test. +If option *Exit code test case* is non-empty, an additional test case will be generated per text executable (referred to as *exit code test* in the following), and that exit code test will pass if the test executable's exit code is 0. This allows to reflect some additional result as a test case; for instance, the test executable might be built such that it performs memory leak detection at shutdown (see below for [example](#evaluating_exit_code_leak_example)); the result of that check can then be seen within VS as the result of the according additional test. + +A couple of tokens can used as part of a test executable's output; if GTA sees theses tokens, it will act accordingly: +* `GTA_EXIT_CODE_OUTPUT_BEGIN`: This token will make GTA capture the following output and add it to the exit code test as error message. +* `GTA_EXIT_CODE_OUTPUT_END`: This token will stop GTA from adding the following output to the error message. If it is not provided, GTA will capture the complete remaining output as error message of the exit code test. +* `GTA_EXIT_CODE_SKIP`: This token will make the exit code test have outcome *Skipped*. This can e.g. be useful if a particular check is only perfomed in Debug mode, or to provide a general warning that something has gone wrong without making the exit code test fail. + +Note that a test executable might be run more than once by GTA (e.g., if tests are run in parallel, or if the selection of tests to be run results in command lines too long for a single test run). In this case, the exit codes and respective outputs of a test exectutable are aggregated as follows: +* The exit code test will be reported as + * skipped if all runs of that executable have been reported as skipped, + * failed if at least one test run has been reported as failed, and + * passed otherwise. +* The exit code reported will be the one with the greatest absolute value; e.g., if the exit codes have been -2, 0, and 1, the reported exit code will be -2. +* Captured outputs will all go into the single exit code test's error message. -To increase usefulness of the additional tests, a couple of tokens can used as part of a test executable's output; if GTA sees theses tokens, it will act accordingly: -* `GTA_EXIT_CODE_OUTPUT_BEGIN`: This token will make GTA capture the following output and add it to the additional test case as error message. -* `GTA_EXIT_CODE_OUTPUT_END`: This token will stop GTA from adding the following output to the error message. If it is not provided, GTA will capture the complete remaining output as error message of the additional test. -* `GTA_EXIT_CODE_SKIP`: This token will make the additional test case have outcome *Skipped*. This can e.g. be useful if a particular check is only perfomed in Debug mode, or to provide a general warning that something has gone wrong. +##### Example usage: Memory leak detection + +An example usage of the *Exit code test case* can be found as part of the SampleTests solution: [Project *MemoryLeakTests*](https://github.com/csoltenborn/GoogleTestAdapter/tree/master/SampleTests/MemoryLeakTests) makes use of MS' memory leak detection facilities and reports the results to VS via an exit code test. The approach can easily be re-used for other Google Test projects: +* add files `gta_leak_detection.h` and `gta_leak_detection.cpp` to the project +* in the project's `main` method, return the result of `gta_leak_detection::PerformLeakDetection(argc, argv, RUN_ALL_TESTS())` (instead of the result of `RUN_ALL_TESTS()`) +* set the following GTA options (probably through the settings file): + * `MemoryLeakTest` (enables evaluation of the executable's exit code; feel free to choose another name) + * `-is_run_by_gta` (makes sure the test executable is aware of being run by GTA) + +However, note that Google Test as of V1.8.1 [uses some memory allocation](https://github.com/google/googletest/pull/1142) which is recognized by MS' leak detection mechanism as a leak (although it isn't), in particular for failing assertions. Some of these "false positives" have been fixed with the linked issue, making leak detection useful as long as all tests are green; however, and until this problem is fixed, the memory leak detection provided by GTA will result in a skipped exit code test in case `RUN_ALL_TESTS()` does not return `0`, but will report the leak in the test's error message. If you run into such problems, please report them against the [Google Test repository](https://github.com/google/googletest) if appropriate. -Note that when running tests in parallel, a test executable might be run more than once by GTA. In this case, the exit codes and respective outputs of a test exectutable are aggregated as follows: -* The exit code reported will be the one with the greatest absolute value; e.g., if the exit codes have been -2, 0, and 1, the reported exit code will be -2. -* Captured outputs will all go into the test's error message. -* The test will be reported as skipped if all runs of that executable have been reported as skipped. - -An example usage of the *Exit code test case* can be found as part of the SampleTests solution: [Project *MemoryLeakTests*](https://github.com/csoltenborn/GoogleTestAdapter/tree/master/SampleTests/MemoryLeakTests) makes use of MS' memory leak detection facilities and reports the results to VS via the described mechanism. Things to be noted: -* The mechanism is enabled for the project by means of GTA's [solution settings](https://github.com/csoltenborn/GoogleTestAdapter/blob/master/SampleTests/SampleTests.gta.runsettings). -* To make sure that the test executable behaves as a normal gtest executable when not run via GTA, a command line parameter `-is_run_by_gta` is passed to it via the *Additional test execution parameters* option (again provided via the solution settings). This allows the test executable to just return the result of gtests' `RUN_ALL_TESTS()` macro if run outside GTA, and to return the result of leak detetion otherwise (i.e., return 0 if and only if no leaks have been found). In case of the provided implementation for leak detection, this means to always return with exit code 0 in the `main()` method, since the leak detection code will actively call `exit(1)` if leaks are found. -* Since leak detection is only perfomed when the executable is compiled with Debug configuration, the main method makes use of the `GTA_EXIT_CODE_SKIP` and `GTA_EXIT_CODE_OUTPUT_BEGIN` tokens to make sure the test is reported as skipped in that setting, and to additionally produce some meaningful output. -* Finally, note that Google Test as of V1.8.1 [uses some memory allocation](https://github.com/google/googletest/pull/1142) which is recognized by MS' leak detection mechanism as a leak (although it isn't), in particular for failing assertions. Some of these "false positives" have been fixed with the linked issue, but there appear to be more. If you run into such problems, please report them against the [Google Test repository](https://github.com/google/googletest). #### Running tests from command line with `VSTest.Console.exe` diff --git a/SampleTests/LeakCheckTests/LeakCheckTests.cpp b/SampleTests/LeakCheckTests/LeakCheckTests.cpp deleted file mode 100644 index 74c12daf2..000000000 --- a/SampleTests/LeakCheckTests/LeakCheckTests.cpp +++ /dev/null @@ -1,174 +0,0 @@ -#include "gtest/gtest.h" -#include -#include -#include - -bool is_run_by_gta = false; -int result_of_run_all_tests = 0; - -// construct new singleton instance on first allocation, to perform memory leak reporting on destruction -// construction is performed in overridden 'new' operator (see Common\stdafx.cpp) to ensure its initialized -// before first allocation -namespace gsi -{ - namespace diag - { - class EnableLeakCheck - { - public: - static void Initialize() - { - static EnableLeakCheck leakReporter; - } - private: - EnableLeakCheck() {} - ~EnableLeakCheck() - { - _CrtDumpMemoryLeaks(); - -#ifdef _DEBUG - // exit point 1 - reached in Debug mode if no memory leaks have been found - std::cout << "No memory leaks have been found."; -#endif // _DEBUG - } - }; - } -} - -void InitializeLeakCheck_() -{ - gsi::diag::EnableLeakCheck::Initialize(); -} - -#undef new - -void* operator new(size_t size) //throw( std::bad_alloc ) -{ - InitializeLeakCheck_(); - return malloc(size); -} - -void* operator new[](size_t const size) -{ - InitializeLeakCheck_(); - return operator new(size); -} - - -namespace -{ - template inline size_t lengthof(T const (&array)[N]) { return N; } - template struct lengthof_sizer - { - unsigned char count[N]; - }; - template< class T, int N > inline lengthof_sizer lengthof_get_sizer(T const (&array)[N]) { return lengthof_sizer(); } -#define LENGTHOF( a ) sizeof( lengthof_get_sizer( a ).count ) - - class ShutdownReportHook - { - public: - static void RegisterMemoryLeakAssertOnExit() - { - _CrtSetReportHookW2(_CRT_RPTHOOK_INSTALL, &RunHook_); - } - private: - static int RunHook_ - ( - int reportType, - wchar_t *message, - int *returnValue - ) - { - static bool reportingLeaks_ = false; - - // Detect when the memory leak dump is starting, and flag for special processing of leak reports. - const wchar_t szStartDumpString[] = L"Detected memory leaks!"; //CRT is hard coded to say "Detected memory leaks!\n" in the memory leak report - if (::wcsncmp(message, szStartDumpString, LENGTHOF(szStartDumpString) - 1) == 0) - { - reportingLeaks_ = true; - std::wcout << std::wstring(message); - - // TODO remove if gtest "memory leaks" have been fixed - if (result_of_run_all_tests != 0) - { - if (is_run_by_gta) - std::cout << "GTA_EXIT_CODE_SKIP\n"; - - std::cout << "\nNote that due to some weaknesses of Google Test and the used memory leak detection technology, the leak detection results are only reliable if at least one real test is executed, and if all executed tests have passed.\n\n"; - } - - return 0; - } - - // Detect when the memory leak dump is done, and then exit the process with an error code. - const wchar_t szDoneDumpString[] = L"Object dump complete."; //CRT is hard coded to say "Object dump complete.\n" in the memory leak report - if (::wcsncmp(message, szDoneDumpString, LENGTHOF(szDoneDumpString) - 1) == 0) - { - std::wcout << std::wstring(szDoneDumpString); - - // exit point 2 - reached in case of memory leaks (and at the end of the leak check output) - exit(1); - } - - // decide if we want to print the message or not... - if (reportingLeaks_) - { - std::wcout << std::wstring(message); - } - - return 0; - } - }; -} - -struct InitCleanupOnExit -{ - InitCleanupOnExit() - { - std::atexit(&CleanupOnExit_); // Cleanup event sink on program shutdown. - } - -private: - - static void CleanupOnExit_() - { - // Memory leaks reports happen on shutdown after this point, so force them to go out via stderr - // so any parent process will see it as an error. - ShutdownReportHook::RegisterMemoryLeakAssertOnExit(); - } - -} gInitCleanupOnExit; - - -int main(int argc, char** argv) -{ - std::string prefix("-is_run_by_gta"); - for (int i = 0; i < argc; i++) - { - if (strncmp(argv[i], prefix.c_str(), strlen(prefix.c_str())) == 0) - { - is_run_by_gta = true; - break; - } - } - - testing::InitGoogleTest(&argc, argv); - result_of_run_all_tests = RUN_ALL_TESTS(); - - if (is_run_by_gta) - std::cout << "GTA_EXIT_CODE_OUTPUT_BEGIN\n"; - - #ifndef _DEBUG - if (is_run_by_gta) - { - std::cout << "GTA_EXIT_CODE_SKIP\n"; - std::cout << "Memory leak detection is only performed if compiled with Debug configuration.\n"; - } -#endif - - // exit point 3 - reached if not in Debug mode - // memory leak detection will do exit(1) if memory leaks are found - // thus, return 0 if run by gta since otherwise, a returnValue != 0 would result in the memory leak test being flagged as failed - return is_run_by_gta ? 0 : result_of_run_all_tests; -} \ No newline at end of file diff --git a/SampleTests/LeakCheckTests/LeakCheckTests.vcxproj b/SampleTests/LeakCheckTests/LeakCheckTests.vcxproj index 6b39db3f0..cf7bfb250 100644 --- a/SampleTests/LeakCheckTests/LeakCheckTests.vcxproj +++ b/SampleTests/LeakCheckTests/LeakCheckTests.vcxproj @@ -169,8 +169,12 @@ - - + + + + + + diff --git a/SampleTests/LeakCheckTests/LeakCheckTests.vcxproj.filters b/SampleTests/LeakCheckTests/LeakCheckTests.vcxproj.filters index e876341ff..c24abe411 100644 --- a/SampleTests/LeakCheckTests/LeakCheckTests.vcxproj.filters +++ b/SampleTests/LeakCheckTests/LeakCheckTests.vcxproj.filters @@ -15,14 +15,22 @@ - + Source Files - + Source Files - + + Source Files + + Source Files + + + Header Files + + \ No newline at end of file diff --git a/SampleTests/LeakCheckTests/gta_leak_detection.cpp b/SampleTests/LeakCheckTests/gta_leak_detection.cpp new file mode 100644 index 000000000..c965b4c5e --- /dev/null +++ b/SampleTests/LeakCheckTests/gta_leak_detection.cpp @@ -0,0 +1,171 @@ +#include +#include +#include +#include + +/* +Example code for memory leak detection with GTA. +See https://github.com/csoltenborn/GoogleTestAdapter#evaluating-the-test-executables-exit-code for usage. +*/ + +// construct new singleton instance on first allocation, to perform memory leak reporting on destruction +// construction is performed in overridden 'new' operators to ensure its initialized before first allocation +// based on code provided by https://github.com/alfredskpoon (see https://github.com/csoltenborn/GoogleTestAdapter/issues/266) +namespace gta_leak_detection +{ + bool _isRunByGta = false; + int _resultOfRunAllTests = -1; + + class EnableLeakCheck + { + public: + static void Initialize() + { + static EnableLeakCheck leakReporter; + } + private: + EnableLeakCheck() {} + ~EnableLeakCheck() // NOLINT(bugprone-exception-escape) + { + _CrtDumpMemoryLeaks(); + +#ifdef _DEBUG + // exit point 1 - reached in Debug mode if no memory leaks have been found + std::cout << "No memory leaks have been found."; + exit(0); +#endif // _DEBUG + } + }; + + + template inline size_t lengthof(T const (&array)[N]) { return N; } + template struct lengthof_sizer + { + unsigned char count[N]; + }; + template< class T, int N > inline lengthof_sizer lengthof_get_sizer(T const (&array)[N]) { return lengthof_sizer(); } +#define LENGTHOF( a ) sizeof( lengthof_get_sizer( a ).count ) + + class ShutdownReportHook + { + public: + static void RegisterMemoryLeakAssertOnExit() + { + _CrtSetReportHookW2(_CRT_RPTHOOK_INSTALL, &RunHook_); + } + private: + static int RunHook_ + ( + int reportType, + wchar_t *message, + int *returnValue + ) + { + static bool reportingLeaks_ = false; + + // Detect when the memory leak dump is starting, and flag for special processing of leak reports. + const wchar_t szStartDumpString[] = L"Detected memory leaks!"; //CRT is hard coded to say "Detected memory leaks!\n" in the memory leak report + if (::wcsncmp(message, szStartDumpString, LENGTHOF(szStartDumpString) - 1) == 0) + { + reportingLeaks_ = true; + std::wcout << std::wstring(message); + + // TODO remove if gtest "memory leaks" have been fixed + if (_resultOfRunAllTests != 0) + { + if (_isRunByGta) + std::cout << "GTA_EXIT_CODE_SKIP\n"; + + std::cout << "\nTest result is 'Skipped' due to some weaknesses of Google Test 1.8.1 and crtdbg.h: leak detection results are only reliable if at least one real test is executed, and if all executed tests have passed.\n\n"; + } + + return 0; + } + + // Detect when the memory leak dump is done, and then exit the process with an error code. + const wchar_t szDoneDumpString[] = L"Object dump complete."; //CRT is hard coded to say "Object dump complete.\n" in the memory leak report + if (::wcsncmp(message, szDoneDumpString, LENGTHOF(szDoneDumpString) - 1) == 0) + { + std::wcout << std::wstring(szDoneDumpString); + + // exit point 2 - reached in case of memory leaks (and at the end of the leak check output) + exit(1); + } + + // decide if we want to print the message or not... + if (reportingLeaks_) + { + std::wcout << std::wstring(message); + } + + return 0; + } + }; + + struct InitCleanupOnExit + { + InitCleanupOnExit() + { + std::atexit(&CleanupOnExit_); // Cleanup event sink on program shutdown. + } + + private: + + static void CleanupOnExit_() + { + // Memory leaks reports happen on shutdown after this point, so force them to go out via stderr + // so any parent process will see it as an error. + ShutdownReportHook::RegisterMemoryLeakAssertOnExit(); + } + + } gInitCleanupOnExit; + + + int PerformLeakDetection(int argc, char** argv, int resultOfRunAllTests) + { + _resultOfRunAllTests = resultOfRunAllTests; + + std::string option("-is_run_by_gta"); + for (int i = 0; i < argc; i++) + { + if (strncmp(argv[i], option.c_str(), strlen(option.c_str())) == 0) + { + _isRunByGta = true; + break; + } + } + + // use the rest of the output as message of exit code test + if (_isRunByGta) + std::cout << "GTA_EXIT_CODE_OUTPUT_BEGIN\n"; + + // exit point 3 + // memory leak detection will do exit(1) if memory leaks are found, and exit(0) if not + // this exit is thus taken only if compiled with Release configuration + // since test outcome is Skipped in this case, we can just return the result of RUN_ALL_TESTS() +#ifndef _DEBUG + if (_isRunByGta) + { + std::cout << "GTA_EXIT_CODE_SKIP\n"; + std::cout << "Memory leak detection is only performed if compiled with Debug configuration.\n"; + } +#endif + return _resultOfRunAllTests; + } +} + + +#undef new + +void* operator new(size_t size) // NOLINT(cert-dcl54-cpp, misc-new-delete-overloads, hicpp-new-delete-operators) + //throw( std::bad_alloc ) +{ + gta_leak_detection::EnableLeakCheck::Initialize(); + return malloc(size); +} + +void* operator new[](size_t const size) // NOLINT(cert-dcl54-cpp, misc-new-delete-overloads, hicpp-new-delete-operators) +{ + gta_leak_detection::EnableLeakCheck::Initialize(); + return operator new(size); +} \ No newline at end of file diff --git a/SampleTests/LeakCheckTests/gta_leak_detection.h b/SampleTests/LeakCheckTests/gta_leak_detection.h new file mode 100644 index 000000000..8daf97aab --- /dev/null +++ b/SampleTests/LeakCheckTests/gta_leak_detection.h @@ -0,0 +1,6 @@ +#pragma once + +namespace gta_leak_detection +{ + int PerformLeakDetection(int argc, char** argv, int resultOfRunAllTests); +} \ No newline at end of file diff --git a/SampleTests/LeakCheckTests/test_leak.cpp b/SampleTests/LeakCheckTests/leaking_tests.cpp similarity index 99% rename from SampleTests/LeakCheckTests/test_leak.cpp rename to SampleTests/LeakCheckTests/leaking_tests.cpp index 5b0ba8bc7..1be23be94 100644 --- a/SampleTests/LeakCheckTests/test_leak.cpp +++ b/SampleTests/LeakCheckTests/leaking_tests.cpp @@ -24,4 +24,4 @@ TEST(memory_leaks, failing_and_leaking) char * ch = new char[100]; std::cout << "Leaking 100 chars...\n"; ASSERT_TRUE(false); -} +} \ No newline at end of file diff --git a/SampleTests/LeakCheckTests/main.cpp b/SampleTests/LeakCheckTests/main.cpp new file mode 100644 index 000000000..32b252ae8 --- /dev/null +++ b/SampleTests/LeakCheckTests/main.cpp @@ -0,0 +1,8 @@ +#include "gtest/gtest.h" +#include "gta_leak_detection.h" + +int main(int argc, char** argv) +{ + testing::InitGoogleTest(&argc, argv); + return gta_leak_detection::PerformLeakDetection(argc, argv, RUN_ALL_TESTS()); +} \ No newline at end of file From 0378071d1a06cf51caf7d2d885788b394bb606fd Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sun, 3 Mar 2019 17:08:17 +0100 Subject: [PATCH 29/81] exit code tests can be run withput real tests --- .../Runners/CommandLineGeneratorTests.cs | 24 ++++++++++++++++ GoogleTestAdapter/Core/Model/TestCase.cs | 6 ++++ .../Core/Runners/CommandLineGenerator.cs | 20 +++++++++++++ .../Core/Runners/SequentialTestRunner.cs | 6 ++-- .../TestExecutorParallelTests.cs | 6 ++++ .../TestExecutorSequentialTests.cs | 6 ++++ ...cutorSequentialTests_FrameworkDebugging.cs | 6 ++++ ...ExecutorSequentialTests_NativeDebugging.cs | 6 ++++ .../TestExecutorTestsBase.cs | 28 ++++++++++++++++++- 9 files changed, 105 insertions(+), 3 deletions(-) diff --git a/GoogleTestAdapter/Core.Tests/Runners/CommandLineGeneratorTests.cs b/GoogleTestAdapter/Core.Tests/Runners/CommandLineGeneratorTests.cs index 5c4097a23..3f822ed02 100644 --- a/GoogleTestAdapter/Core.Tests/Runners/CommandLineGeneratorTests.cs +++ b/GoogleTestAdapter/Core.Tests/Runners/CommandLineGeneratorTests.cs @@ -4,6 +4,7 @@ using FluentAssertions; using GoogleTestAdapter.Helpers; using GoogleTestAdapter.Settings; +using GoogleTestAdapter.TestResults; using GoogleTestAdapter.Tests.Common; using Microsoft.VisualStudio.TestTools.UnitTesting; using static GoogleTestAdapter.Tests.Common.TestMetadata.TestCategories; @@ -42,6 +43,29 @@ public void GetCommandLines_AdditionalArguments_AreAppendedCorrectly() commandLine.Should().EndWith(" -testdirectory=\"MyTestDirectory\""); } + [TestMethod] + [TestCategory(Unit)] + public void GetCommandLines_NoTestCases_NoFilter() + { + string commandLine = new CommandLineGenerator(new List(), TestDataCreator.DummyExecutable.Length, "", "", TestEnvironment.Options).GetCommandLines().First().CommandLine; + + commandLine.Should().NotContain(GoogleTestConstants.FilterOption); + } + + [TestMethod] + [TestCategory(Unit)] + public void GetCommandLines_OnlyExitCodeTestCase_DummyFilter() + { + var exitCodeTestName = "ExitCodeTest"; + MockOptions.Setup(o => o.ExitCodeTestCase).Returns(exitCodeTestName); + + var exitCodeTestCase = + ExitCodeTestsReporter.CreateExitCodeTestCase(MockOptions.Object, TestDataCreator.DummyExecutable); + string commandLine = new CommandLineGenerator(new List {exitCodeTestCase}, TestDataCreator.DummyExecutable.Length, "", "", TestEnvironment.Options).GetCommandLines().First().CommandLine; + + commandLine.Should().Contain($"{GoogleTestConstants.FilterOption}GTA_NOT_EXISTING_DUMMY_TEST_CASE"); + } + [TestMethod] [TestCategory(Unit)] public void GetCommandLines_AllTests_ProducesCorrectArguments() diff --git a/GoogleTestAdapter/Core/Model/TestCase.cs b/GoogleTestAdapter/Core/Model/TestCase.cs index 44291bbf6..6e0a8984f 100644 --- a/GoogleTestAdapter/Core/Model/TestCase.cs +++ b/GoogleTestAdapter/Core/Model/TestCase.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; namespace GoogleTestAdapter.Model { @@ -24,6 +25,11 @@ public TestCase(string fullyQualifiedName, string source, string displayName, st LineNumber = lineNumber; } + public bool IsExitCodeTestCase + { + get { return !Properties.Any(p => p is TestCaseMetaDataProperty); } + } + public override bool Equals(object obj) { var other = obj as TestCase; diff --git a/GoogleTestAdapter/Core/Runners/CommandLineGenerator.cs b/GoogleTestAdapter/Core/Runners/CommandLineGenerator.cs index 437adba09..e8709fd9f 100644 --- a/GoogleTestAdapter/Core/Runners/CommandLineGenerator.cs +++ b/GoogleTestAdapter/Core/Runners/CommandLineGenerator.cs @@ -62,6 +62,17 @@ public IEnumerable GetCommandLines() private IEnumerable GetFinalCommandLines(string baseCommandLine) { + var exitCodeTest = + _testCasesToRun.SingleOrDefault(tc => tc.IsExitCodeTestCase); + if (exitCodeTest != null) + { + _testCasesToRun.Remove(exitCodeTest); + if (!_testCasesToRun.Any()) + { + return CreateDummyCommandLineArgs(baseCommandLine, exitCodeTest).Yield(); + } + } + var commandLines = new List(); string userParam = GetAdditionalUserParameter(); if (AllTestCasesOfExecutableAreRun()) @@ -118,6 +129,15 @@ private IEnumerable GetFinalCommandLines(string baseCommandLine) return commandLines; } + private Args CreateDummyCommandLineArgs(string baseCommandLine, TestCase exitCodeTest) + { + string commandLine = baseCommandLine; + commandLine += $"{GoogleTestConstants.FilterOption}GTA_NOT_EXISTING_DUMMY_TEST_CASE"; + commandLine += GetAdditionalUserParameter(); + + return new Args(new List { exitCodeTest }, commandLine); + } + /// /// Returns a list of test-suite-name-lists, each of which shall fit as filter on a single command-line. /// diff --git a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs index 21cc561a3..1984d6dd7 100644 --- a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs @@ -87,7 +87,7 @@ private void RunTestsFromExecutable(string executable, string workingDir, string resultXmlFile = Path.GetTempFileName(); var serializer = new TestDurationSerializer(); - var generator = new CommandLineGenerator(testCasesToRun.Where(tc => tc.Properties.Any(p => p is TestCaseMetaDataProperty)), executable.Length, userParameters, resultXmlFile, _settings); + var generator = new CommandLineGenerator(testCasesToRun, executable.Length, userParameters, resultXmlFile, _settings); foreach (CommandLineGenerator.Args arguments in generator.GetCommandLines()) { if (_canceled) @@ -157,7 +157,9 @@ private IEnumerable TryRunTests(string executable, string workingDir RunTestExecutable(executable, workingDir, arguments,isBeingDebugged, processExecutorFactory, streamingParser); var remainingTestCases = - arguments.TestCases.Except(streamingParser.TestResults.Select(tr => tr.TestCase)); + arguments.TestCases + .Except(streamingParser.TestResults.Select(tr => tr.TestCase)) + .Where(tc => !tc.IsExitCodeTestCase); var testResults = new TestResultCollector(_logger, _threadName) .CollectTestResults(remainingTestCases, executable, resultXmlFile, consoleOutput, streamingParser.CrashedTestCase); testResults = testResults.OrderBy(tr => tr.TestCase.FullyQualifiedName).ToList(); diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorParallelTests.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorParallelTests.cs index 938008d7a..9f045ad91 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorParallelTests.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorParallelTests.cs @@ -208,6 +208,12 @@ public override void MemoryLeakTests_FailingWithoutLeaks_CorrectResult() base.MemoryLeakTests_FailingWithoutLeaks_CorrectResult(); } + [TestMethod] + public override void MemoryLeakTests_ExitCodeTest_OnlyexitCodeTestResultAndNoWarnings() + { + base.MemoryLeakTests_ExitCodeTest_OnlyexitCodeTestResultAndNoWarnings(); + } + #endregion } diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests.cs index 94e145705..caae3bcec 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests.cs @@ -231,6 +231,12 @@ public override void MemoryLeakTests_FailingWithoutLeaks_CorrectResult() base.MemoryLeakTests_FailingWithoutLeaks_CorrectResult(); } + [TestMethod] + public override void MemoryLeakTests_ExitCodeTest_OnlyexitCodeTestResultAndNoWarnings() + { + base.MemoryLeakTests_ExitCodeTest_OnlyexitCodeTestResultAndNoWarnings(); + } + #endregion } diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs index 98f6d6ca8..191098098 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs @@ -243,6 +243,12 @@ public override void MemoryLeakTests_FailingWithoutLeaks_CorrectResult() base.MemoryLeakTests_FailingWithoutLeaks_CorrectResult(); } + [TestMethod] + public override void MemoryLeakTests_ExitCodeTest_OnlyexitCodeTestResultAndNoWarnings() + { + base.MemoryLeakTests_ExitCodeTest_OnlyexitCodeTestResultAndNoWarnings(); + } + #endregion } } \ No newline at end of file diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_NativeDebugging.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_NativeDebugging.cs index 89a728515..0f5bd8330 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_NativeDebugging.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_NativeDebugging.cs @@ -186,6 +186,12 @@ public override void RunTests_CancelingExecutor_StopsTestExecution() base.RunTests_CancelingExecutor_StopsTestExecution(); } + [TestMethod] + public override void MemoryLeakTests_ExitCodeTest_OnlyexitCodeTestResultAndNoWarnings() + { + base.MemoryLeakTests_ExitCodeTest_OnlyexitCodeTestResultAndNoWarnings(); + } + #endregion } } \ No newline at end of file diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs index ab48ffec5..092868d1c 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs @@ -340,7 +340,33 @@ public virtual void MemoryLeakTests_FailingWithLeaks_CorrectResult() !MockRunContext.Object.IsBeingDebugged; RunMemoryLeakTest(TestResources.LeakCheckTests_DebugX86, "memory_leaks.failing_and_leaking", VsTestOutcome.Failed, VsTestOutcome.Skipped, msg => msg.Contains("Exit code: 1") - && (!outputAvailable || msg.Contains("Detected memory leaks!"))); + && (!outputAvailable || msg.Contains("Detected memory leaks!"))); + } + + [TestMethod] + [TestCategory(Integration)] + public virtual void MemoryLeakTests_ExitCodeTest_OnlyexitCodeTestResultAndNoWarnings() + { + string exitCodeTestName = "MemoryLeakTest"; + MockOptions.Setup(o => o.ExitCodeTestCase).Returns(exitCodeTestName); + MockOptions.Setup(o => o.AdditionalTestExecutionParam).Returns("-is_run_by_gta"); + + var testCases = new GoogleTestDiscoverer(MockLogger.Object, TestEnvironment.Options, + new ProcessExecutorFactory(), new DefaultDiaResolverFactory()).GetTestsFromExecutable(TestResources.LeakCheckTests_DebugX86); + var testCase = testCases.Single(tc => tc.DisplayName.StartsWith(exitCodeTestName)); + + var executor = new TestExecutor(TestEnvironment.Logger, TestEnvironment.Options, MockDebuggerAttacher.Object); + executor.RunTests(testCase.Yield().Select(tc => tc.ToVsTestCase()), MockRunContext.Object, MockFrameworkHandle.Object); + + MockFrameworkHandle.Verify(h => h.RecordResult(It.Is(result => + result.TestCase.FullyQualifiedName.StartsWith("MemoryLeakTest") + && result.Outcome == VsTestOutcome.Passed + )), + Times.Once); + MockFrameworkHandle.Verify(h => h.RecordResult(It.IsAny()), Times.Once); + + MockLogger.Verify(l => l.DebugWarning(It.Is(msg1 => msg1.Contains("main method") && msg1.Contains("exit code"))), Times.Never); + MockLogger.Verify(l => l.DebugWarning(It.Is(msg => msg.Contains("test cases seem to not have been run"))), Times.Never); } [TestMethod] From 0aee9e0704429116004496747f02242fde6e2c2b Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Fri, 8 Mar 2019 18:52:31 +0100 Subject: [PATCH 30/81] fixed some solution warnings --- GoogleTestAdapter/Core.Tests/Core.Tests.csproj | 4 ++-- .../DiaResolver.Tests/DiaResolver.Tests.csproj | 4 ++-- .../TestAdapter.Tests/TestAdapter.Tests.csproj | 4 ++-- GoogleTestAdapter/Tests.Common/Key.snk | Bin 596 -> 0 bytes .../Tests.Common/Tests.Common.csproj | 4 ++-- .../VsPackage.GTA.Tests.Unit.csproj | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) delete mode 100644 GoogleTestAdapter/Tests.Common/Key.snk diff --git a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj index 70a6db79b..da6221a87 100644 --- a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj +++ b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj @@ -40,7 +40,8 @@ false - Key.snk + + @@ -112,7 +113,6 @@ - Designer diff --git a/GoogleTestAdapter/DiaResolver.Tests/DiaResolver.Tests.csproj b/GoogleTestAdapter/DiaResolver.Tests/DiaResolver.Tests.csproj index d560ff353..b9ba0f2b7 100644 --- a/GoogleTestAdapter/DiaResolver.Tests/DiaResolver.Tests.csproj +++ b/GoogleTestAdapter/DiaResolver.Tests/DiaResolver.Tests.csproj @@ -37,7 +37,8 @@ false - Key.snk + + @@ -102,7 +103,6 @@ - Designer diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj b/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj index fa2fcd559..0a29685ac 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj +++ b/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj @@ -37,7 +37,8 @@ false - Key.snk + + @@ -118,7 +119,6 @@ - Designer diff --git a/GoogleTestAdapter/Tests.Common/Key.snk b/GoogleTestAdapter/Tests.Common/Key.snk deleted file mode 100644 index 2d749d17256abe28fb38d2c59e46428edfc8ffb2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50096$qvpe+1@Fo7MmiI+J~!+aQqa%#*@?h^ z#eTUsP&Mk!iXEz6+WH&mhz)ssa8{X=IuKf%0Ej_+EV5RK6XBoty~{7!j5_}9{#J5M zjn;{{JV3ZaS_!Ih*GGq)-7t=s=1YAFqFTUgV!_Ik8z`@NYS0~!ux|ttIVATtO$^V+ z`}r~EA$*oW2|nLaL&!5uw-FoUR~B<+)uynGEzW3iRc4I24={Ffu~j!@w+HyS;)Uld z{mdS^cuNGuC}r8nY*<`s%HbhCHBYe(V4XBtF#&1_JXJe!N3f>COk-VUx>x^9L52t! zNT2Jthq0CptppLn-@p?Y5L2kH!qD?UTGVn)JByf*A0JD z`Im~XUdmhKS$VwdN6_R{9#$Bmu4D-}e3(-TC-~F*FInBJSFM+l6GWAt? z$|o91=KGjfalse - Key.snk + + @@ -157,7 +158,6 @@ - PreserveNewest diff --git a/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/VsPackage.GTA.Tests.Unit.csproj b/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/VsPackage.GTA.Tests.Unit.csproj index b85a50a1f..13127471c 100644 --- a/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/VsPackage.GTA.Tests.Unit.csproj +++ b/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/VsPackage.GTA.Tests.Unit.csproj @@ -38,7 +38,8 @@ false - Key.snk + + @@ -117,7 +118,6 @@ - Designer From 34eb7eb30c1ee8bcd788cafb6b1d4010aae3f6bb Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Fri, 8 Mar 2019 19:26:44 +0100 Subject: [PATCH 31/81] fixed some warnings and hints --- GoogleTestAdapter/Common/ProcessWaiter.cs | 3 +- .../DurationBasedTestsSplitterTests.cs | 32 +++++++++++-------- .../Core/GoogleTestDiscoverer.cs | 11 ++++--- GoogleTestAdapter/Core/Helpers/Utils.cs | 3 +- GoogleTestAdapter/Core/Model/TestCase.cs | 4 +-- GoogleTestAdapter/Core/Model/TestProperty.cs | 2 +- .../Core/Runners/CommandLineGenerator.cs | 8 ++--- .../Core/Runners/PreparingTestRunner.cs | 3 +- .../Core/Scheduling/TestDurationSerializer.cs | 5 +-- .../Core/TestCases/TestCaseFactory.cs | 3 +- .../Core/TestResults/ErrorMessageParser.cs | 6 ++-- .../Core/TestResults/XmlTestResultParser.cs | 5 +-- .../TestAdapter/Helpers/TestCaseFilter.cs | 3 +- .../Settings/RunSettingsContainer.cs | 2 ++ .../AbstractConsoleIntegrationTests.cs | 4 +-- .../ResultChecker/ResultChecker.cs | 3 +- .../ResultChecker/TrxResultChecker.cs | 6 ++-- .../Tests.Common/TestDataCreator.cs | 3 +- .../AsyncPackageRegistrationAttribute.cs | 3 +- .../AsyncPackage/ExtensionMethods.cs | 3 +- .../AbstractSwitchBooleanOptionCommand.cs | 11 ++----- .../GoogleTestExtensionOptionsPage.cs | 3 +- 22 files changed, 56 insertions(+), 70 deletions(-) diff --git a/GoogleTestAdapter/Common/ProcessWaiter.cs b/GoogleTestAdapter/Common/ProcessWaiter.cs index abfccefdd..46774cbf8 100644 --- a/GoogleTestAdapter/Common/ProcessWaiter.cs +++ b/GoogleTestAdapter/Common/ProcessWaiter.cs @@ -33,8 +33,7 @@ public int WaitForExit() private void OnExited(object sender, EventArgs e) { - var process = sender as Process; - if (process != null) + if (sender is Process process) { lock (this) { diff --git a/GoogleTestAdapter/Core.Tests/Scheduling/DurationBasedTestsSplitterTests.cs b/GoogleTestAdapter/Core.Tests/Scheduling/DurationBasedTestsSplitterTests.cs index 0a90a3590..65934af90 100644 --- a/GoogleTestAdapter/Core.Tests/Scheduling/DurationBasedTestsSplitterTests.cs +++ b/GoogleTestAdapter/Core.Tests/Scheduling/DurationBasedTestsSplitterTests.cs @@ -15,11 +15,13 @@ public class DurationBasedTestsSplitterTests : TestsBase [TestCategory(Unit)] public void SplitTestcases_SimpleCase_TestsAreDistributedCorrectly() { - IDictionary durations = new Dictionary(); - durations.Add(TestDataCreator.ToTestCase("ShortTest1"), 1); - durations.Add(TestDataCreator.ToTestCase("ShortTest2"), 1); - durations.Add(TestDataCreator.ToTestCase("LongTest"), 3); - durations.Add(TestDataCreator.ToTestCase("ShortTest3"), 1); + IDictionary durations = new Dictionary + { + { TestDataCreator.ToTestCase("ShortTest1"), 1 }, + { TestDataCreator.ToTestCase("ShortTest2"), 1 }, + { TestDataCreator.ToTestCase("LongTest"), 3 }, + { TestDataCreator.ToTestCase("ShortTest3"), 1 } + }; MockOptions.Setup(o => o.MaxNrOfThreads).Returns(2); @@ -36,11 +38,13 @@ public void SplitTestcases_SimpleCase_TestsAreDistributedCorrectly() [TestCategory(Unit)] public void SplitTestcases_SimpleCaseWithThreeThreads_TestsAreDistributedCorrectly() { - IDictionary durations = new Dictionary(); - durations.Add(TestDataCreator.ToTestCase("ShortTest1"), 1); - durations.Add(TestDataCreator.ToTestCase("ShortTest2"), 1); - durations.Add(TestDataCreator.ToTestCase("LongTest"), 3); - durations.Add(TestDataCreator.ToTestCase("ShortTest3"), 1); + IDictionary durations = new Dictionary + { + { TestDataCreator.ToTestCase("ShortTest1"), 1 }, + { TestDataCreator.ToTestCase("ShortTest2"), 1 }, + { TestDataCreator.ToTestCase("LongTest"), 3 }, + { TestDataCreator.ToTestCase("ShortTest3"), 1 } + }; MockOptions.Setup(o => o.MaxNrOfThreads).Returns(3); @@ -58,9 +62,11 @@ public void SplitTestcases_SimpleCaseWithThreeThreads_TestsAreDistributedCorrect [TestCategory(Unit)] public void SplitTestcases_AsymmetricCase_TestsAreDistributedCorrectly() { - IDictionary durations = new Dictionary(); - durations.Add(TestDataCreator.ToTestCase("ShortTest1"), 1); - durations.Add(TestDataCreator.ToTestCase("LongTest"), 5); + IDictionary durations = new Dictionary + { + { TestDataCreator.ToTestCase("ShortTest1"), 1 }, + { TestDataCreator.ToTestCase("LongTest"), 5 } + }; MockOptions.Setup(o => o.MaxNrOfThreads).Returns(3); diff --git a/GoogleTestAdapter/Core/GoogleTestDiscoverer.cs b/GoogleTestAdapter/Core/GoogleTestDiscoverer.cs index 22563e304..5ca35fbed 100644 --- a/GoogleTestAdapter/Core/GoogleTestDiscoverer.cs +++ b/GoogleTestAdapter/Core/GoogleTestDiscoverer.cs @@ -53,14 +53,15 @@ private static void DiscoverTests(string executable, ITestFrameworkReporter repo return; int nrOfTestCases = 0; - Action reportTestCases = tc => + void ReportTestCases(TestCase testCase) { - reporter.ReportTestsFound(tc.Yield()); - logger.DebugInfo("Added testcase " + tc.DisplayName); + reporter.ReportTestsFound(testCase.Yield()); + logger.DebugInfo("Added testcase " + testCase.DisplayName); nrOfTestCases++; - }; + } + var factory = new TestCaseFactory(executable, logger, settings, diaResolverFactory, processExecutorFactory); - factory.CreateTestCases(reportTestCases); + factory.CreateTestCases(ReportTestCases); logger.LogInfo("Found " + nrOfTestCases + " tests in executable " + executable); }); } diff --git a/GoogleTestAdapter/Core/Helpers/Utils.cs b/GoogleTestAdapter/Core/Helpers/Utils.cs index 08640b497..e49f42c3c 100644 --- a/GoogleTestAdapter/Core/Helpers/Utils.cs +++ b/GoogleTestAdapter/Core/Helpers/Utils.cs @@ -26,8 +26,7 @@ public static string GetTempDirectory() public static bool DeleteDirectory(string directory) { - string dummy; - return DeleteDirectory(directory, out dummy); + return DeleteDirectory(directory, out _); } public static bool DeleteDirectory(string directory, out string errorMessage) diff --git a/GoogleTestAdapter/Core/Model/TestCase.cs b/GoogleTestAdapter/Core/Model/TestCase.cs index 6e0a8984f..d3c16acf3 100644 --- a/GoogleTestAdapter/Core/Model/TestCase.cs +++ b/GoogleTestAdapter/Core/Model/TestCase.cs @@ -32,9 +32,7 @@ public bool IsExitCodeTestCase public override bool Equals(object obj) { - var other = obj as TestCase; - - if (other == null) + if (!(obj is TestCase other)) return false; return FullyQualifiedName == other.FullyQualifiedName && Source == other.Source; diff --git a/GoogleTestAdapter/Core/Model/TestProperty.cs b/GoogleTestAdapter/Core/Model/TestProperty.cs index f00d98cb7..4d50b142b 100644 --- a/GoogleTestAdapter/Core/Model/TestProperty.cs +++ b/GoogleTestAdapter/Core/Model/TestProperty.cs @@ -16,7 +16,7 @@ public override string ToString() public override bool Equals(object obj) { - if (ReferenceEquals(null, obj)) + if (obj is null) return false; if (ReferenceEquals(this, obj)) return true; diff --git a/GoogleTestAdapter/Core/Runners/CommandLineGenerator.cs b/GoogleTestAdapter/Core/Runners/CommandLineGenerator.cs index e8709fd9f..80078c5d2 100644 --- a/GoogleTestAdapter/Core/Runners/CommandLineGenerator.cs +++ b/GoogleTestAdapter/Core/Runners/CommandLineGenerator.cs @@ -36,14 +36,11 @@ public CommandLineGenerator(IEnumerable testCasesToRun, int lengthOfExecutableString, string userParameters, string resultXmlFile, SettingsWrapper settings) { - if (userParameters == null) - throw new ArgumentNullException(nameof(userParameters)); - _lengthOfExecutableString = lengthOfExecutableString; _testCasesToRun = testCasesToRun.ToList(); _resultXmlFile = resultXmlFile; _settings = settings; - _userParameters = userParameters; + _userParameters = userParameters ?? throw new ArgumentNullException(nameof(userParameters)); } public IEnumerable GetCommandLines() @@ -108,10 +105,9 @@ private IEnumerable GetFinalCommandLines(string baseCommandLine) string baseCommandLineForLastSuites = filterAndTestsForLastSuites.baseCommandLineWithFilter; List testCasesNotRunBySuite = GetTestCasesNotRunBySuite(suitesRunningAllTests); - List includedTestCases; int remainingLength = MaxCommandLength - baseCommandLineForLastSuites.Length - _lengthOfExecutableString - userParam.Length - 1; - string commandLine = baseCommandLineForLastSuites + JoinTestsUpToMaxLength(testCasesNotRunBySuite, remainingLength, out includedTestCases); + string commandLine = baseCommandLineForLastSuites + JoinTestsUpToMaxLength(testCasesNotRunBySuite, remainingLength, out var includedTestCases); includedTestCases.AddRange(filterAndTestsForLastSuites.testCases); // a single command line holding both suite- and single-tests-filters diff --git a/GoogleTestAdapter/Core/Runners/PreparingTestRunner.cs b/GoogleTestAdapter/Core/Runners/PreparingTestRunner.cs index 45138c899..2e513e728 100644 --- a/GoogleTestAdapter/Core/Runners/PreparingTestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/PreparingTestRunner.cs @@ -61,8 +61,7 @@ public void RunTests(IEnumerable testCasesToRun, bool isBeingDebugged, stopwatch.Stop(); _logger.DebugInfo($"{_threadName}Execution took {stopwatch.Elapsed}"); - string errorMessage; - if (!Utils.DeleteDirectory(_testDirectory, out errorMessage)) + if (!Utils.DeleteDirectory(_testDirectory, out var errorMessage)) { _logger.DebugWarning( $"{_threadName}Could not delete test directory '" + _testDirectory + "': " + errorMessage); diff --git a/GoogleTestAdapter/Core/Scheduling/TestDurationSerializer.cs b/GoogleTestAdapter/Core/Scheduling/TestDurationSerializer.cs index f565356ec..8eef2441c 100644 --- a/GoogleTestAdapter/Core/Scheduling/TestDurationSerializer.cs +++ b/GoogleTestAdapter/Core/Scheduling/TestDurationSerializer.cs @@ -1,5 +1,7 @@ // This file has been modified by Microsoft on 6/2017. +#pragma warning disable IDE0017 // Simplify object initialization + using GoogleTestAdapter.Helpers; using GoogleTestAdapter.Model; using System; @@ -102,8 +104,7 @@ private IDictionary ReadTestDurations(string executable, List durationsMap = container.TestDurations.ToDictionary(x => x.Test, x => x); foreach (TestCase testcase in testcases) { - TestDuration pair; - if (durationsMap.TryGetValue(testcase.FullyQualifiedName, out pair)) + if (durationsMap.TryGetValue(testcase.FullyQualifiedName, out var pair)) durations.Add(testcase, pair.Duration); } diff --git a/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs b/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs index c8cb95da8..f1e057e17 100644 --- a/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs +++ b/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs @@ -63,8 +63,7 @@ public IList CreateTestCases(Action reportTestCase = null) } testCases.Add(testCase); - ISet testCasesOfSuite; - if (!suite2TestCases.TryGetValue(args.TestCaseDescriptor.Suite, out testCasesOfSuite)) + if (!suite2TestCases.TryGetValue(args.TestCaseDescriptor.Suite, out var testCasesOfSuite)) { suite2TestCases.Add(args.TestCaseDescriptor.Suite, testCasesOfSuite = new HashSet()); } diff --git a/GoogleTestAdapter/Core/TestResults/ErrorMessageParser.cs b/GoogleTestAdapter/Core/TestResults/ErrorMessageParser.cs index 8859d2720..d5e0774cf 100644 --- a/GoogleTestAdapter/Core/TestResults/ErrorMessageParser.cs +++ b/GoogleTestAdapter/Core/TestResults/ErrorMessageParser.cs @@ -110,8 +110,7 @@ private IList SplitConsoleOutput(string errorMessage) private void HandleSingleFailure() { string errorMessage = ErrorMessages[0]; - string stackTrace; - CreateErrorMessageAndStacktrace(ref errorMessage, out stackTrace); + CreateErrorMessageAndStacktrace(ref errorMessage, out var stackTrace); ErrorMessage = errorMessage; ErrorStackTrace = stackTrace; @@ -125,8 +124,7 @@ private void HandleMultipleFailures() { string errorMessage = ErrorMessages[i]; int msgId = i + 1; - string stackTrace; - CreateErrorMessageAndStacktrace(ref errorMessage, out stackTrace, msgId); + CreateErrorMessageAndStacktrace(ref errorMessage, out var stackTrace, msgId); finalErrorMessages.Add($"#{msgId} - {errorMessage}"); finalStackTraces.Add(stackTrace); diff --git a/GoogleTestAdapter/Core/TestResults/XmlTestResultParser.cs b/GoogleTestAdapter/Core/TestResults/XmlTestResultParser.cs index 23b7a9baa..fc5c150b1 100644 --- a/GoogleTestAdapter/Core/TestResults/XmlTestResultParser.cs +++ b/GoogleTestAdapter/Core/TestResults/XmlTestResultParser.cs @@ -99,7 +99,9 @@ private List ParseTestResults() var testResults = new List(); try { +#pragma warning disable IDE0017 // Simplify object initialization var settings = new XmlReaderSettings(); // Don't use an object initializer for FxCop to understand. +#pragma warning restore IDE0017 // Simplify object initialization settings.XmlResolver = null; using (var reader = XmlReader.Create(_xmlResultFile, settings)) { @@ -146,8 +148,7 @@ private TestResult ParseTestResult(XmlNode testcaseNode) { string qualifiedName = GetQualifiedName(testcaseNode); - TestCase testCase; - if (!_testCasesMap.TryGetValue(qualifiedName, out testCase) && + if (!_testCasesMap.TryGetValue(qualifiedName, out var testCase) && !_workaroundMapLazy.Value.TryGetValue(qualifiedName, out testCase)) { return null; diff --git a/GoogleTestAdapter/TestAdapter/Helpers/TestCaseFilter.cs b/GoogleTestAdapter/TestAdapter/Helpers/TestCaseFilter.cs index 8747f1fa9..33b6ebfb0 100644 --- a/GoogleTestAdapter/TestAdapter/Helpers/TestCaseFilter.cs +++ b/GoogleTestAdapter/TestAdapter/Helpers/TestCaseFilter.cs @@ -146,8 +146,7 @@ private bool Matches(TestCase testCase, ITestCaseFilterExpression filterExpressi private bool ValidateTraitValue(object value) { - string traitValue = value as string; - if (traitValue == null) + if (!(value is string traitValue)) return false; return TraitValueRegex.IsMatch(traitValue); diff --git a/GoogleTestAdapter/TestAdapter/Settings/RunSettingsContainer.cs b/GoogleTestAdapter/TestAdapter/Settings/RunSettingsContainer.cs index d89ea9bdd..8e43c75e3 100644 --- a/GoogleTestAdapter/TestAdapter/Settings/RunSettingsContainer.cs +++ b/GoogleTestAdapter/TestAdapter/Settings/RunSettingsContainer.cs @@ -1,5 +1,7 @@ // This file has been modified by Microsoft on 6/2017. +#pragma warning disable IDE0017 // Simplify object initialization + using GoogleTestAdapter.Helpers; using GoogleTestAdapter.Settings; using Microsoft.VisualStudio.TestPlatform.ObjectModel; diff --git a/GoogleTestAdapter/Tests.Common/AbstractConsoleIntegrationTests.cs b/GoogleTestAdapter/Tests.Common/AbstractConsoleIntegrationTests.cs index d368e6719..da9774097 100644 --- a/GoogleTestAdapter/Tests.Common/AbstractConsoleIntegrationTests.cs +++ b/GoogleTestAdapter/Tests.Common/AbstractConsoleIntegrationTests.cs @@ -92,9 +92,7 @@ public static string RunExecutableAndGetOutput(string solutionFile, string argum string workingDir = ""; var launcher = new TestProcessLauncher(); - List standardOut; - List standardErr; - launcher.GetOutputStreams(workingDir, command, arguments, out standardOut, out standardErr); + launcher.GetOutputStreams(workingDir, command, arguments, out List standardOut, out var standardErr); string resultString = string.Join("\n", standardOut) + "\n\n" + string.Join("\n", standardErr); // ReSharper disable once AssignNullToNotNullAttribute diff --git a/GoogleTestAdapter/Tests.Common/ResultChecker/ResultChecker.cs b/GoogleTestAdapter/Tests.Common/ResultChecker/ResultChecker.cs index 3f06ffb8d..f23d433d8 100644 --- a/GoogleTestAdapter/Tests.Common/ResultChecker/ResultChecker.cs +++ b/GoogleTestAdapter/Tests.Common/ResultChecker/ResultChecker.cs @@ -32,8 +32,7 @@ public void CheckResults(string testResults, string typeName, [CallerMemberName] } string expectedResult = File.ReadAllText(expectationFile); - string msg; - bool stringsAreEqual = AreEqual(expectedResult, testResults, out msg); + bool stringsAreEqual = AreEqual(expectedResult, testResults, out var msg); if (!stringsAreEqual) { #pragma warning disable CS0162 // Unreachable code (because overwriteTestResults is compile time constant) diff --git a/GoogleTestAdapter/Tests.Common/ResultChecker/TrxResultChecker.cs b/GoogleTestAdapter/Tests.Common/ResultChecker/TrxResultChecker.cs index 1b7bcf8f2..583655185 100644 --- a/GoogleTestAdapter/Tests.Common/ResultChecker/TrxResultChecker.cs +++ b/GoogleTestAdapter/Tests.Common/ResultChecker/TrxResultChecker.cs @@ -63,8 +63,7 @@ public void RunTestsAndCheckOutput(string typeName, string arguments, string tes Assert.Inconclusive($"First time this test runs, created golden file - check for correctness! File: {goldenFile}"); } CheckIfFileIsParsable(goldenFile); - string diffFile; - if (!CompareXmlFiles(goldenFile, transformedResultFile, out diffFile)) + if (!CompareXmlFiles(goldenFile, transformedResultFile, out var diffFile)) { if (!Directory.Exists(_diffFilesDir)) Directory.CreateDirectory(_diffFilesDir); @@ -97,8 +96,7 @@ private string RunExecutableAndGetResultsFile(string arguments) string workingDir = ""; var launcher = new TestProcessLauncher(); - List standardOut, allOutput; - launcher.GetOutputStreams(workingDir, command, arguments, out standardOut, out _, out allOutput); + launcher.GetOutputStreams(workingDir, command, arguments, out var standardOut, out _, out var allOutput); _completeOutput = $"Console output:{Environment.NewLine}{string.Join(Environment.NewLine, allOutput)}"; return ParseResultsFileFromOutput(standardOut); diff --git a/GoogleTestAdapter/Tests.Common/TestDataCreator.cs b/GoogleTestAdapter/Tests.Common/TestDataCreator.cs index 330463aa7..a07384c5f 100644 --- a/GoogleTestAdapter/Tests.Common/TestDataCreator.cs +++ b/GoogleTestAdapter/Tests.Common/TestDataCreator.cs @@ -96,8 +96,7 @@ public IEnumerable CreateDummyTestCasesFull(string[] qualifiedNamesToR int index = qualifiedName.LastIndexOf(".", StringComparison.Ordinal); string suite = qualifiedName.Substring(0, index); - ISet testCasesWithSuiteName; - if (!suite2TestCases.TryGetValue(suite, out testCasesWithSuiteName)) + if (!suite2TestCases.TryGetValue(suite, out var testCasesWithSuiteName)) suite2TestCases.Add(suite, testCasesWithSuiteName = new HashSet()); testCasesWithSuiteName.Add(testCase); } diff --git a/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/AsyncPackageRegistrationAttribute.cs b/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/AsyncPackageRegistrationAttribute.cs index f5b0b9a80..1ffcd3b71 100644 --- a/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/AsyncPackageRegistrationAttribute.cs +++ b/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/AsyncPackageRegistrationAttribute.cs @@ -102,8 +102,7 @@ public override void Register(RegistrationContext context) { packageKey = context.CreateKey(RegKeyName(context)); //use a friendly description if it exists. - DescriptionAttribute attr = TypeDescriptor.GetAttributes(t)[typeof(DescriptionAttribute)] as DescriptionAttribute; - if (attr != null && !String.IsNullOrEmpty(attr.Description)) { + if (TypeDescriptor.GetAttributes(t)[typeof(DescriptionAttribute)] is DescriptionAttribute attr && !String.IsNullOrEmpty(attr.Description)) { packageKey.SetValue(string.Empty, attr.Description); } else { diff --git a/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/ExtensionMethods.cs b/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/ExtensionMethods.cs index 1fc1376f8..09a961fec 100644 --- a/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/ExtensionMethods.cs +++ b/GoogleTestAdapter/VsPackage.GTA/AsyncPackage/ExtensionMethods.cs @@ -41,8 +41,7 @@ await ThreadHelper.JoinableTaskFactory.RunAsync(async () => /// true if async packages are supported public static bool IsAsyncPackageSupported(this IServiceProvider serviceProvider) { - IAsyncServiceProvider asyncServiceProvider = serviceProvider.GetService(typeof(SAsyncServiceProvider)) as IAsyncServiceProvider; - return asyncServiceProvider != null; + return serviceProvider.GetService(typeof(SAsyncServiceProvider)) is IAsyncServiceProvider; } } } \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.Shared/Commands/AbstractSwitchBooleanOptionCommand.cs b/GoogleTestAdapter/VsPackage.Shared/Commands/AbstractSwitchBooleanOptionCommand.cs index 1eee1fe62..6b246547b 100644 --- a/GoogleTestAdapter/VsPackage.Shared/Commands/AbstractSwitchBooleanOptionCommand.cs +++ b/GoogleTestAdapter/VsPackage.Shared/Commands/AbstractSwitchBooleanOptionCommand.cs @@ -12,13 +12,9 @@ internal abstract class AbstractSwitchBooleanOptionCommand protected AbstractSwitchBooleanOptionCommand(IGoogleTestExtensionOptionsPage package, int commandId) { - if (package == null) - throw new ArgumentNullException(nameof(package)); + Package = package ?? throw new ArgumentNullException(nameof(package)); - Package = package; - - OleMenuCommandService commandService = ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService; - if (commandService != null) + if (ServiceProvider.GetService(typeof(IMenuCommandService)) is OleMenuCommandService commandService) { var finalCommandId = new CommandID(CommandSet, commandId); var command = new OleMenuCommand(OnCommandInvoked, finalCommandId); @@ -33,8 +29,7 @@ protected AbstractSwitchBooleanOptionCommand(IGoogleTestExtensionOptionsPage pac private void OnBeforeQueryStatus(object sender, EventArgs e) { - var command = sender as OleMenuCommand; - if (command != null) + if (sender is OleMenuCommand command) command.Checked = Value; } diff --git a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs index fe7722373..7ff617f76 100644 --- a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs @@ -45,7 +45,6 @@ public sealed partial class GoogleTestExtensionOptionsPage : Package, IGoogleTes private ParallelizationOptionsDialogPage _parallelizationOptions; private GoogleTestOptionsDialogPage _googleTestOptions; - // ReSharper disable once NotAccessedField.Local private DebuggerAttacherServiceHost _debuggerAttacherServiceHost; private bool _isAsyncLoadSupported; @@ -141,6 +140,8 @@ public void Dispose() Dispose(true); } + [SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", + MessageId = nameof(_debuggerAttacherServiceHost), Justification = "Close() includes Dispose()")] protected override void Dispose(bool disposing) { if (disposing) From c0efb1138ba4e2e420254b8900a9002820dcd1ac Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Fri, 8 Mar 2019 19:28:47 +0100 Subject: [PATCH 32/81] removed FluentAssertions analyzers since they do not appear to be maintained any more (and produce lots of false positives) --- GoogleTestAdapter/Core.Tests/Core.Tests.csproj | 3 --- GoogleTestAdapter/Core.Tests/packages.config | 1 - GoogleTestAdapter/DiaResolver.Tests/DiaResolver.Tests.csproj | 3 --- GoogleTestAdapter/DiaResolver.Tests/packages.config | 1 - GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj | 3 --- GoogleTestAdapter/TestAdapter.Tests/packages.config | 1 - GoogleTestAdapter/Tests.Common/Tests.Common.csproj | 3 --- GoogleTestAdapter/Tests.Common/packages.config | 1 - .../VsPackage.GTA.Tests.Unit/VsPackage.GTA.Tests.Unit.csproj | 3 --- GoogleTestAdapter/VsPackage.GTA.Tests.Unit/packages.config | 1 - .../VsPackage.Tests.Generated/VsPackage.Tests.Generated.csproj | 3 --- GoogleTestAdapter/VsPackage.Tests.Generated/packages.config | 1 - GoogleTestAdapter/VsPackage.Tests/VsPackage.Tests.csproj | 3 --- GoogleTestAdapter/VsPackage.Tests/packages.config | 1 - 14 files changed, 28 deletions(-) diff --git a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj index da6221a87..ab66af659 100644 --- a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj +++ b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj @@ -135,9 +135,6 @@ Tests.Common - - - diff --git a/GoogleTestAdapter/Core.Tests/packages.config b/GoogleTestAdapter/Core.Tests/packages.config index c82825cc2..87cac3d92 100644 --- a/GoogleTestAdapter/Core.Tests/packages.config +++ b/GoogleTestAdapter/Core.Tests/packages.config @@ -2,7 +2,6 @@ - diff --git a/GoogleTestAdapter/DiaResolver.Tests/DiaResolver.Tests.csproj b/GoogleTestAdapter/DiaResolver.Tests/DiaResolver.Tests.csproj index b9ba0f2b7..14b159823 100644 --- a/GoogleTestAdapter/DiaResolver.Tests/DiaResolver.Tests.csproj +++ b/GoogleTestAdapter/DiaResolver.Tests/DiaResolver.Tests.csproj @@ -107,9 +107,6 @@ Designer - - - diff --git a/GoogleTestAdapter/DiaResolver.Tests/packages.config b/GoogleTestAdapter/DiaResolver.Tests/packages.config index b9f419743..265e3a75c 100644 --- a/GoogleTestAdapter/DiaResolver.Tests/packages.config +++ b/GoogleTestAdapter/DiaResolver.Tests/packages.config @@ -2,7 +2,6 @@ - diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj b/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj index 0a29685ac..284b7640e 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj +++ b/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj @@ -151,9 +151,6 @@ Tests.Common - - - diff --git a/GoogleTestAdapter/TestAdapter.Tests/packages.config b/GoogleTestAdapter/TestAdapter.Tests/packages.config index a2b919a99..dbf70ba5c 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/packages.config +++ b/GoogleTestAdapter/TestAdapter.Tests/packages.config @@ -2,7 +2,6 @@ - diff --git a/GoogleTestAdapter/Tests.Common/Tests.Common.csproj b/GoogleTestAdapter/Tests.Common/Tests.Common.csproj index 24415b5e9..0b1141c06 100644 --- a/GoogleTestAdapter/Tests.Common/Tests.Common.csproj +++ b/GoogleTestAdapter/Tests.Common/Tests.Common.csproj @@ -189,9 +189,6 @@ PreserveNewest - - - diff --git a/GoogleTestAdapter/Tests.Common/packages.config b/GoogleTestAdapter/Tests.Common/packages.config index 82b401a63..1002f4ebe 100644 --- a/GoogleTestAdapter/Tests.Common/packages.config +++ b/GoogleTestAdapter/Tests.Common/packages.config @@ -2,7 +2,6 @@ - diff --git a/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/VsPackage.GTA.Tests.Unit.csproj b/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/VsPackage.GTA.Tests.Unit.csproj index 13127471c..88f93b10d 100644 --- a/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/VsPackage.GTA.Tests.Unit.csproj +++ b/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/VsPackage.GTA.Tests.Unit.csproj @@ -122,9 +122,6 @@ Designer - - - diff --git a/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/packages.config b/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/packages.config index 3eda5c295..00c298a97 100644 --- a/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/packages.config +++ b/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/packages.config @@ -2,7 +2,6 @@ - diff --git a/GoogleTestAdapter/VsPackage.Tests.Generated/VsPackage.Tests.Generated.csproj b/GoogleTestAdapter/VsPackage.Tests.Generated/VsPackage.Tests.Generated.csproj index d7eaee637..143e4acf0 100644 --- a/GoogleTestAdapter/VsPackage.Tests.Generated/VsPackage.Tests.Generated.csproj +++ b/GoogleTestAdapter/VsPackage.Tests.Generated/VsPackage.Tests.Generated.csproj @@ -119,9 +119,6 @@ - - - diff --git a/GoogleTestAdapter/VsPackage.Tests.Generated/packages.config b/GoogleTestAdapter/VsPackage.Tests.Generated/packages.config index 66a2dc8a9..b500a066c 100644 --- a/GoogleTestAdapter/VsPackage.Tests.Generated/packages.config +++ b/GoogleTestAdapter/VsPackage.Tests.Generated/packages.config @@ -1,6 +1,5 @@  - \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.Tests/VsPackage.Tests.csproj b/GoogleTestAdapter/VsPackage.Tests/VsPackage.Tests.csproj index eddee26ff..bb19867fe 100644 --- a/GoogleTestAdapter/VsPackage.Tests/VsPackage.Tests.csproj +++ b/GoogleTestAdapter/VsPackage.Tests/VsPackage.Tests.csproj @@ -161,9 +161,6 @@ - - - diff --git a/GoogleTestAdapter/VsPackage.Tests/packages.config b/GoogleTestAdapter/VsPackage.Tests/packages.config index 986378f41..ef91e6519 100644 --- a/GoogleTestAdapter/VsPackage.Tests/packages.config +++ b/GoogleTestAdapter/VsPackage.Tests/packages.config @@ -2,7 +2,6 @@ - From 3ed12996d115c9f3db4401bb5849f6bc08d2c79e Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Fri, 8 Mar 2019 21:40:16 +0100 Subject: [PATCH 33/81] removed unnecessary dependency --- GoogleTestAdapter/TestAdapter/TestAdapter.csproj | 4 ---- 1 file changed, 4 deletions(-) diff --git a/GoogleTestAdapter/TestAdapter/TestAdapter.csproj b/GoogleTestAdapter/TestAdapter/TestAdapter.csproj index 328deee35..580b4f984 100644 --- a/GoogleTestAdapter/TestAdapter/TestAdapter.csproj +++ b/GoogleTestAdapter/TestAdapter/TestAdapter.csproj @@ -51,10 +51,6 @@ - - $(NuGetPackages)VSSDK.Shell.11.11.0.0\lib\net45\Microsoft.VisualStudio.Shell.11.0.dll - False - $(NuGetPackages)Microsoft.TestPlatform.ObjectModel.11.0.0\lib\net35\Microsoft.VisualStudio.TestPlatform.ObjectModel.dll False From 10fd131b8c13f8abe96a0ca586eeb9cb29b25e51 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sat, 9 Mar 2019 09:20:02 +0100 Subject: [PATCH 34/81] removed TAfGT specific projects and code generation for now to make contributions easier (and until MS has merged current GTA state into the TAfGT repository) - see wiki --- CONTRIBUTING.md | 3 - GoogleTestAdapter/Core.Tests/.gitignore | 1 - GoogleTestAdapter/Core.Tests/app.config | 23 ++++ .../DiaResolver.Tests/.gitignore | 1 - .../DiaResolver.Tests/app.config | 23 ++++ GoogleTestAdapter/GoogleTestAdapter.sln | 57 --------- .../TestAdapter.Tests/.gitignore | 4 +- .../TestAdapter.Tests/app.config | 23 ++++ GoogleTestAdapter/TestAdapter/.gitignore | 2 - .../TestAdapter/TestExecutorBranding.cs | 11 ++ GoogleTestAdapter/Tests.Common/.gitignore | 1 - GoogleTestAdapter/Tests.Common/app.config | 23 ++++ .../VsPackage.GTA.Tests.Unit/.gitignore | 1 - .../VsPackage.GTA.Tests.Unit/app.config | 23 ++++ .../VsPackage.Tests.Generated/.gitignore | 1 - .../VsPackage.Tests.Generated/app.config | 23 ++++ GoogleTestAdapter/VsPackage.Tests/.gitignore | 2 - GoogleTestAdapter/VsPackage.Tests/app.config | 23 ++++ ThirdPartyNotices.txt | 113 ------------------ build_preparation.bat | 10 +- 20 files changed, 178 insertions(+), 190 deletions(-) delete mode 100644 CONTRIBUTING.md create mode 100644 GoogleTestAdapter/Core.Tests/app.config create mode 100644 GoogleTestAdapter/DiaResolver.Tests/app.config create mode 100644 GoogleTestAdapter/TestAdapter.Tests/app.config create mode 100644 GoogleTestAdapter/TestAdapter/TestExecutorBranding.cs create mode 100644 GoogleTestAdapter/Tests.Common/app.config create mode 100644 GoogleTestAdapter/VsPackage.GTA.Tests.Unit/app.config create mode 100644 GoogleTestAdapter/VsPackage.Tests.Generated/app.config create mode 100644 GoogleTestAdapter/VsPackage.Tests/app.config delete mode 100644 ThirdPartyNotices.txt diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index bc0d380e8..000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,3 +0,0 @@ -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). - -For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. \ No newline at end of file diff --git a/GoogleTestAdapter/Core.Tests/.gitignore b/GoogleTestAdapter/Core.Tests/.gitignore index 151142b4d..707677037 100644 --- a/GoogleTestAdapter/Core.Tests/.gitignore +++ b/GoogleTestAdapter/Core.Tests/.gitignore @@ -1,2 +1 @@ -app.config Key.snk \ No newline at end of file diff --git a/GoogleTestAdapter/Core.Tests/app.config b/GoogleTestAdapter/Core.Tests/app.config new file mode 100644 index 000000000..fbc79343d --- /dev/null +++ b/GoogleTestAdapter/Core.Tests/app.config @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/GoogleTestAdapter/DiaResolver.Tests/.gitignore b/GoogleTestAdapter/DiaResolver.Tests/.gitignore index 151142b4d..707677037 100644 --- a/GoogleTestAdapter/DiaResolver.Tests/.gitignore +++ b/GoogleTestAdapter/DiaResolver.Tests/.gitignore @@ -1,2 +1 @@ -app.config Key.snk \ No newline at end of file diff --git a/GoogleTestAdapter/DiaResolver.Tests/app.config b/GoogleTestAdapter/DiaResolver.Tests/app.config new file mode 100644 index 000000000..fbc79343d --- /dev/null +++ b/GoogleTestAdapter/DiaResolver.Tests/app.config @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/GoogleTestAdapter/GoogleTestAdapter.sln b/GoogleTestAdapter/GoogleTestAdapter.sln index ef468f2ae..dfee3be1c 100644 --- a/GoogleTestAdapter/GoogleTestAdapter.sln +++ b/GoogleTestAdapter/GoogleTestAdapter.sln @@ -25,8 +25,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VsPackage.GTA", "VsPackage. EndProject Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "VsPackage.Shared", "VsPackage.Shared\VsPackage.Shared.shproj", "{AC75F34E-190B-402A-8C46-91B0FA02450F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VsPackage.TAfGT", "VsPackage.TAfGT\VsPackage.TAfGT.csproj", "{55294B5F-A075-43F2-B0E9-2B11925E8B91}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestAdapter", "TestAdapter\TestAdapter.csproj", "{44C04E51-D543-4155-A57E-BBEB73D3F8E5}" ProjectSection(ProjectDependencies) = postProject {FDC95D92-5E1E-4BDF-AA35-181851FCE755} = {FDC95D92-5E1E-4BDF-AA35-181851FCE755} @@ -70,8 +68,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "Common\Common.csp EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common.Dynamic.GTA", "Common.Dynamic.GTA\Common.Dynamic.GTA.csproj", "{17F4B73F-E4D3-4E40-98FC-788B1D0F8225}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common.Dynamic.TAfGT", "Common.Dynamic.TAfGT\Common.Dynamic.TAfGT.csproj", "{9041BDED-FA1B-4C17-B7EA-7B750C470C23}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VsPackage.GTA.Tests.Unit", "VsPackage.GTA.Tests.Unit\VsPackage.GTA.Tests.Unit.csproj", "{87F26371-0005-4301-9C49-A6DF4F06B81C}" ProjectSection(ProjectDependencies) = postProject {12952B24-C70B-4A26-839A-EE4183BE8CC0} = {12952B24-C70B-4A26-839A-EE4183BE8CC0} @@ -118,12 +114,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DllProject", "..\SampleTest EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DllTests", "..\SampleTests\DllDependentProject\DllDependentProject.vcxproj", "{2E3221EB-86DA-427D-84EC-DEFD3F966D9A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NewProjectWizard", "NewProjectWizard\NewProjectWizard.csproj", "{483FE0C7-4E8D-4591-BE45-EAC6B2EA5F4F}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Packaging.GTA", "Packaging.GTA\Packaging.GTA.csproj", "{4735D8CC-FA30-432D-854C-2984A7DA5DD2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Packaging.TAfGT", "Packaging.TAfGT\Packaging.TAfGT.csproj", "{B3AEAD11-8EA3-4AB0-9DB0-643BFAAEB9B2}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SemaphoreExe", "SemaphoreExe\SemaphoreExe.vcxproj", "{F48AD2EC-96B3-41C6-9F89-3542EC7A3D43}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{C5996129-A88E-45E1-A7B0-0B145B4FA0D8}" @@ -165,7 +157,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LeakCheckTests", "..\Sample EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution - VsPackage.Shared\VsPackage.Shared.projitems*{55294b5f-a075-43f2-b0e9-2b11925e8b91}*SharedItemsImports = 4 VsPackage.Shared\VsPackage.Shared.projitems*{ac75f34e-190b-402a-8c46-91b0fa02450f}*SharedItemsImports = 13 VsPackage.Shared\VsPackage.Shared.projitems*{e6276cad-e4c3-4b25-876a-65b265ebff1a}*SharedItemsImports = 4 EndGlobalSection @@ -190,18 +181,6 @@ Global {E6276CAD-E4C3-4B25-876A-65B265EBFF1A}.Release|x64.Build.0 = Release|Any CPU {E6276CAD-E4C3-4B25-876A-65B265EBFF1A}.Release|x86.ActiveCfg = Release|Any CPU {E6276CAD-E4C3-4B25-876A-65B265EBFF1A}.Release|x86.Build.0 = Release|Any CPU - {55294B5F-A075-43F2-B0E9-2B11925E8B91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {55294B5F-A075-43F2-B0E9-2B11925E8B91}.Debug|Any CPU.Build.0 = Debug|Any CPU - {55294B5F-A075-43F2-B0E9-2B11925E8B91}.Debug|x64.ActiveCfg = Debug|Any CPU - {55294B5F-A075-43F2-B0E9-2B11925E8B91}.Debug|x64.Build.0 = Debug|Any CPU - {55294B5F-A075-43F2-B0E9-2B11925E8B91}.Debug|x86.ActiveCfg = Debug|Any CPU - {55294B5F-A075-43F2-B0E9-2B11925E8B91}.Debug|x86.Build.0 = Debug|Any CPU - {55294B5F-A075-43F2-B0E9-2B11925E8B91}.Release|Any CPU.ActiveCfg = Release|Any CPU - {55294B5F-A075-43F2-B0E9-2B11925E8B91}.Release|Any CPU.Build.0 = Release|Any CPU - {55294B5F-A075-43F2-B0E9-2B11925E8B91}.Release|x64.ActiveCfg = Release|Any CPU - {55294B5F-A075-43F2-B0E9-2B11925E8B91}.Release|x64.Build.0 = Release|Any CPU - {55294B5F-A075-43F2-B0E9-2B11925E8B91}.Release|x86.ActiveCfg = Release|Any CPU - {55294B5F-A075-43F2-B0E9-2B11925E8B91}.Release|x86.Build.0 = Release|Any CPU {44C04E51-D543-4155-A57E-BBEB73D3F8E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {44C04E51-D543-4155-A57E-BBEB73D3F8E5}.Debug|Any CPU.Build.0 = Debug|Any CPU {44C04E51-D543-4155-A57E-BBEB73D3F8E5}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -322,18 +301,6 @@ Global {17F4B73F-E4D3-4E40-98FC-788B1D0F8225}.Release|x64.Build.0 = Release|Any CPU {17F4B73F-E4D3-4E40-98FC-788B1D0F8225}.Release|x86.ActiveCfg = Release|Any CPU {17F4B73F-E4D3-4E40-98FC-788B1D0F8225}.Release|x86.Build.0 = Release|Any CPU - {9041BDED-FA1B-4C17-B7EA-7B750C470C23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9041BDED-FA1B-4C17-B7EA-7B750C470C23}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9041BDED-FA1B-4C17-B7EA-7B750C470C23}.Debug|x64.ActiveCfg = Debug|Any CPU - {9041BDED-FA1B-4C17-B7EA-7B750C470C23}.Debug|x64.Build.0 = Debug|Any CPU - {9041BDED-FA1B-4C17-B7EA-7B750C470C23}.Debug|x86.ActiveCfg = Debug|Any CPU - {9041BDED-FA1B-4C17-B7EA-7B750C470C23}.Debug|x86.Build.0 = Debug|Any CPU - {9041BDED-FA1B-4C17-B7EA-7B750C470C23}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9041BDED-FA1B-4C17-B7EA-7B750C470C23}.Release|Any CPU.Build.0 = Release|Any CPU - {9041BDED-FA1B-4C17-B7EA-7B750C470C23}.Release|x64.ActiveCfg = Release|Any CPU - {9041BDED-FA1B-4C17-B7EA-7B750C470C23}.Release|x64.Build.0 = Release|Any CPU - {9041BDED-FA1B-4C17-B7EA-7B750C470C23}.Release|x86.ActiveCfg = Release|Any CPU - {9041BDED-FA1B-4C17-B7EA-7B750C470C23}.Release|x86.Build.0 = Release|Any CPU {87F26371-0005-4301-9C49-A6DF4F06B81C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {87F26371-0005-4301-9C49-A6DF4F06B81C}.Debug|Any CPU.Build.0 = Debug|Any CPU {87F26371-0005-4301-9C49-A6DF4F06B81C}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -486,18 +453,6 @@ Global {2E3221EB-86DA-427D-84EC-DEFD3F966D9A}.Release|x64.Build.0 = Release|x64 {2E3221EB-86DA-427D-84EC-DEFD3F966D9A}.Release|x86.ActiveCfg = Release|Win32 {2E3221EB-86DA-427D-84EC-DEFD3F966D9A}.Release|x86.Build.0 = Release|Win32 - {483FE0C7-4E8D-4591-BE45-EAC6B2EA5F4F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {483FE0C7-4E8D-4591-BE45-EAC6B2EA5F4F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {483FE0C7-4E8D-4591-BE45-EAC6B2EA5F4F}.Debug|x64.ActiveCfg = Debug|Any CPU - {483FE0C7-4E8D-4591-BE45-EAC6B2EA5F4F}.Debug|x64.Build.0 = Debug|Any CPU - {483FE0C7-4E8D-4591-BE45-EAC6B2EA5F4F}.Debug|x86.ActiveCfg = Debug|Any CPU - {483FE0C7-4E8D-4591-BE45-EAC6B2EA5F4F}.Debug|x86.Build.0 = Debug|Any CPU - {483FE0C7-4E8D-4591-BE45-EAC6B2EA5F4F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {483FE0C7-4E8D-4591-BE45-EAC6B2EA5F4F}.Release|Any CPU.Build.0 = Release|Any CPU - {483FE0C7-4E8D-4591-BE45-EAC6B2EA5F4F}.Release|x64.ActiveCfg = Release|Any CPU - {483FE0C7-4E8D-4591-BE45-EAC6B2EA5F4F}.Release|x64.Build.0 = Release|Any CPU - {483FE0C7-4E8D-4591-BE45-EAC6B2EA5F4F}.Release|x86.ActiveCfg = Release|Any CPU - {483FE0C7-4E8D-4591-BE45-EAC6B2EA5F4F}.Release|x86.Build.0 = Release|Any CPU {4735D8CC-FA30-432D-854C-2984A7DA5DD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4735D8CC-FA30-432D-854C-2984A7DA5DD2}.Debug|Any CPU.Build.0 = Debug|Any CPU {4735D8CC-FA30-432D-854C-2984A7DA5DD2}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -510,18 +465,6 @@ Global {4735D8CC-FA30-432D-854C-2984A7DA5DD2}.Release|x64.Build.0 = Release|Any CPU {4735D8CC-FA30-432D-854C-2984A7DA5DD2}.Release|x86.ActiveCfg = Release|Any CPU {4735D8CC-FA30-432D-854C-2984A7DA5DD2}.Release|x86.Build.0 = Release|Any CPU - {B3AEAD11-8EA3-4AB0-9DB0-643BFAAEB9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B3AEAD11-8EA3-4AB0-9DB0-643BFAAEB9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B3AEAD11-8EA3-4AB0-9DB0-643BFAAEB9B2}.Debug|x64.ActiveCfg = Debug|Any CPU - {B3AEAD11-8EA3-4AB0-9DB0-643BFAAEB9B2}.Debug|x64.Build.0 = Debug|Any CPU - {B3AEAD11-8EA3-4AB0-9DB0-643BFAAEB9B2}.Debug|x86.ActiveCfg = Debug|Any CPU - {B3AEAD11-8EA3-4AB0-9DB0-643BFAAEB9B2}.Debug|x86.Build.0 = Debug|Any CPU - {B3AEAD11-8EA3-4AB0-9DB0-643BFAAEB9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B3AEAD11-8EA3-4AB0-9DB0-643BFAAEB9B2}.Release|Any CPU.Build.0 = Release|Any CPU - {B3AEAD11-8EA3-4AB0-9DB0-643BFAAEB9B2}.Release|x64.ActiveCfg = Release|Any CPU - {B3AEAD11-8EA3-4AB0-9DB0-643BFAAEB9B2}.Release|x64.Build.0 = Release|Any CPU - {B3AEAD11-8EA3-4AB0-9DB0-643BFAAEB9B2}.Release|x86.ActiveCfg = Release|Any CPU - {B3AEAD11-8EA3-4AB0-9DB0-643BFAAEB9B2}.Release|x86.Build.0 = Release|Any CPU {F48AD2EC-96B3-41C6-9F89-3542EC7A3D43}.Debug|Any CPU.ActiveCfg = Debug|Win32 {F48AD2EC-96B3-41C6-9F89-3542EC7A3D43}.Debug|Any CPU.Build.0 = Debug|Win32 {F48AD2EC-96B3-41C6-9F89-3542EC7A3D43}.Debug|x64.ActiveCfg = Debug|x64 diff --git a/GoogleTestAdapter/TestAdapter.Tests/.gitignore b/GoogleTestAdapter/TestAdapter.Tests/.gitignore index b4abc5dc2..707677037 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/.gitignore +++ b/GoogleTestAdapter/TestAdapter.Tests/.gitignore @@ -1,3 +1 @@ -app.config -Key.snk -packages.config \ No newline at end of file +Key.snk \ No newline at end of file diff --git a/GoogleTestAdapter/TestAdapter.Tests/app.config b/GoogleTestAdapter/TestAdapter.Tests/app.config new file mode 100644 index 000000000..fbc79343d --- /dev/null +++ b/GoogleTestAdapter/TestAdapter.Tests/app.config @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/GoogleTestAdapter/TestAdapter/.gitignore b/GoogleTestAdapter/TestAdapter/.gitignore index 2f65fa587..4707cdd1e 100644 --- a/GoogleTestAdapter/TestAdapter/.gitignore +++ b/GoogleTestAdapter/TestAdapter/.gitignore @@ -1,3 +1 @@ Key.snk -packages.config -TestExecutorBranding.cs \ No newline at end of file diff --git a/GoogleTestAdapter/TestAdapter/TestExecutorBranding.cs b/GoogleTestAdapter/TestAdapter/TestExecutorBranding.cs new file mode 100644 index 000000000..bf4d160bb --- /dev/null +++ b/GoogleTestAdapter/TestAdapter/TestExecutorBranding.cs @@ -0,0 +1,11 @@ +// This file was generated from a template. Any modifications will be lost. +namespace GoogleTestAdapter.TestAdapter +{ + + public partial class TestExecutor + { + public const string ExecutorUriString = + "executor://GoogleTestRunner/v1"; + } + +} \ No newline at end of file diff --git a/GoogleTestAdapter/Tests.Common/.gitignore b/GoogleTestAdapter/Tests.Common/.gitignore index e5ab9d402..a64a4d5c2 100644 --- a/GoogleTestAdapter/Tests.Common/.gitignore +++ b/GoogleTestAdapter/Tests.Common/.gitignore @@ -1,3 +1,2 @@ -app.config nuget.exe VsTestConsole \ No newline at end of file diff --git a/GoogleTestAdapter/Tests.Common/app.config b/GoogleTestAdapter/Tests.Common/app.config new file mode 100644 index 000000000..e211d0ea3 --- /dev/null +++ b/GoogleTestAdapter/Tests.Common/app.config @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/.gitignore b/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/.gitignore index 151142b4d..707677037 100644 --- a/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/.gitignore +++ b/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/.gitignore @@ -1,2 +1 @@ -app.config Key.snk \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/app.config b/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/app.config new file mode 100644 index 000000000..fbc79343d --- /dev/null +++ b/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/app.config @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.Tests.Generated/.gitignore b/GoogleTestAdapter/VsPackage.Tests.Generated/.gitignore index a97ac1d18..6da4def5e 100644 --- a/GoogleTestAdapter/VsPackage.Tests.Generated/.gitignore +++ b/GoogleTestAdapter/VsPackage.Tests.Generated/.gitignore @@ -1,3 +1,2 @@ -app.config ConsoleTests.cs TestErrors diff --git a/GoogleTestAdapter/VsPackage.Tests.Generated/app.config b/GoogleTestAdapter/VsPackage.Tests.Generated/app.config new file mode 100644 index 000000000..e211d0ea3 --- /dev/null +++ b/GoogleTestAdapter/VsPackage.Tests.Generated/app.config @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.Tests/.gitignore b/GoogleTestAdapter/VsPackage.Tests/.gitignore index 12e48362b..b0ffbc96c 100644 --- a/GoogleTestAdapter/VsPackage.Tests/.gitignore +++ b/GoogleTestAdapter/VsPackage.Tests/.gitignore @@ -1,3 +1 @@ -app.config -packages.config TestErrors \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.Tests/app.config b/GoogleTestAdapter/VsPackage.Tests/app.config new file mode 100644 index 000000000..e211d0ea3 --- /dev/null +++ b/GoogleTestAdapter/VsPackage.Tests/app.config @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt deleted file mode 100644 index 03341878c..000000000 --- a/ThirdPartyNotices.txt +++ /dev/null @@ -1,113 +0,0 @@ - -THIRD-PARTY SOFTWARE NOTICES AND INFORMATION -Do Not Translate or Localize - -Test Adapter for Google Test incorporates components from the projects listed below. Microsoft licenses these components to you under Microsoft’s software licensing terms, except that components licensed under open source licenses requiring that such components remain under their original license are being made available to you by Microsoft under their original licensing terms. The original copyright notices and the licenses under which Microsoft received such components are set forth below for informational purposes. Microsoft reserves all rights not expressly granted herein, whether by implication, estoppel or otherwise. - - - -1. Google Test Adapter (https://github.com/csoltenborn/GoogleTestAdapter) -2. Google Test Framework (https://github.com/google/googletest) -3. Image files from PICOL (http://picol.org/index.php) - - -%% Google Test Adapter NOTICES, INFORMATION, AND LICENSE BEGIN HERE -========================================= -Copyright 2015, 2016, 2017 Christian Soltenborn, Jonas Gefele - -Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - -[http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) - -Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -========================================= -END OF Google Test Adapter NOTICES, INFORMATION, AND LICENSE - -%% Google Test Framework NOTICES, INFORMATION, AND LICENSE BEGIN HERE -========================================= -Copyright 2008, Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -========================================= -END OF Google Test Framework NOTICES, INFORMATION, AND LICENSE - -%% Image files from PICOL NOTICES, INFORMATION, AND LICENSE BEGIN HERE -========================================= -Attribution-ShareAlike 3.0 Unported -CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM ITS USE. -License -THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. -BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS. -1. Definitions -"Adaptation" means a work based upon the Work, or upon the Work and other pre-existing works, such as a translation, adaptation, derivative work, arrangement of music or other alterations of a literary or artistic work, or phonogram or performance and includes cinematographic adaptations or any other form in which the Work may be recast, transformed, or adapted including in any form recognizably derived from the original, except that a work that constitutes a Collection will not be considered an Adaptation for the purpose of this License. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered an Adaptation for the purpose of this License. -"Collection" means a collection of literary or artistic works, such as encyclopedias and anthologies, or performances, phonograms or broadcasts, or other works or subject matter other than works listed in Section 1(f) below, which, by reason of the selection and arrangement of their contents, constitute intellectual creations, in which the Work is included in its entirety in unmodified form along with one or more other contributions, each constituting separate and independent works in themselves, which together are assembled into a collective whole. A work that constitutes a Collection will not be considered an Adaptation (as defined below) for the purposes of this License. -"Creative Commons Compatible License" means a license that is listed at https://creativecommons.org/compatiblelicenses that has been approved by Creative Commons as being essentially equivalent to this License, including, at a minimum, because that license: (i) contains terms that have the same purpose, meaning and effect as the License Elements of this License; and, (ii) explicitly permits the relicensing of adaptations of works made available under that license under this License or a Creative Commons jurisdiction license with the same License Elements as this License. -"Distribute" means to make available to the public the original and copies of the Work or Adaptation, as appropriate, through sale or other transfer of ownership. -"License Elements" means the following high-level license attributes as selected by Licensor and indicated in the title of this License: Attribution, ShareAlike. -"Licensor" means the individual, individuals, entity or entities that offer(s) the Work under the terms of this License. -"Original Author" means, in the case of a literary or artistic work, the individual, individuals, entity or entities who created the Work or if no individual or entity can be identified, the publisher; and in addition (i) in the case of a performance the actors, singers, musicians, dancers, and other persons who act, sing, deliver, declaim, play in, interpret or otherwise perform literary or artistic works or expressions of folklore; (ii) in the case of a phonogram the producer being the person or legal entity who first fixes the sounds of a performance or other sounds; and, (iii) in the case of broadcasts, the organization that transmits the broadcast. -"Work" means the literary and/or artistic work offered under the terms of this License including without limitation any production in the literary, scientific and artistic domain, whatever may be the mode or form of its expression including digital form, such as a book, pamphlet and other writing; a lecture, address, sermon or other work of the same nature; a dramatic or dramatico-musical work; a choreographic work or entertainment in dumb show; a musical composition with or without words; a cinematographic work to which are assimilated works expressed by a process analogous to cinematography; a work of drawing, painting, architecture, sculpture, engraving or lithography; a photographic work to which are assimilated works expressed by a process analogous to photography; a work of applied art; an illustration, map, plan, sketch or three-dimensional work relative to geography, topography, architecture or science; a performance; a broadcast; a phonogram; a compilation of data to the extent it is protected as a copyrightable work; or a work performed by a variety or circus performer to the extent it is not otherwise considered a literary or artistic work. -"You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation. -"Publicly Perform" means to perform public recitations of the Work and to communicate to the public those public recitations, by any means or process, including by wire or wireless means or public digital performances; to make available to the public Works in such a way that members of the public may access these Works from a place and at a place individually chosen by them; to perform the Work to the public by any means or process and the communication to the public of the performances of the Work, including by public digital performance; to broadcast and rebroadcast the Work by any means including signs, sounds or images. -"Reproduce" means to make copies of the Work by any means including without limitation by sound or visual recordings and the right of fixation and reproducing fixations of the Work, including storage of a protected performance or phonogram in digital form or other electronic medium. -2. Fair Dealing Rights. Nothing in this License is intended to reduce, limit, or restrict any uses free from copyright or rights arising from limitations or exceptions that are provided for in connection with the copyright protection under copyright law or other applicable laws. -3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below: -to Reproduce the Work, to incorporate the Work into one or more Collections, and to Reproduce the Work as incorporated in the Collections; -to create and Reproduce Adaptations provided that any such Adaptation, including any translation in any medium, takes reasonable steps to clearly label, demarcate or otherwise identify that changes were made to the original Work. For example, a translation could be marked "The original work was translated from English to Spanish," or a modification could indicate "The original work has been modified."; -to Distribute and Publicly Perform the Work including as incorporated in Collections; and, to Distribute and Publicly Perform Adaptations. -For the avoidance of doubt: -Non-waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme cannot be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License; -Waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme can be waived, the Licensor waives the exclusive right to collect such royalties for any exercise by You of the rights granted under this License; and, -Voluntary License Schemes. The Licensor waives the right to collect royalties, whether individually or, in the event that the Licensor is a member of a collecting society that administers voluntary licensing schemes, via that society, from any exercise by You of the rights granted under this License. -The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. Subject to Section 8(f), all rights not expressly granted by Licensor are hereby reserved. -4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions: -You may Distribute or Publicly Perform the Work only under the terms of this License. You must include a copy of, or the Uniform Resource Identifier (URI) for, this License with every copy of the Work You Distribute or Publicly Perform. You may not offer or impose any terms on the Work that restrict the terms of this License or the ability of the recipient of the Work to exercise the rights granted to that recipient under the terms of the License. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties with every copy of the Work You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Work, You may not impose any effective technological measures on the Work that restrict the ability of a recipient of the Work from You to exercise the rights granted to that recipient under the terms of the License. This Section 4(a) applies to the Work as incorporated in a Collection, but this does not require the Collection apart from the Work itself to be made subject to the terms of this License. If You create a Collection, upon notice from any Licensor You must, to the extent practicable, remove from the Collection any credit as required by Section 4(c), as requested. If You create an Adaptation, upon notice from any Licensor You must, to the extent practicable, remove from the Adaptation any credit as required by Section 4(c), as requested. -You may Distribute or Publicly Perform an Adaptation only under the terms of: (i) this License; (ii) a later version of this License with the same License Elements as this License; (iii) a Creative Commons jurisdiction license (either this or a later license version) that contains the same License Elements as this License (e.g., Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons Compatible License. If you license the Adaptation under one of the licenses mentioned in (iv), you must comply with the terms of that license. If you license the Adaptation under the terms of any of the licenses mentioned in (i), (ii) or (iii) (the "Applicable License"), you must comply with the terms of the Applicable License generally and the following provisions: (I) You must include a copy of, or the URI for, the Applicable License with every copy of each Adaptation You Distribute or Publicly Perform; (II) You may not offer or impose any terms on the Adaptation that restrict the terms of the Applicable License or the ability of the recipient of the Adaptation to exercise the rights granted to that recipient under the terms of the Applicable License; (III) You must keep intact all notices that refer to the Applicable License and to the disclaimer of warranties with every copy of the Work as included in the Adaptation You Distribute or Publicly Perform; (IV) when You Distribute or Publicly Perform the Adaptation, You may not impose any effective technological measures on the Adaptation that restrict the ability of a recipient of the Adaptation from You to exercise the rights granted to that recipient under the terms of the Applicable License. This Section 4(b) applies to the Adaptation as incorporated in a Collection, but this does not require the Collection apart from the Adaptation itself to be made subject to the terms of the Applicable License. -If You Distribute, or Publicly Perform the Work or any Adaptations or Collections, You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution ("Attribution Parties") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and (iv) , consistent with Ssection 3(b), in the case of an Adaptation, a credit identifying the use of the Work in the Adaptation (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). The credit required by this Section 4(c) may be implemented in any reasonable manner; provided, however, that in the case of a Adaptation or Collection, at a minimum such credit will appear, if a credit for all contributing authors of the Adaptation or Collection appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this Section for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties. -Except as otherwise agreed in writing by the Licensor or as may be otherwise permitted by applicable law, if You Reproduce, Distribute or Publicly Perform the Work either by itself or as part of any Adaptations or Collections, You must not distort, mutilate, modify or take other derogatory action in relation to the Work which would be prejudicial to the Original Author's honor or reputation. Licensor agrees that in those jurisdictions (e.g. Japan), in which any exercise of the right granted in Section 3(b) of this License (the right to make Adaptations) would be deemed to be a distortion, mutilation, modification or other derogatory action prejudicial to the Original Author's honor and reputation, the Licensor will waive or not assert, as appropriate, this Section, to the fullest extent permitted by the applicable national law, to enable You to reasonably exercise Your right under Section 3(b) of this License (right to make Adaptations) but not otherwise. -5. Representations, Warranties and Disclaimer -UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. -6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. -7. Termination -This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Adaptations or Collections from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License. -Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above. -8. Miscellaneous -Each time You Distribute or Publicly Perform the Work or a Collection, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License. -Each time You Distribute or Publicly Perform an Adaptation, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License. -If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. -No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent. -This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You. -The rights granted under, and the subject matter referenced, in this License were drafted utilizing the terminology of the Berne Convention for the Protection of Literary and Artistic Works (as amended on September 28, 1979), the Rome Convention of 1961, the WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and the Universal Copyright Convention (as revised on July 24, 1971). These rights and subject matter take effect in the relevant jurisdiction in which the License terms are sought to be enforced according to the corresponding provisions of the implementation of those treaty provisions in the applicable national law. If the standard suite of rights granted under applicable copyright law includes additional rights not granted under this License, such additional rights are deemed to be included in the License; this License is not intended to restrict the license of any rights under applicable law. -Creative Commons Notice -Creative Commons is not a party to this License, and makes no warranty whatsoever in connection with the Work. Creative Commons will not be liable to You or any party on any legal theory for any damages whatsoever, including without limitation any general, special, incidental or consequential damages arising in connection to this license. Notwithstanding the foregoing two (2) sentences, if Creative Commons has expressly identified itself as the Licensor hereunder, it shall have all rights and obligations of Licensor. -Except for the limited purpose of indicating to the public that the Work is licensed under the CCPL, Creative Commons does not authorize the use by either party of the trademark "Creative Commons" or any related trademark or logo of Creative Commons without the prior written consent of Creative Commons. Any permitted use will be in compliance with Creative Commons' then-current trademark usage guidelines, as may be published on its website or otherwise made available upon request from time to time. For the avoidance of doubt, this trademark restriction does not form part of the License. -Creative Commons may be contacted at https://creativecommons.org/. -========================================= -END OF Image files from PICOL NOTICES, INFORMATION, AND LICENSE - - diff --git a/build_preparation.bat b/build_preparation.bat index 6ef28ae20..4476d4172 100644 --- a/build_preparation.bat +++ b/build_preparation.bat @@ -28,12 +28,12 @@ if not "%input%" == "yes" goto End echo Setting adapter flavor to GTA powershell -Command "(gc TestAdapterFlavor.props) -replace '>TAfGT<', '>GTA<' | Out-File TestAdapterFlavor.props" -echo Executing T4 scripts -set VisualStudioVersion=15.0 -%MS_BUILD% ResolveTTs.proj +rem echo Executing T4 scripts +rem set VisualStudioVersion=15.0 +rem %MS_BUILD% ResolveTTs.proj -echo Removing TAfGT projects (for now) -powershell -ExecutionPolicy Bypass .\Tools\RemoveProjects.ps1 -flavor GTA +rem echo Removing TAfGT projects (for now) +rem powershell -ExecutionPolicy Bypass .\Tools\RemoveProjects.ps1 -flavor GTA echo Restoring NuGet packages pushd GoogleTestAdapter From 8c703ea448132e2632bcb6a2fcb8af94aaa2b4d2 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sat, 9 Mar 2019 09:57:29 +0100 Subject: [PATCH 35/81] updated OpenCover version --- GoogleTestAdapter/Core.Tests/packages.config | 2 +- GoogleTestAdapter/DiaResolver.Tests/packages.config | 2 +- GoogleTestAdapter/TestAdapter.Tests/packages.config | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/GoogleTestAdapter/Core.Tests/packages.config b/GoogleTestAdapter/Core.Tests/packages.config index 87cac3d92..22cbd61b0 100644 --- a/GoogleTestAdapter/Core.Tests/packages.config +++ b/GoogleTestAdapter/Core.Tests/packages.config @@ -3,7 +3,7 @@ - + diff --git a/GoogleTestAdapter/DiaResolver.Tests/packages.config b/GoogleTestAdapter/DiaResolver.Tests/packages.config index 265e3a75c..22cbd61b0 100644 --- a/GoogleTestAdapter/DiaResolver.Tests/packages.config +++ b/GoogleTestAdapter/DiaResolver.Tests/packages.config @@ -3,7 +3,7 @@ - + diff --git a/GoogleTestAdapter/TestAdapter.Tests/packages.config b/GoogleTestAdapter/TestAdapter.Tests/packages.config index dbf70ba5c..ebde7ba65 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/packages.config +++ b/GoogleTestAdapter/TestAdapter.Tests/packages.config @@ -4,7 +4,7 @@ - + From 6ebd0a885d0dc994a8852c031fabc7fbda0f265a Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sat, 9 Mar 2019 11:06:31 +0100 Subject: [PATCH 36/81] Revert "updated OpenCover version" This reverts commit 8c703ea448132e2632bcb6a2fcb8af94aaa2b4d2. --- GoogleTestAdapter/Core.Tests/packages.config | 2 +- GoogleTestAdapter/DiaResolver.Tests/packages.config | 2 +- GoogleTestAdapter/TestAdapter.Tests/packages.config | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/GoogleTestAdapter/Core.Tests/packages.config b/GoogleTestAdapter/Core.Tests/packages.config index 22cbd61b0..87cac3d92 100644 --- a/GoogleTestAdapter/Core.Tests/packages.config +++ b/GoogleTestAdapter/Core.Tests/packages.config @@ -3,7 +3,7 @@ - + diff --git a/GoogleTestAdapter/DiaResolver.Tests/packages.config b/GoogleTestAdapter/DiaResolver.Tests/packages.config index 22cbd61b0..265e3a75c 100644 --- a/GoogleTestAdapter/DiaResolver.Tests/packages.config +++ b/GoogleTestAdapter/DiaResolver.Tests/packages.config @@ -3,7 +3,7 @@ - + diff --git a/GoogleTestAdapter/TestAdapter.Tests/packages.config b/GoogleTestAdapter/TestAdapter.Tests/packages.config index ebde7ba65..dbf70ba5c 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/packages.config +++ b/GoogleTestAdapter/TestAdapter.Tests/packages.config @@ -4,7 +4,7 @@ - + From 5b3163783a66a54b6a7cae3b0115cde4981bd503 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sat, 9 Mar 2019 16:23:34 +0100 Subject: [PATCH 37/81] removed Show release notes option, new donation buttons --- .../Settings/SettingsWrapperTests.cs | 1 - .../Settings/IGoogleTestAdapterSettings.cs | 2 - .../Core/Settings/SettingsWrapper.cs | 8 -- GoogleTestAdapter/Tests.Common/TestsBase.cs | 1 - .../GoogleTestExtensionOptionsPage.cs | 12 +-- .../OptionsPages/GeneralOptionsDialogPage.cs | 22 ----- .../VsPackage.GTA/ReleaseNotes/Donations.cs | 36 +-------- .../VsPackage.GTA/ReleaseNotes/History.cs | 7 +- .../ReleaseNotes/ReleaseNotesCreator.cs | 14 +--- .../ReleaseNotesDialog.Designer.cs | 80 ++++++++++--------- .../ReleaseNotes/ReleaseNotesDialog.cs | 18 +---- .../VsPackage.GTA/VsPackage.GTA.csproj | 3 - .../GoogleTestExtensionOptionsPage.cs | 1 - 13 files changed, 50 insertions(+), 155 deletions(-) delete mode 100644 GoogleTestAdapter/VsPackage.GTA/OptionsPages/GeneralOptionsDialogPage.cs diff --git a/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs b/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs index deedbb7bf..418eefb03 100644 --- a/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs +++ b/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs @@ -522,7 +522,6 @@ public void ToString_PrintsCorrectly() optionsString.Should().Contain("ParseSymbolInformation: True"); optionsString.Should().Contain("DebugMode: False"); optionsString.Should().Contain("TimestampOutput: False"); - optionsString.Should().Contain("ShowReleaseNotes: True"); optionsString.Should().Contain("AdditionalTestExecutionParam: ''"); optionsString.Should().Contain("BatchForTestSetup: 'C:\\\\myfolder\\myfile.xml'"); optionsString.Should().Contain("BatchForTestTeardown: ''"); diff --git a/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs b/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs index 922264f6b..0534985df 100644 --- a/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs +++ b/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs @@ -42,7 +42,6 @@ public interface IGoogleTestAdapterSettings bool? ParseSymbolInformation { get; set; } bool? DebugMode { get; set; } bool? TimestampOutput { get; set; } - bool? ShowReleaseNotes { get; set; } bool? KillProcessesOnCancel { get; set; } bool? SkipOriginCheck { get; set; } string ExitCodeTestCase { get; set; } @@ -83,7 +82,6 @@ public static void GetUnsetValuesFrom(this IGoogleTestAdapterSettings self, IGoo self.ParseSymbolInformation = self.ParseSymbolInformation ?? other.ParseSymbolInformation; self.DebugMode = self.DebugMode ?? other.DebugMode; self.TimestampOutput = self.TimestampOutput ?? other.TimestampOutput; - self.ShowReleaseNotes = self.ShowReleaseNotes ?? other.ShowReleaseNotes; self.KillProcessesOnCancel = self.KillProcessesOnCancel ?? other.KillProcessesOnCancel; self.SkipOriginCheck = self.SkipOriginCheck ?? other.SkipOriginCheck; self.ExitCodeTestCase = self.ExitCodeTestCase ?? other.ExitCodeTestCase; diff --git a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs index 04cd72f65..23a5956a6 100644 --- a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs +++ b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs @@ -482,14 +482,6 @@ public virtual List TraitsRegexesAfter public virtual bool TimestampOutput => _currentSettings.TimestampOutput ?? OptionTimestampOutputDefaultValue; - public const string OptionShowReleaseNotes = "Show release notes after update"; - public const bool OptionShowReleaseNotesDefaultValue = true; - public const string OptionShowReleaseNotesDescription = - "If true, a dialog with release notes is shown after the extension has been updated."; - - public virtual bool ShowReleaseNotes => _currentSettings.ShowReleaseNotes ?? OptionShowReleaseNotesDefaultValue; - - public const string OptionAdditionalTestExecutionParams = "Additional test execution parameters"; public const string OptionAdditionalTestExecutionParamsDefaultValue = ""; public const string OptionAdditionalTestExecutionParamsDescription = diff --git a/GoogleTestAdapter/Tests.Common/TestsBase.cs b/GoogleTestAdapter/Tests.Common/TestsBase.cs index 00100701f..96bd82639 100644 --- a/GoogleTestAdapter/Tests.Common/TestsBase.cs +++ b/GoogleTestAdapter/Tests.Common/TestsBase.cs @@ -80,7 +80,6 @@ public static void SetupOptions(Mock mockOptions) mockOptions.Setup(o => o.ParseSymbolInformation).Returns(SettingsWrapper.OptionParseSymbolInformationDefaultValue); mockOptions.Setup(o => o.DebugMode).Returns(SettingsWrapper.OptionDebugModeDefaultValue); mockOptions.Setup(o => o.TimestampOutput).Returns(SettingsWrapper.OptionTimestampOutputDefaultValue); - mockOptions.Setup(o => o.ShowReleaseNotes).Returns(SettingsWrapper.OptionShowReleaseNotesDefaultValue); mockOptions.Setup(o => o.AdditionalTestExecutionParam) .Returns(SettingsWrapper.OptionAdditionalTestExecutionParamsDefaultValue); mockOptions.Setup(o => o.BatchForTestSetup).Returns(SettingsWrapper.OptionBatchForTestSetupDefaultValue); diff --git a/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs index c55eb1689..219932549 100644 --- a/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs @@ -50,12 +50,9 @@ private void TryDisplayReleaseNotesIfNecessary() versionProvider.UpdateLastVersion(); - //if ((_generalOptions.ShowReleaseNotes || History.ForceShowReleaseNotes(formerlyInstalledVersion)) && - // (formerlyInstalledVersion == null || formerlyInstalledVersion < currentVersion)) if (formerlyInstalledVersion == null || formerlyInstalledVersion < currentVersion) { - var creator = new ReleaseNotesCreator(formerlyInstalledVersion, currentVersion, - Donations.IsPreDonationsVersion(formerlyInstalledVersion)); + var creator = new ReleaseNotesCreator(formerlyInstalledVersion, currentVersion); DisplayReleaseNotes(creator.CreateHtml()); } } @@ -70,18 +67,13 @@ private void DisplayReleaseNotes(string html) using (var dialog = new ReleaseNotesDialog { - HtmlFile = new Uri($"file://{htmlFile}"), - ShowReleaseNotesChecked = _generalOptions.ShowReleaseNotes + HtmlFile = new Uri($"file://{htmlFile}") }) { dialog.AddExternalUri(Donations.Uri); - dialog.ShowReleaseNotesChanged += - (sender, args) => _generalOptions.ShowReleaseNotes = args.ShowReleaseNotes; dialog.Closed += (sender, args) => File.Delete(htmlFile); dialog.ShowDialog(); } } - - private bool ShowReleaseNotes => _generalOptions.ShowReleaseNotes; } } diff --git a/GoogleTestAdapter/VsPackage.GTA/OptionsPages/GeneralOptionsDialogPage.cs b/GoogleTestAdapter/VsPackage.GTA/OptionsPages/GeneralOptionsDialogPage.cs deleted file mode 100644 index 38f3e75e3..000000000 --- a/GoogleTestAdapter/VsPackage.GTA/OptionsPages/GeneralOptionsDialogPage.cs +++ /dev/null @@ -1,22 +0,0 @@ -// This file has been modified by Microsoft on 6/2017. - -using GoogleTestAdapter.Settings; -using System.ComponentModel; - -namespace GoogleTestAdapter.VsPackage.OptionsPages -{ - - public partial class GeneralOptionsDialogPage : NotifyingDialogPage - { - [Category(SettingsWrapper.CategoryMiscName)] - [DisplayName(SettingsWrapper.OptionShowReleaseNotes)] - [Description(SettingsWrapper.OptionShowReleaseNotesDescription)] - public bool ShowReleaseNotes - { - get { return _showReleaseNotes; } - set { SetAndNotify(ref _showReleaseNotes, value); } - } - private bool _showReleaseNotes = SettingsWrapper.OptionShowReleaseNotesDefaultValue; - } - -} \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/Donations.cs b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/Donations.cs index ac70ff074..fc8f4a2b8 100644 --- a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/Donations.cs +++ b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/Donations.cs @@ -4,45 +4,11 @@ namespace GoogleTestAdapter.VsPackage.GTA.ReleaseNotes { public static class Donations { - public static readonly Version Version = new Version(0, 13, 0); public static readonly Uri Uri = new Uri("https://github.com/csoltenborn/GoogleTestAdapter#donations"); - public const string Note = @"On my own account: -In the last couple of months, I noticed that my private laptop certainly has a finite lifetime. Thinking about the requirements a new one has to stand up to, I realized that developing and supporting Google Test Adapter has in the last years been one of the major use cases of that laptop. Thus, I decided to take this as reason for from now on accepting donations :-) - -Therefore, if you would like to appreciate development and support of Google Test Adapter, please consider to [donate!](https://github.com/csoltenborn/GoogleTestAdapter#donations) Thanks in advance... -
-
-Update (2/24/2019): This is most likely the final version with support for VS2012. No more donations so far - I guess I have reached my potential (allthough not my donation goals), so I'm not going to annoy you any further. Thanks once more to the donators - I've really appreciated it! -
-
-Update (2/5/2019): I have again received some (and quite generous) donations - thanks a lot to Treb and Sebastian! Still not at my donation goal, though... If you happen to work with GTA in a professional manner (e.g. in a company which uses GTA to execute the C++ tests, be it within Visual Studio or on the build server), may I ask you to reconsider donating? If you need some more motivation, note that my birthday was just a couple of days ago ;-) -
-
-Update (12/16/2019): Welcome again to my donation weekly soap :-) Responds to my last request for donations were quite a bit better and included some rather generous ones, but still a way to go until my donation goals are met. Thanks a lot to Yehuda, Walter, Thomas, Lewis, Greg, and my colleague Benedikt! I loved to hear that GTA just works for you and is indeed quite helpful. -
-
-Update (12/09/2018): Given the fact that I have a couple of thousands users, I must admit that I have been unpleasantly surprised by the amount of donations I received (thanks, Tim and -Arne! I appreciate it more than you might imagine). Thus, I have decided to disable the Do not show release notes option until I have reached my donation goals (sorry for this, Tim and Arne). Please consider to [donate](https://github.com/csoltenborn/GoogleTestAdapter#donations) - and note that Christmas is pretty close ;-) + public static readonly string Header = $@"
Please consider to donate!


"; - - public const string Footer = @" -
-
-" + ConsiderDonating; - - public const string Header = ConsiderDonating + @" -
-
-"; - - private const string ConsiderDonating = @"
Please consider to donate!
"; - - public static bool IsPreDonationsVersion(Version formerVersion) - { - return formerVersion == null || formerVersion < Version; - } } } \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/History.cs b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/History.cs index 2b25e1d76..b7e0a57cf 100644 --- a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/History.cs +++ b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/History.cs @@ -56,7 +56,7 @@ static History() { new Version(0, 12, 1), new DateTime(2017, 11, 16) }, { new Version(0, 12, 2), new DateTime(2017, 12, 6) }, { new Version(0, 12, 3), new DateTime(2017, 12, 9) }, - { Donations.Version, new DateTime(2018, 6, 25) }, + { new Version(0, 13, 0), new DateTime(2018, 6, 25) }, { new Version(0, 13, 1), new DateTime(2018, 6, 26) }, { new Version(0, 13, 2), new DateTime(2018, 7, 3) }, { new Version(0, 13, 3), new DateTime(2018, 7, 16) }, @@ -68,11 +68,6 @@ static History() { new Version(0, 14, 4), new DateTime(2019, 2, 24) } }; } - - public static bool ForceShowReleaseNotes(Version formerVersion) - { - return Donations.IsPreDonationsVersion(formerVersion); - } } } \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesCreator.cs b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesCreator.cs index 1c423eebc..df48ec380 100644 --- a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesCreator.cs +++ b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesCreator.cs @@ -11,13 +11,11 @@ public class ReleaseNotesCreator private readonly Version _formerlyInstalledVersion; private readonly Version _currentVersion; - private readonly bool _showMainDonationNote; - public ReleaseNotesCreator(Version formerlyInstalledVersion, Version currentVersion, bool showMainDonationNote = false) + public ReleaseNotesCreator(Version formerlyInstalledVersion, Version currentVersion) { _formerlyInstalledVersion = formerlyInstalledVersion; _currentVersion = currentVersion; - _showMainDonationNote = showMainDonationNote; } private string CreateMarkdown() @@ -27,11 +25,6 @@ private string CreateMarkdown() string releaseNotes = Donations.Header; - //if (_showMainDonationNote) - //{ - releaseNotes += Donations.Note; - //} - releaseNotes += CreateHeader(); int startIndex = Array.IndexOf(Versions, _currentVersion); @@ -41,11 +34,6 @@ private string CreateMarkdown() releaseNotes += CreateEntry(Versions[i]); } - //if (!_showMainDonationNote) - //{ - releaseNotes += Donations.Footer; - //} - return releaseNotes; } diff --git a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesDialog.Designer.cs b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesDialog.Designer.cs index 5865ed48a..2dc2d7388 100644 --- a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesDialog.Designer.cs +++ b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesDialog.Designer.cs @@ -36,9 +36,9 @@ private void InitializeComponent() this.ForwardButton = new System.Windows.Forms.Button(); this.WebBrowser = new System.Windows.Forms.WebBrowser(); this.OkButtonPanel = new System.Windows.Forms.TableLayoutPanel(); - this.ShowReleaseNotesCheckBox = new System.Windows.Forms.CheckBox(); this.OkButton = new System.Windows.Forms.Button(); this.toolTip = new System.Windows.Forms.ToolTip(this.components); + this.DonateButton = new System.Windows.Forms.Button(); this.RootPanel.SuspendLayout(); this.NavigationPanel.SuspendLayout(); this.OkButtonPanel.SuspendLayout(); @@ -54,13 +54,14 @@ private void InitializeComponent() this.RootPanel.Controls.Add(this.OkButtonPanel, 0, 2); this.RootPanel.Dock = System.Windows.Forms.DockStyle.Fill; this.RootPanel.Location = new System.Drawing.Point(0, 0); + this.RootPanel.Margin = new System.Windows.Forms.Padding(7, 7, 7, 7); this.RootPanel.Name = "RootPanel"; this.RootPanel.RowCount = 3; this.RootPanel.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.RootPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.RootPanel.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.RootPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); - this.RootPanel.Size = new System.Drawing.Size(784, 561); + this.RootPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 45F)); + this.RootPanel.Size = new System.Drawing.Size(1829, 1251); this.RootPanel.TabIndex = 0; // // NavigationPanel @@ -70,18 +71,20 @@ private void InitializeComponent() this.NavigationPanel.Controls.Add(this.BackButton); this.NavigationPanel.Controls.Add(this.ForwardButton); this.NavigationPanel.Dock = System.Windows.Forms.DockStyle.Fill; - this.NavigationPanel.Location = new System.Drawing.Point(3, 3); + this.NavigationPanel.Location = new System.Drawing.Point(7, 7); + this.NavigationPanel.Margin = new System.Windows.Forms.Padding(7, 7, 7, 7); this.NavigationPanel.Name = "NavigationPanel"; - this.NavigationPanel.Size = new System.Drawing.Size(778, 29); + this.NavigationPanel.Size = new System.Drawing.Size(1815, 65); this.NavigationPanel.TabIndex = 3; // // BackButton // this.BackButton.AccessibleName = "Go back"; this.BackButton.Enabled = false; - this.BackButton.Location = new System.Drawing.Point(3, 3); + this.BackButton.Location = new System.Drawing.Point(7, 7); + this.BackButton.Margin = new System.Windows.Forms.Padding(7, 7, 7, 7); this.BackButton.Name = "BackButton"; - this.BackButton.Size = new System.Drawing.Size(23, 23); + this.BackButton.Size = new System.Drawing.Size(54, 51); this.BackButton.TabIndex = 0; this.BackButton.Text = "<"; this.BackButton.UseVisualStyleBackColor = true; @@ -90,9 +93,10 @@ private void InitializeComponent() // this.ForwardButton.AccessibleName = "Go forward"; this.ForwardButton.Enabled = false; - this.ForwardButton.Location = new System.Drawing.Point(32, 3); + this.ForwardButton.Location = new System.Drawing.Point(75, 7); + this.ForwardButton.Margin = new System.Windows.Forms.Padding(7, 7, 7, 7); this.ForwardButton.Name = "ForwardButton"; - this.ForwardButton.Size = new System.Drawing.Size(23, 23); + this.ForwardButton.Size = new System.Drawing.Size(54, 51); this.ForwardButton.TabIndex = 1; this.ForwardButton.Text = ">"; this.ForwardButton.UseVisualStyleBackColor = true; @@ -104,11 +108,12 @@ private void InitializeComponent() this.RootPanel.SetColumnSpan(this.WebBrowser, 2); this.WebBrowser.Dock = System.Windows.Forms.DockStyle.Fill; this.WebBrowser.IsWebBrowserContextMenuEnabled = false; - this.WebBrowser.Location = new System.Drawing.Point(3, 38); - this.WebBrowser.MinimumSize = new System.Drawing.Size(20, 20); + this.WebBrowser.Location = new System.Drawing.Point(7, 86); + this.WebBrowser.Margin = new System.Windows.Forms.Padding(7, 7, 7, 7); + this.WebBrowser.MinimumSize = new System.Drawing.Size(47, 45); this.WebBrowser.Name = "WebBrowser"; this.WebBrowser.ScriptErrorsSuppressed = true; - this.WebBrowser.Size = new System.Drawing.Size(778, 485); + this.WebBrowser.Size = new System.Drawing.Size(1815, 1079); this.WebBrowser.TabIndex = 0; this.WebBrowser.WebBrowserShortcutsEnabled = false; this.WebBrowser.Navigating += new System.Windows.Forms.WebBrowserNavigatingEventHandler(this.WebBrowser_Navigating); @@ -117,55 +122,57 @@ private void InitializeComponent() // this.OkButtonPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); this.OkButtonPanel.AutoSize = true; - this.OkButtonPanel.ColumnCount = 3; + this.OkButtonPanel.ColumnCount = 2; this.RootPanel.SetColumnSpan(this.OkButtonPanel, 2); this.OkButtonPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); this.OkButtonPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); - this.OkButtonPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); - this.OkButtonPanel.Controls.Add(this.ShowReleaseNotesCheckBox, 0, 0); + this.OkButtonPanel.Controls.Add(this.DonateButton, 0, 0); this.OkButtonPanel.Controls.Add(this.OkButton, 1, 0); - this.OkButtonPanel.Location = new System.Drawing.Point(3, 529); + this.OkButtonPanel.Location = new System.Drawing.Point(7, 1179); + this.OkButtonPanel.Margin = new System.Windows.Forms.Padding(7, 7, 7, 7); this.OkButtonPanel.Name = "OkButtonPanel"; this.OkButtonPanel.RowCount = 1; this.OkButtonPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.OkButtonPanel.Size = new System.Drawing.Size(778, 29); + this.OkButtonPanel.Size = new System.Drawing.Size(1815, 65); this.OkButtonPanel.TabIndex = 4; // - // ShowReleaseNotesCheckBox - // - this.ShowReleaseNotesCheckBox.AccessibleName = "Show release notes after extension has been updated"; - this.ShowReleaseNotesCheckBox.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.ShowReleaseNotesCheckBox.AutoSize = true; - this.ShowReleaseNotesCheckBox.Location = new System.Drawing.Point(3, 6); - this.ShowReleaseNotesCheckBox.Name = "ShowReleaseNotesCheckBox"; - this.ShowReleaseNotesCheckBox.Size = new System.Drawing.Size(179, 17); - this.ShowReleaseNotesCheckBox.TabIndex = 1; - this.ShowReleaseNotesCheckBox.Text = "Show release notes after update"; - this.toolTip.SetToolTip(this.ShowReleaseNotesCheckBox, "Ignored until donation goals are achieved (sorry to donators)"); - this.ShowReleaseNotesCheckBox.UseVisualStyleBackColor = true; - // // OkButton // this.OkButton.AccessibleName = "Close release notes dialog"; this.OkButton.Anchor = System.Windows.Forms.AnchorStyles.None; - this.OkButton.Location = new System.Drawing.Point(351, 3); + this.OkButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.OkButton.Location = new System.Drawing.Point(1273, 7); + this.OkButton.Margin = new System.Windows.Forms.Padding(7, 7, 7, 7); this.OkButton.Name = "OkButton"; - this.OkButton.Size = new System.Drawing.Size(75, 23); + this.OkButton.Size = new System.Drawing.Size(175, 51); this.OkButton.TabIndex = 2; - this.OkButton.Text = "OK"; + this.OkButton.Text = "Whatever..."; this.OkButton.UseVisualStyleBackColor = true; // + // DonateButton + // + this.DonateButton.AccessibleName = "Close release notes dialog"; + this.DonateButton.Anchor = System.Windows.Forms.AnchorStyles.None; + this.DonateButton.Location = new System.Drawing.Point(303, 7); + this.DonateButton.Margin = new System.Windows.Forms.Padding(7); + this.DonateButton.Name = "DonateButton"; + this.DonateButton.Size = new System.Drawing.Size(301, 51); + this.DonateButton.TabIndex = 3; + this.DonateButton.Text = "Cool - I want to donate!"; + this.DonateButton.UseVisualStyleBackColor = true; + // // ReleaseNotesDialog // this.AcceptButton = this.OkButton; this.AccessibleName = "Release notes of Google Test Adapter"; - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleDimensions = new System.Drawing.SizeF(14F, 29F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.CancelButton = this.OkButton; this.CausesValidation = false; - this.ClientSize = new System.Drawing.Size(784, 561); + this.ClientSize = new System.Drawing.Size(1829, 1251); this.Controls.Add(this.RootPanel); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Margin = new System.Windows.Forms.Padding(7, 7, 7, 7); this.Name = "ReleaseNotesDialog"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "Google Test Adapter: Release notes"; @@ -173,7 +180,6 @@ private void InitializeComponent() this.RootPanel.PerformLayout(); this.NavigationPanel.ResumeLayout(false); this.OkButtonPanel.ResumeLayout(false); - this.OkButtonPanel.PerformLayout(); this.ResumeLayout(false); } @@ -182,12 +188,12 @@ private void InitializeComponent() private System.Windows.Forms.TableLayoutPanel RootPanel; private System.Windows.Forms.WebBrowser WebBrowser; - private System.Windows.Forms.CheckBox ShowReleaseNotesCheckBox; private System.Windows.Forms.Button OkButton; private System.Windows.Forms.FlowLayoutPanel NavigationPanel; private System.Windows.Forms.Button BackButton; private System.Windows.Forms.Button ForwardButton; private System.Windows.Forms.TableLayoutPanel OkButtonPanel; private System.Windows.Forms.ToolTip toolTip; + private System.Windows.Forms.Button DonateButton; } } \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesDialog.cs b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesDialog.cs index 6f6b1b5c6..9eb8266ce 100644 --- a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesDialog.cs +++ b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesDialog.cs @@ -2,18 +2,12 @@ using System.Collections.Generic; using System.Diagnostics; using System.Windows.Forms; +using GoogleTestAdapter.VsPackage.GTA.ReleaseNotes; namespace GoogleTestAdapter.VsPackage.ReleaseNotes { public partial class ReleaseNotesDialog : Form { - internal class ShowReleaseNotesChangedEventArgs : EventArgs - { - internal bool ShowReleaseNotes { get; set; } - } - - internal event EventHandler ShowReleaseNotesChanged; - private readonly ISet _externalUris = new HashSet(); public ReleaseNotesDialog() @@ -26,10 +20,8 @@ public ReleaseNotesDialog() WebBrowser.CanGoForwardChanged += (sender, args) => ForwardButton.Enabled = WebBrowser.CanGoForward; ForwardButton.Click += (sender, args) => WebBrowser.GoForward(); - ShowReleaseNotesCheckBox.CheckedChanged += - (sender, args) => ShowReleaseNotesChanged?.Invoke(this, new ShowReleaseNotesChangedEventArgs { ShowReleaseNotes = ShowReleaseNotesCheckBox.Checked }); - OkButton.Click += (sender, args) => Close(); + DonateButton.Click += (sender, args) => OpenUriInDefaultBrowser(Donations.Uri); } internal Uri HtmlFile @@ -38,12 +30,6 @@ internal Uri HtmlFile set => WebBrowser.Url = value; } - internal bool ShowReleaseNotesChecked - { - get => ShowReleaseNotesCheckBox.Checked; - set => ShowReleaseNotesCheckBox.Checked = value; - } - internal void AddExternalUri(Uri externalUri) { _externalUris.Add(externalUri); diff --git a/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj b/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj index b03f202d0..0f3ed9ee8 100644 --- a/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj +++ b/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj @@ -73,9 +73,6 @@ - - Component - diff --git a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs index 7ff617f76..91b5ac02f 100644 --- a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs @@ -235,7 +235,6 @@ private RunSettings GetRunSettingsFromOptionPages() ParseSymbolInformation = _generalOptions.ParseSymbolInformation, DebugMode = _generalOptions.DebugMode, TimestampOutput = _generalOptions.TimestampOutput, - ShowReleaseNotes = ShowReleaseNotes, AdditionalTestExecutionParam = _generalOptions.AdditionalTestExecutionParams, BatchForTestSetup = _generalOptions.BatchForTestSetup, BatchForTestTeardown = _generalOptions.BatchForTestTeardown, From 57d3d2abb1bbf60c0e75c1099dc7eb518ec0a743 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sat, 9 Mar 2019 19:19:14 +0100 Subject: [PATCH 38/81] refactoring --- .../LeakCheckTests/gta_leak_detection.cpp | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/SampleTests/LeakCheckTests/gta_leak_detection.cpp b/SampleTests/LeakCheckTests/gta_leak_detection.cpp index c965b4c5e..6be4a20cb 100644 --- a/SampleTests/LeakCheckTests/gta_leak_detection.cpp +++ b/SampleTests/LeakCheckTests/gta_leak_detection.cpp @@ -13,10 +13,10 @@ See https://github.com/csoltenborn/GoogleTestAdapter#evaluating-the-test-executa // based on code provided by https://github.com/alfredskpoon (see https://github.com/csoltenborn/GoogleTestAdapter/issues/266) namespace gta_leak_detection { - bool _isRunByGta = false; - int _resultOfRunAllTests = -1; + bool is_run_by_gta = false; + int result_of_run_all_tests = -1; - class EnableLeakCheck + class EnableLeakCheck // NOLINT(hicpp-special-member-functions, cppcoreguidelines-special-member-functions) { public: static void Initialize() @@ -24,7 +24,8 @@ namespace gta_leak_detection static EnableLeakCheck leakReporter; } private: - EnableLeakCheck() {} + EnableLeakCheck() = default; + ~EnableLeakCheck() // NOLINT(bugprone-exception-escape) { _CrtDumpMemoryLeaks(); @@ -71,11 +72,9 @@ namespace gta_leak_detection std::wcout << std::wstring(message); // TODO remove if gtest "memory leaks" have been fixed - if (_resultOfRunAllTests != 0) + if (result_of_run_all_tests != 0 && is_run_by_gta) { - if (_isRunByGta) - std::cout << "GTA_EXIT_CODE_SKIP\n"; - + std::cout << "GTA_EXIT_CODE_SKIP\n"; std::cout << "\nTest result is 'Skipped' due to some weaknesses of Google Test 1.8.1 and crtdbg.h: leak detection results are only reliable if at least one real test is executed, and if all executed tests have passed.\n\n"; } @@ -123,20 +122,20 @@ namespace gta_leak_detection int PerformLeakDetection(int argc, char** argv, int resultOfRunAllTests) { - _resultOfRunAllTests = resultOfRunAllTests; + result_of_run_all_tests = resultOfRunAllTests; std::string option("-is_run_by_gta"); for (int i = 0; i < argc; i++) { if (strncmp(argv[i], option.c_str(), strlen(option.c_str())) == 0) { - _isRunByGta = true; + is_run_by_gta = true; break; } } // use the rest of the output as message of exit code test - if (_isRunByGta) + if (is_run_by_gta) std::cout << "GTA_EXIT_CODE_OUTPUT_BEGIN\n"; // exit point 3 @@ -144,13 +143,13 @@ namespace gta_leak_detection // this exit is thus taken only if compiled with Release configuration // since test outcome is Skipped in this case, we can just return the result of RUN_ALL_TESTS() #ifndef _DEBUG - if (_isRunByGta) + if (is_run_by_gta) { std::cout << "GTA_EXIT_CODE_SKIP\n"; std::cout << "Memory leak detection is only performed if compiled with Debug configuration.\n"; } #endif - return _resultOfRunAllTests; + return result_of_run_all_tests; } } From f6217cf75c7c8b726971364bb12d0145cc202c58 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sat, 9 Mar 2019 19:19:40 +0100 Subject: [PATCH 39/81] preparing release --- GoogleTestAdapter/Packaging.GTA/VsPackage.nuspec | 2 +- .../VsPackage.GTA/ReleaseNotes/History.cs | 4 ++-- .../VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md | 5 +++++ .../VsPackage.GTA/VsPackage.GTA.csproj | 3 +++ README.md | 14 ++++++++------ appveyor.yml | 2 +- 6 files changed, 20 insertions(+), 10 deletions(-) create mode 100644 GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md diff --git a/GoogleTestAdapter/Packaging.GTA/VsPackage.nuspec b/GoogleTestAdapter/Packaging.GTA/VsPackage.nuspec index e93874d28..680add415 100644 --- a/GoogleTestAdapter/Packaging.GTA/VsPackage.nuspec +++ b/GoogleTestAdapter/Packaging.GTA/VsPackage.nuspec @@ -2,7 +2,7 @@ GoogleTestAdapter - 0.14.4 + 0.15.0 Google Test Adapter Christian Soltenborn Christian Soltenborn diff --git a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/History.cs b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/History.cs index b7e0a57cf..a76214905 100644 --- a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/History.cs +++ b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/History.cs @@ -3,7 +3,6 @@ using System.IO; using System.Linq; using System.Reflection; -using GoogleTestAdapter.VsPackage.GTA.ReleaseNotes; namespace GoogleTestAdapter.VsPackage.ReleaseNotes { @@ -65,7 +64,8 @@ static History() { new Version(0, 14, 1), new DateTime(2018, 12, 10) }, { new Version(0, 14, 2), new DateTime(2018, 12, 16) }, { new Version(0, 14, 3), new DateTime(2019, 2, 5) }, - { new Version(0, 14, 4), new DateTime(2019, 2, 24) } + { new Version(0, 14, 4), new DateTime(2019, 2, 24) }, + { new Version(0, 15, 0), new DateTime(2019, 3, 9) } }; } } diff --git a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md new file mode 100644 index 000000000..d73a61def --- /dev/null +++ b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md @@ -0,0 +1,5 @@ +Changes in this version: +* enhancement: setting the new option [*Exit code test name*](https://github.com/csoltenborn/GoogleTestAdapter#evaluating_exit_code) results in an additional test per test executable that passes if the executable's exit code is 0, and fails otherwise. Additionally, GTA parses the test executable's output for certain [tokens](https://github.com/csoltenborn/GoogleTestAdapter#evaluating_exit_code_tokens) which allow to influence the test's outcome and message. One interesting use case for this is memory leak detection; a complete, reusable [example](https://github.com/csoltenborn/GoogleTestAdapter#evaluating_exit_code_leak_example) is provided as part of GTA's [SampleTests solution](https://github.com/csoltenborn/GoogleTestAdapter/tree/master/SampleTests) ([#266](https://github.com/csoltenborn/GoogleTestAdapter/issues/266), thanks to [alfredskpoon](https://github.com/alfredskpoon) for report, example code, and testing) +* enhancement: the GTA extension is now loaded asynchronically by Visual Studio; the drawback is that support for Visual Studio 2012 had to be dropped ([#243](https://github.com/csoltenborn/GoogleTestAdapter/issues/243)) +* enhancement: the *Show release notes* option has been removed, and this release notes dialog has been slightly changed and now has very funny buttons ([#270](https://github.com/csoltenborn/GoogleTestAdapter/issues/270)) +* donations: thanks, John - I appreciate it! \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj b/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj index 0f3ed9ee8..826c1b93f 100644 --- a/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj +++ b/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj @@ -227,6 +227,9 @@ PreserveNewest + + PreserveNewest +
diff --git a/README.md b/README.md index bcd1a7206..3f8dc20c6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [![Build status](https://ci.appveyor.com/api/projects/status/8hdgmdy1ogqi606j/branch/master?svg=true)](https://ci.appveyor.com/project/csoltenborn/googletestadapter-u1cxh/branch/master) [![Code coverage](https://codecov.io/gh/csoltenborn/GoogleTestAdapter/branch/master/graph/badge.svg)](https://codecov.io/gh/csoltenborn/GoogleTestAdapter) -[![Visual Studio Marketplace downloads](https://img.shields.io/badge/vs_marketplace-117k-blue.svg)](https://marketplace.visualstudio.com/items?itemName=ChristianSoltenborn.GoogleTestAdapter) +[![Visual Studio Marketplace downloads](https://img.shields.io/badge/vs_marketplace-121k-blue.svg)](https://marketplace.visualstudio.com/items?itemName=ChristianSoltenborn.GoogleTestAdapter) [![NuGet downloads](https://img.shields.io/nuget/dt/GoogleTestAdapter.svg?colorB=0c7dbe&label=nuget)](https://www.nuget.org/packages/GoogleTestAdapter) @@ -39,6 +39,8 @@ Google Test Adapter (GTA) is a Visual Studio extension providing test discovery In the last couple of months, I noticed that my private laptop certainly has a finite lifetime. Thinking about the requirements a new one has to stand up to, I realized that developing and supporting *Google Test Adapter* has in the last years been one of the major use cases of that laptop. Thus, I decided to take this as reason for from now on accepting donations :-) +Update: In the meantime, I have received a few donations, and some rather generous ones (thanks again to everybody - the new laptop is great :-) ), but since I'm still quite far away from my original donation goal of collecting half of the laptop's price, I will leave this section as is. + Therefore, if you would like to appreciate development and support of *Google Test Adapter*, **please consider to donate!** [![Donate to Google Test Adapter](https://www.paypalobjects.com/en_US/DE/i/btn/btn_donateCC_LG.gif "Donate to Google Test Adapter")](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YWJX68LZWGN5S) @@ -50,14 +52,14 @@ Please note that I will see your donations as appreciation of my work so far and #### Installation -[![Download from Visual Studio Marketplace](https://img.shields.io/badge/vs_marketplace-v0.14.4-blue.svg)](https://marketplace.visualstudio.com/items?itemName=ChristianSoltenborn.GoogleTestAdapter) +[![Download from Visual Studio Marketplace](https://img.shields.io/badge/vs_marketplace-v0.15.0-blue.svg)](https://marketplace.visualstudio.com/items?itemName=ChristianSoltenborn.GoogleTestAdapter) [![Download from NuGet](https://img.shields.io/nuget/vpre/GoogleTestAdapter.svg?colorB=0c7dbe&label=nuget)](https://www.nuget.org/packages/GoogleTestAdapter) [![Download from GitHub](https://img.shields.io/github/release/csoltenborn/GoogleTestAdapter/all.svg?colorB=0c7dbe&label=github)](https://github.com/csoltenborn/GoogleTestAdapter/releases) Google Test Adapter can be installed in three ways: * Install through the Visual Studio Marketplace at *Tools/Extensions and Updates* - search for *Google Test Adapter*. -* Download and launch the VSIX installer from either the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=ChristianSoltenborn.GoogleTestAdapter) or [GitHub](https://github.com/csoltenborn/GoogleTestAdapter/releases/download/v0.14.4/GoogleTestAdapter-0.14.4.vsix) +* Download and launch the VSIX installer from either the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=ChristianSoltenborn.GoogleTestAdapter) or [GitHub](https://github.com/csoltenborn/GoogleTestAdapter/releases/download/v0.15.0/GoogleTestAdapter-0.15.0.vsix) * Add a NuGet dependency to the [Google test adapter nuget package](https://www.nuget.org/packages/GoogleTestAdapter/) to your Google Test projects. Note, however, that Visual Studio integration is limited this way: VS can discover and run tests, but no debugging, options or toolbar will be available; configuration is only possible through solution config files (see below). After restarting VS, your tests will be displayed in the Test Explorer at build completion time. If no or not all tests show up, have a look at the [trouble shooting section](#trouble_shooting). @@ -110,7 +112,7 @@ Note that traits are assigned in an additive manner within each phase, and in an #### Evaluating the test executable's exit code If option *Exit code test case* is non-empty, an additional test case will be generated per text executable (referred to as *exit code test* in the following), and that exit code test will pass if the test executable's exit code is 0. This allows to reflect some additional result as a test case; for instance, the test executable might be built such that it performs memory leak detection at shutdown (see below for [example](#evaluating_exit_code_leak_example)); the result of that check can then be seen within VS as the result of the according additional test. -A couple of tokens can used as part of a test executable's output; if GTA sees theses tokens, it will act accordingly: +A couple of tokens can used as part of a test executable's output; if GTA sees theses tokens, it will act accordingly: * `GTA_EXIT_CODE_OUTPUT_BEGIN`: This token will make GTA capture the following output and add it to the exit code test as error message. * `GTA_EXIT_CODE_OUTPUT_END`: This token will stop GTA from adding the following output to the error message. If it is not provided, GTA will capture the complete remaining output as error message of the exit code test. * `GTA_EXIT_CODE_SKIP`: This token will make the exit code test have outcome *Skipped*. This can e.g. be useful if a particular check is only perfomed in Debug mode, or to provide a general warning that something has gone wrong without making the exit code test fail. @@ -126,8 +128,8 @@ Note that a test executable might be run more than once by GTA (e.g., if tests a ##### Example usage: Memory leak detection An example usage of the *Exit code test case* can be found as part of the SampleTests solution: [Project *MemoryLeakTests*](https://github.com/csoltenborn/GoogleTestAdapter/tree/master/SampleTests/MemoryLeakTests) makes use of MS' memory leak detection facilities and reports the results to VS via an exit code test. The approach can easily be re-used for other Google Test projects: -* add files `gta_leak_detection.h` and `gta_leak_detection.cpp` to the project -* in the project's `main` method, return the result of `gta_leak_detection::PerformLeakDetection(argc, argv, RUN_ALL_TESTS())` (instead of the result of `RUN_ALL_TESTS()`) +* add files [`gta_leak_detection.h`](https://github.com/csoltenborn/GoogleTestAdapter/tree/master/SampleTests/LeakCheckTests/gta_leak_detection.h) and [`gta_leak_detection.cpp`](https://github.com/csoltenborn/GoogleTestAdapter/tree/master/SampleTests/LeakCheckTests/gta_leak_detection.cpp) to the project +* in the project's `main` method, return the result of `gta_leak_detection::PerformLeakDetection(argc, argv, RUN_ALL_TESTS())` (instead of the result of `RUN_ALL_TESTS()`, see [example](https://github.com/csoltenborn/GoogleTestAdapter/tree/master/SampleTests/LeakCheckTests/main.cpp)) * set the following GTA options (probably through the settings file): * `MemoryLeakTest` (enables evaluation of the executable's exit code; feel free to choose another name) * `-is_run_by_gta` (makes sure the test executable is aware of being run by GTA) diff --git a/appveyor.yml b/appveyor.yml index 7a9406204..51bd6dfbe 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 0.14.4.{build} +version: 0.15.0.{build} os: - Visual Studio 2017 configuration: Release From 3c8c94688ddb09f778d7728970f82c4b31048e0b Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sun, 10 Mar 2019 12:54:55 +0100 Subject: [PATCH 40/81] fixed solution startup project --- GoogleTestAdapter/Packaging.GTA/Packaging.GTA.csproj | 5 +++++ GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj | 5 ----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/GoogleTestAdapter/Packaging.GTA/Packaging.GTA.csproj b/GoogleTestAdapter/Packaging.GTA/Packaging.GTA.csproj index 6f54a09c0..c450a8e8e 100644 --- a/GoogleTestAdapter/Packaging.GTA/Packaging.GTA.csproj +++ b/GoogleTestAdapter/Packaging.GTA/Packaging.GTA.csproj @@ -101,6 +101,11 @@ true + + Program + $(DevEnvDir)devenv.exe + /rootsuffix Exp + echo At least one file is needed within the lib/native folder to convince VS that our package can be installed into native C++ projects. >"$(TargetDir)_.txt" diff --git a/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj b/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj index 826c1b93f..b8bf6f752 100644 --- a/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj +++ b/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj @@ -430,11 +430,6 @@ - - Program - $(DevEnvDir)devenv.exe - /rootsuffix Exp - copy $(OutDir)GoogleTestAdapter.VsPackage.GTA.pkgdef $(SolutionDir)Packaging.GTA From 0d9d0bd65bd1f78277e036d3b19277bcb9000b28 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sun, 10 Mar 2019 13:35:21 +0100 Subject: [PATCH 41/81] minor improvements --- .../VsPackage.GTA/ReleaseNotes/Donations.cs | 1 - .../ReleaseNotes/ReleaseNotesCreator.cs | 2 +- .../ReleaseNotesDialog.Designer.cs | 50 +++++++++---------- .../ReleaseNotes/ReleaseNotesDialog.cs | 8 ++- .../LeakCheckTests/gta_leak_detection.cpp | 2 +- 5 files changed, 34 insertions(+), 29 deletions(-) diff --git a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/Donations.cs b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/Donations.cs index fc8f4a2b8..be73ccb70 100644 --- a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/Donations.cs +++ b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/Donations.cs @@ -8,7 +8,6 @@ public static class Donations public static readonly string Header = $@"
Please consider to donate!

-
"; } } \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesCreator.cs b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesCreator.cs index df48ec380..975e055d9 100644 --- a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesCreator.cs +++ b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesCreator.cs @@ -25,7 +25,7 @@ private string CreateMarkdown() string releaseNotes = Donations.Header; - releaseNotes += CreateHeader(); + releaseNotes += Environment.NewLine + CreateHeader(); int startIndex = Array.IndexOf(Versions, _currentVersion); int endIndex = _formerlyInstalledVersion == null ? -1 : Array.IndexOf(Versions, _formerlyInstalledVersion); diff --git a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesDialog.Designer.cs b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesDialog.Designer.cs index 2dc2d7388..dbc873a98 100644 --- a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesDialog.Designer.cs +++ b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesDialog.Designer.cs @@ -36,9 +36,9 @@ private void InitializeComponent() this.ForwardButton = new System.Windows.Forms.Button(); this.WebBrowser = new System.Windows.Forms.WebBrowser(); this.OkButtonPanel = new System.Windows.Forms.TableLayoutPanel(); + this.DonateButton = new System.Windows.Forms.Button(); this.OkButton = new System.Windows.Forms.Button(); this.toolTip = new System.Windows.Forms.ToolTip(this.components); - this.DonateButton = new System.Windows.Forms.Button(); this.RootPanel.SuspendLayout(); this.NavigationPanel.SuspendLayout(); this.OkButtonPanel.SuspendLayout(); @@ -54,7 +54,7 @@ private void InitializeComponent() this.RootPanel.Controls.Add(this.OkButtonPanel, 0, 2); this.RootPanel.Dock = System.Windows.Forms.DockStyle.Fill; this.RootPanel.Location = new System.Drawing.Point(0, 0); - this.RootPanel.Margin = new System.Windows.Forms.Padding(7, 7, 7, 7); + this.RootPanel.Margin = new System.Windows.Forms.Padding(7); this.RootPanel.Name = "RootPanel"; this.RootPanel.RowCount = 3; this.RootPanel.RowStyles.Add(new System.Windows.Forms.RowStyle()); @@ -72,7 +72,7 @@ private void InitializeComponent() this.NavigationPanel.Controls.Add(this.ForwardButton); this.NavigationPanel.Dock = System.Windows.Forms.DockStyle.Fill; this.NavigationPanel.Location = new System.Drawing.Point(7, 7); - this.NavigationPanel.Margin = new System.Windows.Forms.Padding(7, 7, 7, 7); + this.NavigationPanel.Margin = new System.Windows.Forms.Padding(7); this.NavigationPanel.Name = "NavigationPanel"; this.NavigationPanel.Size = new System.Drawing.Size(1815, 65); this.NavigationPanel.TabIndex = 3; @@ -82,10 +82,10 @@ private void InitializeComponent() this.BackButton.AccessibleName = "Go back"; this.BackButton.Enabled = false; this.BackButton.Location = new System.Drawing.Point(7, 7); - this.BackButton.Margin = new System.Windows.Forms.Padding(7, 7, 7, 7); + this.BackButton.Margin = new System.Windows.Forms.Padding(7); this.BackButton.Name = "BackButton"; this.BackButton.Size = new System.Drawing.Size(54, 51); - this.BackButton.TabIndex = 0; + this.BackButton.TabIndex = 3; this.BackButton.Text = "<"; this.BackButton.UseVisualStyleBackColor = true; // @@ -94,10 +94,10 @@ private void InitializeComponent() this.ForwardButton.AccessibleName = "Go forward"; this.ForwardButton.Enabled = false; this.ForwardButton.Location = new System.Drawing.Point(75, 7); - this.ForwardButton.Margin = new System.Windows.Forms.Padding(7, 7, 7, 7); + this.ForwardButton.Margin = new System.Windows.Forms.Padding(7); this.ForwardButton.Name = "ForwardButton"; this.ForwardButton.Size = new System.Drawing.Size(54, 51); - this.ForwardButton.TabIndex = 1; + this.ForwardButton.TabIndex = 4; this.ForwardButton.Text = ">"; this.ForwardButton.UseVisualStyleBackColor = true; // @@ -109,12 +109,12 @@ private void InitializeComponent() this.WebBrowser.Dock = System.Windows.Forms.DockStyle.Fill; this.WebBrowser.IsWebBrowserContextMenuEnabled = false; this.WebBrowser.Location = new System.Drawing.Point(7, 86); - this.WebBrowser.Margin = new System.Windows.Forms.Padding(7, 7, 7, 7); + this.WebBrowser.Margin = new System.Windows.Forms.Padding(7); this.WebBrowser.MinimumSize = new System.Drawing.Size(47, 45); this.WebBrowser.Name = "WebBrowser"; this.WebBrowser.ScriptErrorsSuppressed = true; this.WebBrowser.Size = new System.Drawing.Size(1815, 1079); - this.WebBrowser.TabIndex = 0; + this.WebBrowser.TabIndex = 2; this.WebBrowser.WebBrowserShortcutsEnabled = false; this.WebBrowser.Navigating += new System.Windows.Forms.WebBrowserNavigatingEventHandler(this.WebBrowser_Navigating); // @@ -129,26 +129,13 @@ private void InitializeComponent() this.OkButtonPanel.Controls.Add(this.DonateButton, 0, 0); this.OkButtonPanel.Controls.Add(this.OkButton, 1, 0); this.OkButtonPanel.Location = new System.Drawing.Point(7, 1179); - this.OkButtonPanel.Margin = new System.Windows.Forms.Padding(7, 7, 7, 7); + this.OkButtonPanel.Margin = new System.Windows.Forms.Padding(7); this.OkButtonPanel.Name = "OkButtonPanel"; this.OkButtonPanel.RowCount = 1; this.OkButtonPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.OkButtonPanel.Size = new System.Drawing.Size(1815, 65); this.OkButtonPanel.TabIndex = 4; // - // OkButton - // - this.OkButton.AccessibleName = "Close release notes dialog"; - this.OkButton.Anchor = System.Windows.Forms.AnchorStyles.None; - this.OkButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.OkButton.Location = new System.Drawing.Point(1273, 7); - this.OkButton.Margin = new System.Windows.Forms.Padding(7, 7, 7, 7); - this.OkButton.Name = "OkButton"; - this.OkButton.Size = new System.Drawing.Size(175, 51); - this.OkButton.TabIndex = 2; - this.OkButton.Text = "Whatever..."; - this.OkButton.UseVisualStyleBackColor = true; - // // DonateButton // this.DonateButton.AccessibleName = "Close release notes dialog"; @@ -157,10 +144,23 @@ private void InitializeComponent() this.DonateButton.Margin = new System.Windows.Forms.Padding(7); this.DonateButton.Name = "DonateButton"; this.DonateButton.Size = new System.Drawing.Size(301, 51); - this.DonateButton.TabIndex = 3; + this.DonateButton.TabIndex = 0; this.DonateButton.Text = "Cool - I want to donate!"; this.DonateButton.UseVisualStyleBackColor = true; // + // OkButton + // + this.OkButton.AccessibleName = "Close release notes dialog"; + this.OkButton.Anchor = System.Windows.Forms.AnchorStyles.None; + this.OkButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.OkButton.Location = new System.Drawing.Point(1273, 7); + this.OkButton.Margin = new System.Windows.Forms.Padding(7); + this.OkButton.Name = "OkButton"; + this.OkButton.Size = new System.Drawing.Size(175, 51); + this.OkButton.TabIndex = 1; + this.OkButton.Text = "Whatever..."; + this.OkButton.UseVisualStyleBackColor = true; + // // ReleaseNotesDialog // this.AcceptButton = this.OkButton; @@ -172,7 +172,7 @@ private void InitializeComponent() this.ClientSize = new System.Drawing.Size(1829, 1251); this.Controls.Add(this.RootPanel); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); - this.Margin = new System.Windows.Forms.Padding(7, 7, 7, 7); + this.Margin = new System.Windows.Forms.Padding(7); this.Name = "ReleaseNotesDialog"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "Google Test Adapter: Release notes"; diff --git a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesDialog.cs b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesDialog.cs index 9eb8266ce..99717e602 100644 --- a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesDialog.cs +++ b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesDialog.cs @@ -14,6 +14,8 @@ public ReleaseNotesDialog() { InitializeComponent(); + Load += (sender, args) => DonateButton.Select(); + WebBrowser.CanGoBackChanged += (sender, args) => BackButton.Enabled = WebBrowser.CanGoBack; BackButton.Click += (sender, args) => WebBrowser.GoBack(); @@ -21,7 +23,11 @@ public ReleaseNotesDialog() ForwardButton.Click += (sender, args) => WebBrowser.GoForward(); OkButton.Click += (sender, args) => Close(); - DonateButton.Click += (sender, args) => OpenUriInDefaultBrowser(Donations.Uri); + DonateButton.Click += (sender, args) => + { + OpenUriInDefaultBrowser(Donations.Uri); + Close(); + }; } internal Uri HtmlFile diff --git a/SampleTests/LeakCheckTests/gta_leak_detection.cpp b/SampleTests/LeakCheckTests/gta_leak_detection.cpp index 6be4a20cb..960137a93 100644 --- a/SampleTests/LeakCheckTests/gta_leak_detection.cpp +++ b/SampleTests/LeakCheckTests/gta_leak_detection.cpp @@ -75,7 +75,7 @@ namespace gta_leak_detection if (result_of_run_all_tests != 0 && is_run_by_gta) { std::cout << "GTA_EXIT_CODE_SKIP\n"; - std::cout << "\nTest result is 'Skipped' due to some weaknesses of Google Test 1.8.1 and crtdbg.h: leak detection results are only reliable if at least one real test is executed, and if all executed tests have passed.\n\n"; + std::cout << "\nTest result is 'Skipped' due to some weaknesses of Google Test 1.8.1 and crtdbg.h: leak detection results are only reliable if all executed tests have passed.\n\n"; } return 0; From aa5df9e998ec4578baac7a6fa3ccb1e4e73a96ba Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sun, 10 Mar 2019 17:00:05 +0100 Subject: [PATCH 42/81] documentation fix --- GoogleTestAdapter/Core/Settings/SettingsWrapper.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs index 23a5956a6..8d58903ce 100644 --- a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs +++ b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs @@ -160,18 +160,19 @@ private string ToString(PropertyInfo propertyInfo) return $"{propertyInfo.Name}: {value}"; } + private const string OnlyInsideVs = " (only available inside VS)"; public const string SolutionDirPlaceholder = "$(SolutionDir)"; private const string DescriptionOfSolutionDirPlaceHolder = - SolutionDirPlaceholder + " - directory of the solution (only available inside VS)"; + SolutionDirPlaceholder + " - directory of the solution" + OnlyInsideVs; public const string PlatformNamePlaceholder = "$(PlatformName)"; private const string DescriptionOfPlatformNamePlaceholder = - PlatformNamePlaceholder + " - the name of the solution's current platform"; + PlatformNamePlaceholder + " - the name of the solution's current platform" + OnlyInsideVs; public const string ConfigurationNamePlaceholder = "$(ConfigurationName)"; private const string DescriptionOfConfigurationNamePlaceholder = - ConfigurationNamePlaceholder + " - the name of the solution's current configuration"; + ConfigurationNamePlaceholder + " - the name of the solution's current configuration" + OnlyInsideVs; private string ReplaceSolutionDirPlaceholder(string theString) { From 031b26261c13057665fade9795cd2e289fb76f8d Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Mon, 11 Mar 2019 19:07:48 +0100 Subject: [PATCH 43/81] removed handling of old property, added Known issues section --- .../VsPackage.GTA/ReleaseNotes/VersionProvider.cs | 4 ---- README.md | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/VersionProvider.cs b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/VersionProvider.cs index 58236621c..b6156630d 100644 --- a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/VersionProvider.cs +++ b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/VersionProvider.cs @@ -9,7 +9,6 @@ namespace GoogleTestAdapter.VsPackage.ReleaseNotes internal class VersionProvider { private const string CollectionName = "GoogleTestAdapter"; - private const string OldVersionPropertyName = "LastStartedVersion"; // TODO remove for release 1.0 private const string VersionPropertyName = "LastVersion"; private readonly WritableSettingsStore _settingsStore; @@ -21,9 +20,6 @@ internal VersionProvider(IServiceProvider serviceProvider) if (!_settingsStore.CollectionExists(CollectionName)) _settingsStore.CreateCollection(CollectionName); - - if (_settingsStore.PropertyExists(CollectionName, OldVersionPropertyName)) - _settingsStore.DeleteProperty(CollectionName, OldVersionPropertyName); } internal Version FormerlyInstalledVersion diff --git a/README.md b/README.md index 3f8dc20c6..52c49a042 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,10 @@ An example usage of the *Exit code test case* can be found as part of the Sample However, note that Google Test as of V1.8.1 [uses some memory allocation](https://github.com/google/googletest/pull/1142) which is recognized by MS' leak detection mechanism as a leak (although it isn't), in particular for failing assertions. Some of these "false positives" have been fixed with the linked issue, making leak detection useful as long as all tests are green; however, and until this problem is fixed, the memory leak detection provided by GTA will result in a skipped exit code test in case `RUN_ALL_TESTS()` does not return `0`, but will report the leak in the test's error message. If you run into such problems, please report them against the [Google Test repository](https://github.com/google/googletest) if appropriate. +##### Known issues + +* Visual Studio 2013: if a test project *FooTests* makes use of a `main()` method of a *BarTests* project (e.g. by referencing its `main.cpp`), the exit code test of *FooTests* will be grouped under *BarTests*' executable. + #### Running tests from command line with `VSTest.Console.exe` From 2093a4fb6e044db11590690e39855cd006f81df4 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sun, 10 Mar 2019 17:32:46 +0100 Subject: [PATCH 44/81] reorganized settings (conversion of old settings missing) --- .../Core/Settings/SettingsWrapper.cs | 8 +- .../GoogleTestExtensionOptionsPage.cs | 61 ++--- .../OptionsPages/GeneralOptionsDialogPage.cs | 217 +----------------- .../ParallelizationOptionsDialogPage.cs | 38 --- .../TestDiscoveryOptionsDialogPage.cs | 105 +++++++++ .../TestExecutionOptionsDialogPage.cs | 167 ++++++++++++++ .../VsPackage.Shared.projitems | 5 +- 7 files changed, 326 insertions(+), 275 deletions(-) delete mode 100644 GoogleTestAdapter/VsPackage.Shared/OptionsPages/ParallelizationOptionsDialogPage.cs create mode 100644 GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestDiscoveryOptionsDialogPage.cs create mode 100644 GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestExecutionOptionsDialogPage.cs diff --git a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs index 8d58903ce..8d0cca3e0 100644 --- a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs +++ b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs @@ -274,15 +274,19 @@ private string ReplaceEnvironmentVariables(string theString) public const string PageGeneralName = "General"; - public const string PageParallelizationName = CategoryParallelizationName; public const string PageGoogleTestName = "Google Test"; + public const string PageTestDiscovery = "Test Discovery"; + public const string PageTestExecution = "Test Execution"; public const string CategoryTestExecutionName = "Test execution"; public const string CategoryTraitsName = "Regexes for trait assignment"; public const string CategoryRuntimeBehaviorName = "Runtime behavior"; public const string CategoryParallelizationName = "Parallelization"; public const string CategoryMiscName = "Misc"; - + public const string CategoryOutputName = "Output"; + public const string CategorySecurityName = "Security"; + public const string CategoryRunConfigurationName = "Run configuration (also applies to test discovery)"; + public const string CategorySetupAndTeardownName = "Setup and teardown"; #region GeneralOptionsPage diff --git a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs index 91b5ac02f..e1cfccff2 100644 --- a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs @@ -18,6 +18,8 @@ using System.ServiceModel; using EnvDTE; using Microsoft.VisualStudio.AsyncPackageHelpers; +using TestDiscoveryOptionsDialogPage = GoogleTestAdapter.VsPackage.OptionsPages.TestDiscoveryOptionsDialogPage; +using Microsoft.Win32; namespace GoogleTestAdapter.VsPackage { @@ -29,9 +31,9 @@ namespace GoogleTestAdapter.VsPackage [Guid(PackageGuidString)] [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "pkgdef, VS and vsixmanifest are valid VS terms")] [ProvideOptionPage(typeof(GeneralOptionsDialogPage), OptionsCategoryName, SettingsWrapper.PageGeneralName, 0, 0, true)] - [ProvideOptionPage(typeof(ParallelizationOptionsDialogPage), OptionsCategoryName, SettingsWrapper.PageParallelizationName, 0, 0, true)] + [ProvideOptionPage(typeof(TestDiscoveryOptionsDialogPage), OptionsCategoryName, SettingsWrapper.PageTestDiscovery, 0, 0, true)] + [ProvideOptionPage(typeof(TestExecutionOptionsDialogPage), OptionsCategoryName, SettingsWrapper.PageTestExecution, 0, 0, true)] [ProvideOptionPage(typeof(GoogleTestOptionsDialogPage), OptionsCategoryName, SettingsWrapper.PageGoogleTestName, 0, 0, true)] -// [Microsoft.VisualStudio.Shell.ProvideAutoLoad(UIContextGuids.SolutionExists)] [ProvideMenuResource("Menus.ctmenu", 1)] public sealed partial class GoogleTestExtensionOptionsPage : Package, IGoogleTestExtensionOptionsPage, IAsyncLoadablePackageInitialize, IDisposable { @@ -42,7 +44,8 @@ public sealed partial class GoogleTestExtensionOptionsPage : Package, IGoogleTes private IGlobalRunSettingsInternal _globalRunSettings; private GeneralOptionsDialogPage _generalOptions; - private ParallelizationOptionsDialogPage _parallelizationOptions; + private TestDiscoveryOptionsDialogPage _testDiscoveryOptions; + private TestExecutionOptionsDialogPage _testExecutionOptions; private GoogleTestOptionsDialogPage _googleTestOptions; private DebuggerAttacherServiceHost _debuggerAttacherServiceHost; @@ -94,14 +97,17 @@ private void DoInitialize() private void InitializeOptions() { _generalOptions = (GeneralOptionsDialogPage) GetDialogPage(typeof(GeneralOptionsDialogPage)); - _parallelizationOptions = - (ParallelizationOptionsDialogPage) GetDialogPage(typeof(ParallelizationOptionsDialogPage)); + _testDiscoveryOptions = + (TestDiscoveryOptionsDialogPage) GetDialogPage(typeof(TestDiscoveryOptionsDialogPage)); + _testExecutionOptions = + (TestExecutionOptionsDialogPage) GetDialogPage(typeof(TestExecutionOptionsDialogPage)); _googleTestOptions = (GoogleTestOptionsDialogPage) GetDialogPage(typeof(GoogleTestOptionsDialogPage)); _globalRunSettings.RunSettings = GetRunSettingsFromOptionPages(); _generalOptions.PropertyChanged += OptionsChanged; - _parallelizationOptions.PropertyChanged += OptionsChanged; + _testDiscoveryOptions.PropertyChanged += OptionsChanged; + _testExecutionOptions.PropertyChanged += OptionsChanged; _googleTestOptions.PropertyChanged += OptionsChanged; } @@ -147,7 +153,8 @@ protected override void Dispose(bool disposing) if (disposing) { _generalOptions?.Dispose(); - _parallelizationOptions?.Dispose(); + _testDiscoveryOptions?.Dispose(); + _testExecutionOptions?.Dispose(); _googleTestOptions?.Dispose(); try @@ -194,10 +201,10 @@ public bool PrintTestOutput public bool ParallelTestExecution { - get { return _parallelizationOptions.EnableParallelTestExecution; } + get { return _testExecutionOptions.EnableParallelTestExecution; } set { - _parallelizationOptions.EnableParallelTestExecution = value; + _testExecutionOptions.EnableParallelTestExecution = value; RefreshVsUi(); } } @@ -224,23 +231,9 @@ private RunSettings GetRunSettingsFromOptionPages() return new RunSettings { PrintTestOutput = _generalOptions.PrintTestOutput, - TestDiscoveryRegex = _generalOptions.TestDiscoveryRegex, - AdditionalPdbs = _generalOptions.AdditionalPdbs, - TestDiscoveryTimeoutInSeconds = _generalOptions.TestDiscoveryTimeoutInSeconds, - WorkingDir = _generalOptions.WorkingDir, - PathExtension = _generalOptions.PathExtension, - TraitsRegexesBefore = _generalOptions.TraitsRegexesBefore, - TraitsRegexesAfter = _generalOptions.TraitsRegexesAfter, - TestNameSeparator = _generalOptions.TestNameSeparator, - ParseSymbolInformation = _generalOptions.ParseSymbolInformation, DebugMode = _generalOptions.DebugMode, TimestampOutput = _generalOptions.TimestampOutput, - AdditionalTestExecutionParam = _generalOptions.AdditionalTestExecutionParams, - BatchForTestSetup = _generalOptions.BatchForTestSetup, - BatchForTestTeardown = _generalOptions.BatchForTestTeardown, - KillProcessesOnCancel = _generalOptions.KillProcessesOnCancel, SkipOriginCheck = _generalOptions.SkipOriginCheck, - ExitCodeTestCase = _generalOptions.ExitCodeTestCase, CatchExceptions = _googleTestOptions.CatchExceptions, BreakOnFailure = _googleTestOptions.BreakOnFailure, @@ -249,10 +242,24 @@ private RunSettings GetRunSettingsFromOptionPages() ShuffleTests = _googleTestOptions.ShuffleTests, ShuffleTestsSeed = _googleTestOptions.ShuffleTestsSeed, - ParallelTestExecution = _parallelizationOptions.EnableParallelTestExecution, - MaxNrOfThreads = _parallelizationOptions.MaxNrOfThreads, - - UseNewTestExecutionFramework = _generalOptions.UseNewTestExecutionFramework2, + TestDiscoveryRegex = _testDiscoveryOptions.TestDiscoveryRegex, + TestDiscoveryTimeoutInSeconds = _testDiscoveryOptions.TestDiscoveryTimeoutInSeconds, + TraitsRegexesBefore = _testDiscoveryOptions.TraitsRegexesBefore, + TraitsRegexesAfter = _testDiscoveryOptions.TraitsRegexesAfter, + TestNameSeparator = _testDiscoveryOptions.TestNameSeparator, + ParseSymbolInformation = _testDiscoveryOptions.ParseSymbolInformation, + + AdditionalPdbs = _testExecutionOptions.AdditionalPdbs, + WorkingDir = _testExecutionOptions.WorkingDir, + PathExtension = _testExecutionOptions.PathExtension, + AdditionalTestExecutionParam = _testExecutionOptions.AdditionalTestExecutionParams, + BatchForTestSetup = _testExecutionOptions.BatchForTestSetup, + BatchForTestTeardown = _testExecutionOptions.BatchForTestTeardown, + KillProcessesOnCancel = _testExecutionOptions.KillProcessesOnCancel, + ExitCodeTestCase = _testExecutionOptions.ExitCodeTestCase, + ParallelTestExecution = _testExecutionOptions.EnableParallelTestExecution, + MaxNrOfThreads = _testExecutionOptions.MaxNrOfThreads, + UseNewTestExecutionFramework = _testExecutionOptions.UseNewTestExecutionFramework2, DebuggingNamedPipeId = _debuggingNamedPipeId, SolutionDir = solutionDir, diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs index 61370fca1..95cab58d7 100644 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs @@ -1,12 +1,8 @@ // This file has been modified by Microsoft on 7/2017. -using GoogleTestAdapter.Helpers; using GoogleTestAdapter.Settings; -using System; -using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; -using System.Linq; namespace GoogleTestAdapter.VsPackage.OptionsPages { @@ -14,171 +10,9 @@ namespace GoogleTestAdapter.VsPackage.OptionsPages [SuppressMessage("ReSharper", "UnusedMember.Global")] public partial class GeneralOptionsDialogPage : NotifyingDialogPage { - #region Test execution + #region Output - [Category(SettingsWrapper.CategoryTestExecutionName)] - [DisplayName(SettingsWrapper.OptionTestDiscoveryRegex)] - [Description(SettingsWrapper.OptionTestDiscoveryRegexDescription)] - public string TestDiscoveryRegex - { - get { return _testDiscoveryRegex; } - set - { - Utils.ValidateRegex(value); - SetAndNotify(ref _testDiscoveryRegex, value); - } - } - private string _testDiscoveryRegex = SettingsWrapper.OptionTestDiscoveryRegexDefaultValue; - - [Category(SettingsWrapper.CategoryTestExecutionName)] - [DisplayName(SettingsWrapper.OptionAdditionalPdbs)] - [Description(SettingsWrapper.OptionAdditionalPdbsDescription)] - public string AdditionalPdbs - { - get { return _additionalPdbs; } - set - { - var patterns = Utils.SplitAdditionalPdbs(_additionalPdbs); - var errorMessages = new List(); - foreach (string pattern in patterns) - { - if (!Utils.ValidatePattern(pattern, out string errorMessage)) - { - errorMessages.Add(errorMessage); - } - } - if (errorMessages.Any()) - { - throw new Exception(string.Join(Environment.NewLine, errorMessages)); - } - - SetAndNotify(ref _additionalPdbs, value); - } - } - private string _additionalPdbs = SettingsWrapper.OptionAdditionalPdbsDefaultValue; - - [Category(SettingsWrapper.CategoryTestExecutionName)] - [DisplayName(SettingsWrapper.OptionTestDiscoveryTimeoutInSeconds)] - [Description(SettingsWrapper.OptionTestDiscoveryTimeoutInSecondsDescription)] - public int TestDiscoveryTimeoutInSeconds - { - get { return _testDiscoveryTimeoutInSeconds; } - set - { - if (value < 0) - throw new ArgumentOutOfRangeException(nameof(value), value, "Expected a number greater than or equal to 0."); - SetAndNotify(ref _testDiscoveryTimeoutInSeconds, value); - } - } - private int _testDiscoveryTimeoutInSeconds = SettingsWrapper.OptionTestDiscoveryTimeoutInSecondsDefaultValue; - - [Category(SettingsWrapper.CategoryTestExecutionName)] - [DisplayName(SettingsWrapper.OptionWorkingDir)] - [Description(SettingsWrapper.OptionWorkingDirDescription)] - public string WorkingDir - { - get { return _workingDirectory; } - set { SetAndNotify(ref _workingDirectory, value); } - } - private string _workingDirectory = SettingsWrapper.OptionWorkingDirDefaultValue; - - [Category(SettingsWrapper.CategoryTestExecutionName)] - [DisplayName(SettingsWrapper.OptionPathExtension)] - [Description(SettingsWrapper.OptionPathExtensionDescription)] - public string PathExtension - { - get { return _pathExtension; } - set { SetAndNotify(ref _pathExtension, value); } - } - private string _pathExtension = SettingsWrapper.OptionPathExtensionDefaultValue; - - [Category(SettingsWrapper.CategoryTestExecutionName)] - [DisplayName(SettingsWrapper.OptionAdditionalTestExecutionParams)] - [Description(SettingsWrapper.OptionAdditionalTestExecutionParamsDescription)] - public string AdditionalTestExecutionParams - { - get { return _additionalTestExecutionParams; } - set { SetAndNotify(ref _additionalTestExecutionParams, value); } - } - private string _additionalTestExecutionParams = SettingsWrapper.OptionAdditionalTestExecutionParamsDefaultValue; - - [Category(SettingsWrapper.CategoryTestExecutionName)] - [DisplayName(SettingsWrapper.OptionBatchForTestSetup)] - [Description(SettingsWrapper.OptionBatchForTestSetupDescription)] - public string BatchForTestSetup - { - get { return _batchForTestSetup; } - set { SetAndNotify(ref _batchForTestSetup, value); } - } - private string _batchForTestSetup = SettingsWrapper.OptionBatchForTestSetupDefaultValue; - - [Category(SettingsWrapper.CategoryTestExecutionName)] - [DisplayName(SettingsWrapper.OptionBatchForTestTeardown)] - [Description(SettingsWrapper.OptionBatchForTestTeardownDescription)] - public string BatchForTestTeardown - { - get { return _batchForTestTeardown; } - set { SetAndNotify(ref _batchForTestTeardown, value); } - } - private string _batchForTestTeardown = SettingsWrapper.OptionBatchForTestTeardownDefaultValue; - - [Category(SettingsWrapper.CategoryTestExecutionName)] - [DisplayName(SettingsWrapper.OptionKillProcessesOnCancel)] - [Description(SettingsWrapper.OptionKillProcessesOnCancelDescription)] - public bool KillProcessesOnCancel - { - get { return _killProcessesOnCancel; } - set { SetAndNotify(ref _killProcessesOnCancel, value); } - } - private bool _killProcessesOnCancel = SettingsWrapper.OptionKillProcessesOnCancelDefaultValue; - - #endregion - - #region Traits - - [Category(SettingsWrapper.CategoryTraitsName)] - [DisplayName(SettingsWrapper.OptionTraitsRegexesBefore)] - [Description(SettingsWrapper.OptionTraitsDescription)] - public string TraitsRegexesBefore - { - get { return _traitsRegexesBefore; } - set - { - Utils.ValidateTraitRegexes(value); - SetAndNotify(ref _traitsRegexesBefore, value); - } - } - private string _traitsRegexesBefore = SettingsWrapper.OptionTraitsRegexesDefaultValue; - - [Category(SettingsWrapper.CategoryTraitsName)] - [DisplayName(SettingsWrapper.OptionTraitsRegexesAfter)] - [Description(SettingsWrapper.OptionTraitsDescription)] - public string TraitsRegexesAfter - { - get { return _traitsRegexesAfter; } - set - { - Utils.ValidateTraitRegexes(value); - SetAndNotify(ref _traitsRegexesAfter, value); - } - } - private string _traitsRegexesAfter = SettingsWrapper.OptionTraitsRegexesDefaultValue; - - #endregion - - #region Misc - - [Category(SettingsWrapper.CategoryMiscName)] - [DisplayName(SettingsWrapper.OptionUseNewTestExecutionFramework)] - [Description(SettingsWrapper.OptionUseNewTestExecutionFrameworkDescription)] - public bool UseNewTestExecutionFramework2 - { - get { return _useNewTestExecutionFramework; } - set { SetAndNotify(ref _useNewTestExecutionFramework, value); } - } - private bool _useNewTestExecutionFramework = SettingsWrapper.OptionUseNewTestExecutionFrameworkDefaultValue; - - [Category(SettingsWrapper.CategoryMiscName)] + [Category(SettingsWrapper.CategoryOutputName)] [DisplayName(SettingsWrapper.OptionPrintTestOutput)] [Description(SettingsWrapper.OptionPrintTestOutputDescription)] public bool PrintTestOutput @@ -188,32 +22,7 @@ public bool PrintTestOutput } private bool _printTestOutput = SettingsWrapper.OptionPrintTestOutputDefaultValue; - [Category(SettingsWrapper.CategoryMiscName)] - [DisplayName(SettingsWrapper.OptionTestNameSeparator)] - [Description(SettingsWrapper.OptionTestNameSeparatorDescription)] - public string TestNameSeparator - { - get { return _testNameSeparator; } - set - { - if (value.Length > 16) - throw new ArgumentOutOfRangeException(nameof(value), value, "Expected string not longer than 16 characters."); - SetAndNotify(ref _testNameSeparator, value); - } - } - private string _testNameSeparator = SettingsWrapper.OptionTestNameSeparatorDefaultValue; - - [Category(SettingsWrapper.CategoryMiscName)] - [DisplayName(SettingsWrapper.OptionParseSymbolInformation)] - [Description(SettingsWrapper.OptionParseSymbolInformationDescription)] - public bool ParseSymbolInformation - { - get { return _parseSymbolInformation; } - set { SetAndNotify(ref _parseSymbolInformation, value); } - } - private bool _parseSymbolInformation = SettingsWrapper.OptionParseSymbolInformationDefaultValue; - - [Category(SettingsWrapper.CategoryMiscName)] + [Category(SettingsWrapper.CategoryOutputName)] [DisplayName(SettingsWrapper.OptionDebugMode)] [Description(SettingsWrapper.OptionDebugModeDescription)] public bool DebugMode @@ -223,7 +32,7 @@ public bool DebugMode } private bool _debugMode = SettingsWrapper.OptionDebugModeDefaultValue; - [Category(SettingsWrapper.CategoryMiscName)] + [Category(SettingsWrapper.CategoryOutputName)] [DisplayName(SettingsWrapper.OptionTimestampOutput)] [Description(SettingsWrapper.OptionTimestampOutputDescription)] public bool TimestampOutput @@ -233,7 +42,11 @@ public bool TimestampOutput } private bool _timestampOutput = SettingsWrapper.OptionTimestampOutputDefaultValue; - [Category(SettingsWrapper.CategoryMiscName)] + #endregion + + #region Security + + [Category(SettingsWrapper.CategorySecurityName)] [DisplayName(SettingsWrapper.OptionSkipOriginCheck)] [Description(SettingsWrapper.OptionSkipOriginCheckDescription)] public bool SkipOriginCheck @@ -242,17 +55,7 @@ public bool SkipOriginCheck set { SetAndNotify(ref _skipOriginCheck, value); } } private bool _skipOriginCheck = SettingsWrapper.OptionSkipOriginCheckDefaultValue; - - [Category(SettingsWrapper.CategoryMiscName)] - [DisplayName(SettingsWrapper.OptionExitCodeTestCase)] - [Description(SettingsWrapper.OptionExitCodeTestCaseDescription)] - public string ExitCodeTestCase - { - get { return _exitCodeTestCase; } - set { SetAndNotify(ref _exitCodeTestCase, value); } - } - private string _exitCodeTestCase = SettingsWrapper.OptionExitCodeTestCaseDefaultValue; - + #endregion } diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/ParallelizationOptionsDialogPage.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/ParallelizationOptionsDialogPage.cs deleted file mode 100644 index 43b8cee23..000000000 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/ParallelizationOptionsDialogPage.cs +++ /dev/null @@ -1,38 +0,0 @@ -// This file has been modified by Microsoft on 6/2017. - -using GoogleTestAdapter.Settings; -using System; -using System.ComponentModel; - -namespace GoogleTestAdapter.VsPackage.OptionsPages -{ - - public class ParallelizationOptionsDialogPage : NotifyingDialogPage - { - [Category(SettingsWrapper.CategoryParallelizationName)] - [DisplayName(SettingsWrapper.OptionEnableParallelTestExecution)] - [Description(SettingsWrapper.OptionEnableParallelTestExecutionDescription)] - public bool EnableParallelTestExecution - { - get { return _enableParallelTestExecution; } - set { SetAndNotify(ref _enableParallelTestExecution, value); } - } - private bool _enableParallelTestExecution = SettingsWrapper.OptionEnableParallelTestExecutionDefaultValue; - - [Category(SettingsWrapper.CategoryParallelizationName)] - [DisplayName(SettingsWrapper.OptionMaxNrOfThreads)] - [Description(SettingsWrapper.OptionMaxNrOfThreadsDescription)] - public int MaxNrOfThreads - { - get { return _maxNrOfThreads; } - set - { - if (value < 0) - throw new ArgumentOutOfRangeException(nameof(value), value, "Expected a number greater than or equal to 0."); - SetAndNotify(ref _maxNrOfThreads, value); - } - } - private int _maxNrOfThreads = SettingsWrapper.OptionMaxNrOfThreadsDefaultValue; - } - -} \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestDiscoveryOptionsDialogPage.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestDiscoveryOptionsDialogPage.cs new file mode 100644 index 000000000..0ab3cd90c --- /dev/null +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestDiscoveryOptionsDialogPage.cs @@ -0,0 +1,105 @@ +// This file has been modified by Microsoft on 6/2017. + +using GoogleTestAdapter.Settings; +using System; +using System.ComponentModel; +using GoogleTestAdapter.Helpers; + +namespace GoogleTestAdapter.VsPackage.OptionsPages +{ + + public class TestDiscoveryOptionsDialogPage : NotifyingDialogPage + { + #region Misc + + [Category(SettingsWrapper.CategoryMiscName)] + [DisplayName(SettingsWrapper.OptionTestDiscoveryRegex)] + [Description(SettingsWrapper.OptionTestDiscoveryRegexDescription)] + public string TestDiscoveryRegex + { + get { return _testDiscoveryRegex; } + set + { + Utils.ValidateRegex(value); + SetAndNotify(ref _testDiscoveryRegex, value); + } + } + private string _testDiscoveryRegex = SettingsWrapper.OptionTestDiscoveryRegexDefaultValue; + + [Category(SettingsWrapper.CategoryMiscName)] + [DisplayName(SettingsWrapper.OptionTestDiscoveryTimeoutInSeconds)] + [Description(SettingsWrapper.OptionTestDiscoveryTimeoutInSecondsDescription)] + public int TestDiscoveryTimeoutInSeconds + { + get { return _testDiscoveryTimeoutInSeconds; } + set + { + if (value < 0) + throw new ArgumentOutOfRangeException(nameof(value), value, "Expected a number greater than or equal to 0."); + SetAndNotify(ref _testDiscoveryTimeoutInSeconds, value); + } + } + private int _testDiscoveryTimeoutInSeconds = SettingsWrapper.OptionTestDiscoveryTimeoutInSecondsDefaultValue; + + [Category(SettingsWrapper.CategoryMiscName)] + [DisplayName(SettingsWrapper.OptionTestNameSeparator)] + [Description(SettingsWrapper.OptionTestNameSeparatorDescription)] + public string TestNameSeparator + { + get { return _testNameSeparator; } + set + { + if (value.Length > 16) + throw new ArgumentOutOfRangeException(nameof(value), value, "Expected string not longer than 16 characters."); + SetAndNotify(ref _testNameSeparator, value); + } + } + private string _testNameSeparator = SettingsWrapper.OptionTestNameSeparatorDefaultValue; + + [Category(SettingsWrapper.CategoryMiscName)] + [DisplayName(SettingsWrapper.OptionParseSymbolInformation)] + [Description(SettingsWrapper.OptionParseSymbolInformationDescription)] + public bool ParseSymbolInformation + { + get { return _parseSymbolInformation; } + set { SetAndNotify(ref _parseSymbolInformation, value); } + } + private bool _parseSymbolInformation = SettingsWrapper.OptionParseSymbolInformationDefaultValue; + + #endregion + + #region Traits + + [Category(SettingsWrapper.CategoryTraitsName)] + [DisplayName(SettingsWrapper.OptionTraitsRegexesBefore)] + [Description(SettingsWrapper.OptionTraitsDescription)] + public string TraitsRegexesBefore + { + get { return _traitsRegexesBefore; } + set + { + Utils.ValidateTraitRegexes(value); + SetAndNotify(ref _traitsRegexesBefore, value); + } + } + private string _traitsRegexesBefore = SettingsWrapper.OptionTraitsRegexesDefaultValue; + + [Category(SettingsWrapper.CategoryTraitsName)] + [DisplayName(SettingsWrapper.OptionTraitsRegexesAfter)] + [Description(SettingsWrapper.OptionTraitsDescription)] + public string TraitsRegexesAfter + { + get { return _traitsRegexesAfter; } + set + { + Utils.ValidateTraitRegexes(value); + SetAndNotify(ref _traitsRegexesAfter, value); + } + } + private string _traitsRegexesAfter = SettingsWrapper.OptionTraitsRegexesDefaultValue; + + #endregion + + } + +} \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestExecutionOptionsDialogPage.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestExecutionOptionsDialogPage.cs new file mode 100644 index 000000000..496b76e7a --- /dev/null +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestExecutionOptionsDialogPage.cs @@ -0,0 +1,167 @@ +// This file has been modified by Microsoft on 6/2017. + +using GoogleTestAdapter.Settings; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using GoogleTestAdapter.Helpers; + +namespace GoogleTestAdapter.VsPackage.OptionsPages +{ + + public class TestExecutionOptionsDialogPage : NotifyingDialogPage + { + #region Parallelization + + [Category(SettingsWrapper.CategoryParallelizationName)] + [DisplayName(SettingsWrapper.OptionEnableParallelTestExecution)] + [Description(SettingsWrapper.OptionEnableParallelTestExecutionDescription)] + public bool EnableParallelTestExecution + { + get { return _enableParallelTestExecution; } + set { SetAndNotify(ref _enableParallelTestExecution, value); } + } + private bool _enableParallelTestExecution = SettingsWrapper.OptionEnableParallelTestExecutionDefaultValue; + + [Category(SettingsWrapper.CategoryParallelizationName)] + [DisplayName(SettingsWrapper.OptionMaxNrOfThreads)] + [Description(SettingsWrapper.OptionMaxNrOfThreadsDescription)] + public int MaxNrOfThreads + { + get { return _maxNrOfThreads; } + set + { + if (value < 0) + throw new ArgumentOutOfRangeException(nameof(value), value, "Expected a number greater than or equal to 0."); + SetAndNotify(ref _maxNrOfThreads, value); + } + } + private int _maxNrOfThreads = SettingsWrapper.OptionMaxNrOfThreadsDefaultValue; + + #endregion + + #region Run configuration + + [Category(SettingsWrapper.CategoryRunConfigurationName)] + [DisplayName(SettingsWrapper.OptionAdditionalPdbs)] + [Description(SettingsWrapper.OptionAdditionalPdbsDescription)] + public string AdditionalPdbs + { + get { return _additionalPdbs; } + set + { + var patterns = Utils.SplitAdditionalPdbs(_additionalPdbs); + var errorMessages = new List(); + foreach (string pattern in patterns) + { + if (!Utils.ValidatePattern(pattern, out string errorMessage)) + { + errorMessages.Add(errorMessage); + } + } + if (errorMessages.Any()) + { + throw new Exception(string.Join(Environment.NewLine, errorMessages)); + } + + SetAndNotify(ref _additionalPdbs, value); + } + } + private string _additionalPdbs = SettingsWrapper.OptionAdditionalPdbsDefaultValue; + + [Category(SettingsWrapper.CategoryRunConfigurationName)] + [DisplayName(SettingsWrapper.OptionWorkingDir)] + [Description(SettingsWrapper.OptionWorkingDirDescription)] + public string WorkingDir + { + get { return _workingDirectory; } + set { SetAndNotify(ref _workingDirectory, value); } + } + private string _workingDirectory = SettingsWrapper.OptionWorkingDirDefaultValue; + + [Category(SettingsWrapper.CategoryRunConfigurationName)] + [DisplayName(SettingsWrapper.OptionPathExtension)] + [Description(SettingsWrapper.OptionPathExtensionDescription)] + public string PathExtension + { + get { return _pathExtension; } + set { SetAndNotify(ref _pathExtension, value); } + } + private string _pathExtension = SettingsWrapper.OptionPathExtensionDefaultValue; + + [Category(SettingsWrapper.CategoryRunConfigurationName)] + [DisplayName(SettingsWrapper.OptionAdditionalTestExecutionParams)] + [Description(SettingsWrapper.OptionAdditionalTestExecutionParamsDescription)] + public string AdditionalTestExecutionParams + { + get { return _additionalTestExecutionParams; } + set { SetAndNotify(ref _additionalTestExecutionParams, value); } + } + private string _additionalTestExecutionParams = SettingsWrapper.OptionAdditionalTestExecutionParamsDefaultValue; + + #endregion + + + #region Setup and teardown + + [Category(SettingsWrapper.CategorySetupAndTeardownName)] + [DisplayName(SettingsWrapper.OptionBatchForTestSetup)] + [Description(SettingsWrapper.OptionBatchForTestSetupDescription)] + public string BatchForTestSetup + { + get { return _batchForTestSetup; } + set { SetAndNotify(ref _batchForTestSetup, value); } + } + private string _batchForTestSetup = SettingsWrapper.OptionBatchForTestSetupDefaultValue; + + [Category(SettingsWrapper.CategorySetupAndTeardownName)] + [DisplayName(SettingsWrapper.OptionBatchForTestTeardown)] + [Description(SettingsWrapper.OptionBatchForTestTeardownDescription)] + public string BatchForTestTeardown + { + get { return _batchForTestTeardown; } + set { SetAndNotify(ref _batchForTestTeardown, value); } + } + private string _batchForTestTeardown = SettingsWrapper.OptionBatchForTestTeardownDefaultValue; + + #endregion + + + #region Misc + + [Category(SettingsWrapper.CategoryMiscName)] + [DisplayName(SettingsWrapper.OptionKillProcessesOnCancel)] + [Description(SettingsWrapper.OptionKillProcessesOnCancelDescription)] + public bool KillProcessesOnCancel + { + get { return _killProcessesOnCancel; } + set { SetAndNotify(ref _killProcessesOnCancel, value); } + } + private bool _killProcessesOnCancel = SettingsWrapper.OptionKillProcessesOnCancelDefaultValue; + + [Category(SettingsWrapper.CategoryMiscName)] + [DisplayName(SettingsWrapper.OptionUseNewTestExecutionFramework)] + [Description(SettingsWrapper.OptionUseNewTestExecutionFrameworkDescription)] + public bool UseNewTestExecutionFramework2 + { + get { return _useNewTestExecutionFramework; } + set { SetAndNotify(ref _useNewTestExecutionFramework, value); } + } + private bool _useNewTestExecutionFramework = SettingsWrapper.OptionUseNewTestExecutionFrameworkDefaultValue; + + [Category(SettingsWrapper.CategoryMiscName)] + [DisplayName(SettingsWrapper.OptionExitCodeTestCase)] + [Description(SettingsWrapper.OptionExitCodeTestCaseDescription)] + public string ExitCodeTestCase + { + get { return _exitCodeTestCase; } + set { SetAndNotify(ref _exitCodeTestCase, value); } + } + private string _exitCodeTestCase = SettingsWrapper.OptionExitCodeTestCaseDefaultValue; + + #endregion + + } + +} \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.Shared/VsPackage.Shared.projitems b/GoogleTestAdapter/VsPackage.Shared/VsPackage.Shared.projitems index aa3160135..e96b48fe6 100644 --- a/GoogleTestAdapter/VsPackage.Shared/VsPackage.Shared.projitems +++ b/GoogleTestAdapter/VsPackage.Shared/VsPackage.Shared.projitems @@ -28,7 +28,10 @@ Component - + + Component + + Component From df9cc606ecc937aa4b6bf57f6d3b641637a597cd Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Tue, 12 Mar 2019 07:23:17 +0100 Subject: [PATCH 45/81] added OptionsUpdater --- .../TestAdapter/Framework/VsVersion.cs | 15 +- .../ReleaseNotes/VersionProvider.cs | 2 +- .../GoogleTestExtensionOptionsPage.cs | 6 +- .../OptionsPages/OptionsUpdater.cs | 187 ++++++++++++++++++ .../VsPackage.Shared.projitems | 1 + 5 files changed, 208 insertions(+), 3 deletions(-) create mode 100644 GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs diff --git a/GoogleTestAdapter/TestAdapter/Framework/VsVersion.cs b/GoogleTestAdapter/TestAdapter/Framework/VsVersion.cs index a5c4330fe..f3da7ba90 100644 --- a/GoogleTestAdapter/TestAdapter/Framework/VsVersion.cs +++ b/GoogleTestAdapter/TestAdapter/Framework/VsVersion.cs @@ -39,6 +39,19 @@ public static int Year(this VsVersion version) default: throw new InvalidOperationException(); } + + } + + public static string VersionString(this VsVersion version) + { + switch (version) + { + case VsVersion.Unknown: + case VsVersion.VS2012: + return "0.0"; + default: + return $"{(int)version}.0"; + } } public static bool NeedsToBeThrottled(this VsVersion version) @@ -71,7 +84,7 @@ public static class VsVersionUtils private static VsVersion? _version; - public static VsVersion GetVisualStudioVersion(ILogger logger) + public static VsVersion GetVisualStudioVersion(ILogger logger = null) { lock (Lock) { diff --git a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/VersionProvider.cs b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/VersionProvider.cs index b6156630d..2e7cbbccb 100644 --- a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/VersionProvider.cs +++ b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/VersionProvider.cs @@ -8,7 +8,7 @@ namespace GoogleTestAdapter.VsPackage.ReleaseNotes internal class VersionProvider { - private const string CollectionName = "GoogleTestAdapter"; + public const string CollectionName = "GoogleTestAdapter"; private const string VersionPropertyName = "LastVersion"; private readonly WritableSettingsStore _settingsStore; diff --git a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs index e1cfccff2..0f4dd6caf 100644 --- a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs @@ -18,8 +18,9 @@ using System.ServiceModel; using EnvDTE; using Microsoft.VisualStudio.AsyncPackageHelpers; -using TestDiscoveryOptionsDialogPage = GoogleTestAdapter.VsPackage.OptionsPages.TestDiscoveryOptionsDialogPage; using Microsoft.Win32; +using VsPackage.Shared.Settings; +using TestDiscoveryOptionsDialogPage = GoogleTestAdapter.VsPackage.OptionsPages.TestDiscoveryOptionsDialogPage; namespace GoogleTestAdapter.VsPackage { @@ -105,6 +106,9 @@ private void InitializeOptions() _globalRunSettings.RunSettings = GetRunSettingsFromOptionPages(); + var optionsUpdater = new OptionsUpdater(_testDiscoveryOptions, _testExecutionOptions, this); + optionsUpdater.UpdateIfNecessary(); + _generalOptions.PropertyChanged += OptionsChanged; _testDiscoveryOptions.PropertyChanged += OptionsChanged; _testExecutionOptions.PropertyChanged += OptionsChanged; diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs new file mode 100644 index 000000000..6f41a7c0a --- /dev/null +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs @@ -0,0 +1,187 @@ +using System; +using System.Linq; +using GoogleTestAdapter.Settings; +using GoogleTestAdapter.TestAdapter.Framework; +using GoogleTestAdapter.VsPackage.OptionsPages; +using GoogleTestAdapter.VsPackage.ReleaseNotes; +using Microsoft.VisualStudio.Settings; +using Microsoft.VisualStudio.Shell.Settings; +using Microsoft.Win32; + +namespace VsPackage.Shared.Settings +{ + public class OptionsUpdater + { + private static readonly string OptionsBase = $@"SOFTWARE\Microsoft\VisualStudio\{VsVersionUtils.GetVisualStudioVersion().VersionString()}\DialogPage\GoogleTestAdapter.VsPackage.OptionsPages."; + + private static readonly string GeneralOptionsPage = OptionsBase + "GeneralOptionsDialogPage"; + private static readonly string ParallelizationOptionsPage = OptionsBase + "ParallelizationOptionsDialogPage"; + + private const string SettingsVersion = "SettingsVersion"; + + private readonly TestDiscoveryOptionsDialogPage _testDiscoveryOptions; + private readonly TestExecutionOptionsDialogPage _testExecutionOptions; + private readonly WritableSettingsStore _settingsStore; + + public OptionsUpdater(TestDiscoveryOptionsDialogPage testDiscoveryOptions, TestExecutionOptionsDialogPage testExecutionOptions, + IServiceProvider serviceProvider) + { + _testDiscoveryOptions = testDiscoveryOptions; + _testExecutionOptions = testExecutionOptions; + + var settingsManager = new ShellSettingsManager(serviceProvider); + _settingsStore = settingsManager.GetWritableSettingsStore(SettingsScope.UserSettings); + } + + public void UpdateIfNecessary() + { + if (_settingsStore.PropertyExists(VersionProvider.CollectionName, SettingsVersion)) + return; + + UpdateSettings(); + + _settingsStore.SetString(VersionProvider.CollectionName, SettingsVersion, History.Versions.Last().ToString()); + } + + private void UpdateSettings() + { + _testDiscoveryOptions.TestDiscoveryTimeoutInSeconds = GetAndDeleteValue( + GeneralOptionsPage, + nameof(TestDiscoveryOptionsDialogPage.TestDiscoveryTimeoutInSeconds), + int.Parse, + SettingsWrapper.OptionTestDiscoveryTimeoutInSecondsDefaultValue); + _testDiscoveryOptions.TestDiscoveryRegex = GetAndDeleteValue( + GeneralOptionsPage, + nameof(TestDiscoveryOptionsDialogPage.TestDiscoveryRegex), + s => s, + SettingsWrapper.OptionTestDiscoveryRegexDefaultValue); + _testDiscoveryOptions.ParseSymbolInformation = GetAndDeleteValue( + GeneralOptionsPage, + nameof(TestDiscoveryOptionsDialogPage.ParseSymbolInformation), + bool.Parse, + SettingsWrapper.OptionParseSymbolInformationDefaultValue); + _testDiscoveryOptions.TestNameSeparator = GetAndDeleteValue( + GeneralOptionsPage, + nameof(TestDiscoveryOptionsDialogPage.TestNameSeparator), + s => s, + SettingsWrapper.OptionTestNameSeparatorDefaultValue); + _testDiscoveryOptions.TraitsRegexesBefore = GetAndDeleteValue( + GeneralOptionsPage, + nameof(TestDiscoveryOptionsDialogPage.TraitsRegexesBefore), + s => s, + SettingsWrapper.OptionTraitsRegexesDefaultValue); + _testDiscoveryOptions.TraitsRegexesAfter = GetAndDeleteValue( + GeneralOptionsPage, + nameof(TestDiscoveryOptionsDialogPage.TraitsRegexesAfter), + s => s, + SettingsWrapper.OptionTraitsRegexesDefaultValue); + + _testExecutionOptions.EnableParallelTestExecution = GetAndDeleteValue( + ParallelizationOptionsPage, + nameof(TestExecutionOptionsDialogPage.EnableParallelTestExecution), + bool.Parse, + SettingsWrapper.OptionEnableParallelTestExecutionDefaultValue); + _testExecutionOptions.MaxNrOfThreads = GetAndDeleteValue( + ParallelizationOptionsPage, + nameof(TestExecutionOptionsDialogPage.MaxNrOfThreads), + int.Parse, + SettingsWrapper.OptionMaxNrOfThreadsDefaultValue); + _testExecutionOptions.AdditionalPdbs = GetAndDeleteValue( + GeneralOptionsPage, + nameof(TestExecutionOptionsDialogPage.AdditionalPdbs), + s => s, + SettingsWrapper.OptionAdditionalPdbsDefaultValue); + _testExecutionOptions.AdditionalTestExecutionParams = GetAndDeleteValue( + GeneralOptionsPage, + nameof(TestExecutionOptionsDialogPage.AdditionalTestExecutionParams), + s => s, + SettingsWrapper.OptionAdditionalTestExecutionParamsDefaultValue); + _testExecutionOptions.BatchForTestSetup = GetAndDeleteValue( + GeneralOptionsPage, + nameof(TestExecutionOptionsDialogPage.BatchForTestSetup), + s => s, + SettingsWrapper.OptionBatchForTestSetupDefaultValue); + _testExecutionOptions.BatchForTestTeardown = GetAndDeleteValue( + GeneralOptionsPage, + nameof(TestExecutionOptionsDialogPage.BatchForTestTeardown), + s => s, + SettingsWrapper.OptionBatchForTestTeardownDefaultValue); + _testExecutionOptions.ExitCodeTestCase = GetAndDeleteValue( + GeneralOptionsPage, + nameof(TestExecutionOptionsDialogPage.ExitCodeTestCase), + s => s, + SettingsWrapper.OptionExitCodeTestCaseDefaultValue); + _testExecutionOptions.PathExtension = GetAndDeleteValue( + GeneralOptionsPage, + nameof(TestExecutionOptionsDialogPage.PathExtension), + s => s, + SettingsWrapper.OptionPathExtensionDefaultValue); + _testExecutionOptions.KillProcessesOnCancel = GetAndDeleteValue( + GeneralOptionsPage, + nameof(TestExecutionOptionsDialogPage.KillProcessesOnCancel), + bool.Parse, + SettingsWrapper.OptionKillProcessesOnCancelDefaultValue); + _testExecutionOptions.UseNewTestExecutionFramework2 = GetAndDeleteValue( + GeneralOptionsPage, + nameof(TestExecutionOptionsDialogPage.UseNewTestExecutionFramework2), + bool.Parse, + SettingsWrapper.OptionUseNewTestExecutionFrameworkDefaultValue); + _testExecutionOptions.WorkingDir = GetAndDeleteValue( + GeneralOptionsPage, + nameof(TestExecutionOptionsDialogPage.WorkingDir), + s => s, + SettingsWrapper.OptionWorkingDirDefaultValue); + } + + private static T GetAndDeleteValue(string optionsKey, string propertyName, Func map, T defaultValue) + { + try + { + var registryKey = Registry.CurrentUser.OpenSubKey(optionsKey, true); + string value = registryKey?.GetValue(propertyName)?.ToString(); + if (value != null) + { + try + { + registryKey.DeleteValue(propertyName); + } + catch (Exception) + { + // so what... + } + return map(value); + } + } + catch (Exception) + { + // too bad + } + + return defaultValue; + } + + //private void SetTestDiscoveryTimeoutInSeconds() + //{ + // try + // { + // string generalOptionsKey = + // @"SOFTWARE\Microsoft\VisualStudio\15.0\DialogPage\GoogleTestAdapter.VsPackage.OptionsPages.GeneralOptionsDialogPage"; + // var key = Registry.CurrentUser.OpenSubKey(generalOptionsKey, true); + // if (key != null) + // { + // string value = key.GetValue(nameof(_testDiscoveryOptions.TestDiscoveryTimeoutInSeconds))?.ToString(); + // if (value != null) + // { + // _testDiscoveryOptions.TestDiscoveryTimeoutInSeconds = int.Parse(value); + // key.DeleteValue(nameof(_testDiscoveryOptions.TestDiscoveryTimeoutInSeconds)); + // } + // } + // } + // catch (Exception e) + // { + // throw; + // } + //} + + } +} \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.Shared/VsPackage.Shared.projitems b/GoogleTestAdapter/VsPackage.Shared/VsPackage.Shared.projitems index e96b48fe6..bd4e0257f 100644 --- a/GoogleTestAdapter/VsPackage.Shared/VsPackage.Shared.projitems +++ b/GoogleTestAdapter/VsPackage.Shared/VsPackage.Shared.projitems @@ -34,6 +34,7 @@ Component +
From e4fe35d47b5ec3682322fa7078e686215b0a88c3 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Tue, 12 Mar 2019 07:57:56 +0100 Subject: [PATCH 46/81] added readme section, removed uncommented code --- .../Resources/ReleaseNotes/0.15.0.md | 1 + .../OptionsPages/OptionsUpdater.cs | 23 ------------------- 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md index d73a61def..6f42d0a3d 100644 --- a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md +++ b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md @@ -1,5 +1,6 @@ Changes in this version: * enhancement: setting the new option [*Exit code test name*](https://github.com/csoltenborn/GoogleTestAdapter#evaluating_exit_code) results in an additional test per test executable that passes if the executable's exit code is 0, and fails otherwise. Additionally, GTA parses the test executable's output for certain [tokens](https://github.com/csoltenborn/GoogleTestAdapter#evaluating_exit_code_tokens) which allow to influence the test's outcome and message. One interesting use case for this is memory leak detection; a complete, reusable [example](https://github.com/csoltenborn/GoogleTestAdapter#evaluating_exit_code_leak_example) is provided as part of GTA's [SampleTests solution](https://github.com/csoltenborn/GoogleTestAdapter/tree/master/SampleTests) ([#266](https://github.com/csoltenborn/GoogleTestAdapter/issues/266), thanks to [alfredskpoon](https://github.com/alfredskpoon) for report, example code, and testing) +* usability: reorganized options ([#271](https://github.com/csoltenborn/GoogleTestAdapter/issues/271)) * enhancement: the GTA extension is now loaded asynchronically by Visual Studio; the drawback is that support for Visual Studio 2012 had to be dropped ([#243](https://github.com/csoltenborn/GoogleTestAdapter/issues/243)) * enhancement: the *Show release notes* option has been removed, and this release notes dialog has been slightly changed and now has very funny buttons ([#270](https://github.com/csoltenborn/GoogleTestAdapter/issues/270)) * donations: thanks, John - I appreciate it! \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs index 6f41a7c0a..2709acf03 100644 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs @@ -160,28 +160,5 @@ private static T GetAndDeleteValue(string optionsKey, string propertyName, Fu return defaultValue; } - //private void SetTestDiscoveryTimeoutInSeconds() - //{ - // try - // { - // string generalOptionsKey = - // @"SOFTWARE\Microsoft\VisualStudio\15.0\DialogPage\GoogleTestAdapter.VsPackage.OptionsPages.GeneralOptionsDialogPage"; - // var key = Registry.CurrentUser.OpenSubKey(generalOptionsKey, true); - // if (key != null) - // { - // string value = key.GetValue(nameof(_testDiscoveryOptions.TestDiscoveryTimeoutInSeconds))?.ToString(); - // if (value != null) - // { - // _testDiscoveryOptions.TestDiscoveryTimeoutInSeconds = int.Parse(value); - // key.DeleteValue(nameof(_testDiscoveryOptions.TestDiscoveryTimeoutInSeconds)); - // } - // } - // } - // catch (Exception e) - // { - // throw; - // } - //} - } } \ No newline at end of file From 90adb5af7a074bb62855db3b2bc865d2d5abb903 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Wed, 13 Mar 2019 06:45:54 +0100 Subject: [PATCH 47/81] =?UTF-8?q?=C3=AEmproved=20robustness,=20added=20deb?= =?UTF-8?q?ug=20output?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../GoogleTestExtensionOptionsPage.cs | 10 ++++----- .../OptionsPages/OptionsUpdater.cs | 21 +++++++++++++++++-- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs index 0f4dd6caf..e05bd5001 100644 --- a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs @@ -18,7 +18,6 @@ using System.ServiceModel; using EnvDTE; using Microsoft.VisualStudio.AsyncPackageHelpers; -using Microsoft.Win32; using VsPackage.Shared.Settings; using TestDiscoveryOptionsDialogPage = GoogleTestAdapter.VsPackage.OptionsPages.TestDiscoveryOptionsDialogPage; @@ -106,7 +105,7 @@ private void InitializeOptions() _globalRunSettings.RunSettings = GetRunSettingsFromOptionPages(); - var optionsUpdater = new OptionsUpdater(_testDiscoveryOptions, _testExecutionOptions, this); + var optionsUpdater = new OptionsUpdater(_testDiscoveryOptions, _testExecutionOptions, this, new ActivityLogLogger(this, () => true)); optionsUpdater.UpdateIfNecessary(); _generalOptions.PropertyChanged += OptionsChanged; @@ -274,12 +273,14 @@ private RunSettings GetRunSettingsFromOptionPages() private void GetVisualStudioConfiguration(out string solutionDir, out string platformName, out string configurationName) { - solutionDir = platformName = configurationName = null; + var logger = new ActivityLogLogger(this, () => true); + solutionDir = platformName = configurationName = null; try { if (GetService(typeof(DTE)) is DTE dte) { + logger.DebugInfo($"dte.Solution.FullName: {dte.Solution.FullName}"); solutionDir = Path.GetDirectoryName(dte.Solution.FullName); if (dte.Solution.Projects.Count > 0) @@ -294,8 +295,7 @@ private void GetVisualStudioConfiguration(out string solutionDir, out string pla } catch (Exception e) { - new ActivityLogLogger(this, () => true) - .LogError($"Exception while receiving configuration info from Visual Studio{Environment.NewLine}{e}"); + logger.LogError($"Exception while receiving configuration info from Visual Studio.{Environment.NewLine}{e}"); } } } diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs index 2709acf03..b644ca42d 100644 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using GoogleTestAdapter.Common; using GoogleTestAdapter.Settings; using GoogleTestAdapter.TestAdapter.Framework; using GoogleTestAdapter.VsPackage.OptionsPages; @@ -21,26 +22,42 @@ public class OptionsUpdater private readonly TestDiscoveryOptionsDialogPage _testDiscoveryOptions; private readonly TestExecutionOptionsDialogPage _testExecutionOptions; + private readonly ILogger _logger; private readonly WritableSettingsStore _settingsStore; public OptionsUpdater(TestDiscoveryOptionsDialogPage testDiscoveryOptions, TestExecutionOptionsDialogPage testExecutionOptions, - IServiceProvider serviceProvider) + IServiceProvider serviceProvider, ILogger logger) { _testDiscoveryOptions = testDiscoveryOptions; _testExecutionOptions = testExecutionOptions; + _logger = logger; var settingsManager = new ShellSettingsManager(serviceProvider); _settingsStore = settingsManager.GetWritableSettingsStore(SettingsScope.UserSettings); } public void UpdateIfNecessary() + { + try + { + TryUpdateIfNecessary(); + } + catch (Exception e) + { + _logger.LogError($"Error while updating options: {e}"); + } + } + + private void TryUpdateIfNecessary() { if (_settingsStore.PropertyExists(VersionProvider.CollectionName, SettingsVersion)) return; UpdateSettings(); - _settingsStore.SetString(VersionProvider.CollectionName, SettingsVersion, History.Versions.Last().ToString()); + string versionString = History.Versions.Last().ToString(); + _logger.DebugInfo($"versionString: {versionString}"); + _settingsStore.SetString(VersionProvider.CollectionName, SettingsVersion, versionString); } private void UpdateSettings() From 3c5a05610dab178e034f53fdaabbafde433c6159 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Wed, 13 Mar 2019 07:42:39 +0100 Subject: [PATCH 48/81] moved some debug output into catch clauses --- .../VsPackage.Shared/GoogleTestExtensionOptionsPage.cs | 10 ++++++++-- .../VsPackage.Shared/OptionsPages/OptionsUpdater.cs | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs index e05bd5001..4ef8bdedd 100644 --- a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs @@ -280,8 +280,14 @@ private void GetVisualStudioConfiguration(out string solutionDir, out string pla { if (GetService(typeof(DTE)) is DTE dte) { - logger.DebugInfo($"dte.Solution.FullName: {dte.Solution.FullName}"); - solutionDir = Path.GetDirectoryName(dte.Solution.FullName); + try + { + solutionDir = Path.GetDirectoryName(dte.Solution.FullName); + } + catch (Exception e) + { + logger.LogError($"Exception caught while receiving solution dir from VS instance. dte.Solution.FullName: {dte.Solution.FullName}. Exception:{Environment.NewLine}{e}"); + } if (dte.Solution.Projects.Count > 0) { diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs index b644ca42d..9322964a1 100644 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs @@ -56,8 +56,14 @@ private void TryUpdateIfNecessary() UpdateSettings(); string versionString = History.Versions.Last().ToString(); - _logger.DebugInfo($"versionString: {versionString}"); - _settingsStore.SetString(VersionProvider.CollectionName, SettingsVersion, versionString); + try + { + _settingsStore.SetString(VersionProvider.CollectionName, SettingsVersion, versionString); + } + catch (Exception e) + { + _logger.LogError($"Exception caught while saving SettingsVersion. versionString: {versionString}. Exception:{Environment.NewLine}{e}"); + } } private void UpdateSettings() From 3b506bebabfb326edb4c39612ee5af8ef8c4ff0b Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Wed, 13 Mar 2019 07:55:00 +0100 Subject: [PATCH 49/81] refactoring --- .../OptionsPages/GeneralOptionsDialogPage.cs | 18 ++++---- .../GoogleTestOptionsDialogPage.cs | 23 +++++----- .../TestDiscoveryOptionsDialogPage.cs | 19 ++++---- .../TestExecutionOptionsDialogPage.cs | 45 ++++++++++--------- 4 files changed, 54 insertions(+), 51 deletions(-) diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs index 95cab58d7..39e981e00 100644 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs @@ -8,7 +8,7 @@ namespace GoogleTestAdapter.VsPackage.OptionsPages { [SuppressMessage("ReSharper", "UnusedMember.Global")] - public partial class GeneralOptionsDialogPage : NotifyingDialogPage + public class GeneralOptionsDialogPage : NotifyingDialogPage { #region Output @@ -17,8 +17,8 @@ public partial class GeneralOptionsDialogPage : NotifyingDialogPage [Description(SettingsWrapper.OptionPrintTestOutputDescription)] public bool PrintTestOutput { - get { return _printTestOutput; } - set { SetAndNotify(ref _printTestOutput, value); } + get => _printTestOutput; + set => SetAndNotify(ref _printTestOutput, value); } private bool _printTestOutput = SettingsWrapper.OptionPrintTestOutputDefaultValue; @@ -27,8 +27,8 @@ public bool PrintTestOutput [Description(SettingsWrapper.OptionDebugModeDescription)] public bool DebugMode { - get { return _debugMode; } - set { SetAndNotify(ref _debugMode, value); } + get => _debugMode; + set => SetAndNotify(ref _debugMode, value); } private bool _debugMode = SettingsWrapper.OptionDebugModeDefaultValue; @@ -37,8 +37,8 @@ public bool DebugMode [Description(SettingsWrapper.OptionTimestampOutputDescription)] public bool TimestampOutput { - get { return _timestampOutput; } - set { SetAndNotify(ref _timestampOutput, value); } + get => _timestampOutput; + set => SetAndNotify(ref _timestampOutput, value); } private bool _timestampOutput = SettingsWrapper.OptionTimestampOutputDefaultValue; @@ -51,8 +51,8 @@ public bool TimestampOutput [Description(SettingsWrapper.OptionSkipOriginCheckDescription)] public bool SkipOriginCheck { - get { return _skipOriginCheck; } - set { SetAndNotify(ref _skipOriginCheck, value); } + get => _skipOriginCheck; + set => SetAndNotify(ref _skipOriginCheck, value); } private bool _skipOriginCheck = SettingsWrapper.OptionSkipOriginCheckDefaultValue; diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GoogleTestOptionsDialogPage.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GoogleTestOptionsDialogPage.cs index a9004ddda..196681333 100644 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GoogleTestOptionsDialogPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GoogleTestOptionsDialogPage.cs @@ -3,6 +3,7 @@ using GoogleTestAdapter.Settings; using System; using System.ComponentModel; +// ReSharper disable LocalizableElement namespace GoogleTestAdapter.VsPackage.OptionsPages { @@ -16,8 +17,8 @@ public class GoogleTestOptionsDialogPage : NotifyingDialogPage [Description(SettingsWrapper.OptionCatchExceptionsDescription)] public bool CatchExceptions { - get { return _catchExceptions; } - set { SetAndNotify(ref _catchExceptions, value); } + get => _catchExceptions; + set => SetAndNotify(ref _catchExceptions, value); } private bool _catchExceptions = SettingsWrapper.OptionCatchExceptionsDefaultValue; @@ -26,8 +27,8 @@ public bool CatchExceptions [Description(SettingsWrapper.OptionBreakOnFailureDescription)] public bool BreakOnFailure { - get { return _breakOnFailure; } - set { SetAndNotify(ref _breakOnFailure, value); } + get => _breakOnFailure; + set => SetAndNotify(ref _breakOnFailure, value); } private bool _breakOnFailure = SettingsWrapper.OptionBreakOnFailureDefaultValue; @@ -40,8 +41,8 @@ public bool BreakOnFailure [Description(SettingsWrapper.OptionRunDisabledTestsDescription)] public bool RunDisabledTests { - get { return _runDisabledTests; } - set { SetAndNotify(ref _runDisabledTests, value); } + get => _runDisabledTests; + set => SetAndNotify(ref _runDisabledTests, value); } private bool _runDisabledTests = SettingsWrapper.OptionRunDisabledTestsDefaultValue; @@ -50,11 +51,11 @@ public bool RunDisabledTests [Description(SettingsWrapper.OptionNrOfTestRepetitionsDescription)] public int NrOfTestRepetitions { - get { return _nrOfTestRepetitions; } + get => _nrOfTestRepetitions; set { if (value < -1) - throw new ArgumentOutOfRangeException(nameof(value), value, "Expected a number greater than or equal to -1."); + throw new ArgumentOutOfRangeException(nameof(NrOfTestRepetitions), value, "Expected a number greater than or equal to -1."); SetAndNotify(ref _nrOfTestRepetitions, value); } } @@ -65,8 +66,8 @@ public int NrOfTestRepetitions [Description(SettingsWrapper.OptionShuffleTestsDescription)] public bool ShuffleTests { - get { return _shuffleTests; } - set { SetAndNotify(ref _shuffleTests, value); } + get => _shuffleTests; + set => SetAndNotify(ref _shuffleTests, value); } private bool _shuffleTests = SettingsWrapper.OptionShuffleTestsDefaultValue; @@ -75,7 +76,7 @@ public bool ShuffleTests [Description(SettingsWrapper.OptionShuffleTestsSeedDescription)] public int ShuffleTestsSeed { - get { return _shuffleTestsSeed; } + get => _shuffleTestsSeed; set { GoogleTestConstants.ValidateShuffleTestsSeedValue(value); diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestDiscoveryOptionsDialogPage.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestDiscoveryOptionsDialogPage.cs index 0ab3cd90c..ea61775ba 100644 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestDiscoveryOptionsDialogPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestDiscoveryOptionsDialogPage.cs @@ -4,6 +4,7 @@ using System; using System.ComponentModel; using GoogleTestAdapter.Helpers; +// ReSharper disable LocalizableElement namespace GoogleTestAdapter.VsPackage.OptionsPages { @@ -17,7 +18,7 @@ public class TestDiscoveryOptionsDialogPage : NotifyingDialogPage [Description(SettingsWrapper.OptionTestDiscoveryRegexDescription)] public string TestDiscoveryRegex { - get { return _testDiscoveryRegex; } + get => _testDiscoveryRegex; set { Utils.ValidateRegex(value); @@ -31,11 +32,11 @@ public string TestDiscoveryRegex [Description(SettingsWrapper.OptionTestDiscoveryTimeoutInSecondsDescription)] public int TestDiscoveryTimeoutInSeconds { - get { return _testDiscoveryTimeoutInSeconds; } + get => _testDiscoveryTimeoutInSeconds; set { if (value < 0) - throw new ArgumentOutOfRangeException(nameof(value), value, "Expected a number greater than or equal to 0."); + throw new ArgumentOutOfRangeException(nameof(TestDiscoveryTimeoutInSeconds), value, "Expected a number greater than or equal to 0."); SetAndNotify(ref _testDiscoveryTimeoutInSeconds, value); } } @@ -46,11 +47,11 @@ public int TestDiscoveryTimeoutInSeconds [Description(SettingsWrapper.OptionTestNameSeparatorDescription)] public string TestNameSeparator { - get { return _testNameSeparator; } + get => _testNameSeparator; set { if (value.Length > 16) - throw new ArgumentOutOfRangeException(nameof(value), value, "Expected string not longer than 16 characters."); + throw new ArgumentOutOfRangeException(nameof(TestNameSeparator), value, "Expected string not longer than 16 characters."); SetAndNotify(ref _testNameSeparator, value); } } @@ -61,8 +62,8 @@ public string TestNameSeparator [Description(SettingsWrapper.OptionParseSymbolInformationDescription)] public bool ParseSymbolInformation { - get { return _parseSymbolInformation; } - set { SetAndNotify(ref _parseSymbolInformation, value); } + get => _parseSymbolInformation; + set => SetAndNotify(ref _parseSymbolInformation, value); } private bool _parseSymbolInformation = SettingsWrapper.OptionParseSymbolInformationDefaultValue; @@ -75,7 +76,7 @@ public bool ParseSymbolInformation [Description(SettingsWrapper.OptionTraitsDescription)] public string TraitsRegexesBefore { - get { return _traitsRegexesBefore; } + get => _traitsRegexesBefore; set { Utils.ValidateTraitRegexes(value); @@ -89,7 +90,7 @@ public string TraitsRegexesBefore [Description(SettingsWrapper.OptionTraitsDescription)] public string TraitsRegexesAfter { - get { return _traitsRegexesAfter; } + get => _traitsRegexesAfter; set { Utils.ValidateTraitRegexes(value); diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestExecutionOptionsDialogPage.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestExecutionOptionsDialogPage.cs index 496b76e7a..11638f28e 100644 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestExecutionOptionsDialogPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestExecutionOptionsDialogPage.cs @@ -6,6 +6,7 @@ using System.ComponentModel; using System.Linq; using GoogleTestAdapter.Helpers; +// ReSharper disable LocalizableElement namespace GoogleTestAdapter.VsPackage.OptionsPages { @@ -19,8 +20,8 @@ public class TestExecutionOptionsDialogPage : NotifyingDialogPage [Description(SettingsWrapper.OptionEnableParallelTestExecutionDescription)] public bool EnableParallelTestExecution { - get { return _enableParallelTestExecution; } - set { SetAndNotify(ref _enableParallelTestExecution, value); } + get => _enableParallelTestExecution; + set => SetAndNotify(ref _enableParallelTestExecution, value); } private bool _enableParallelTestExecution = SettingsWrapper.OptionEnableParallelTestExecutionDefaultValue; @@ -29,11 +30,11 @@ public bool EnableParallelTestExecution [Description(SettingsWrapper.OptionMaxNrOfThreadsDescription)] public int MaxNrOfThreads { - get { return _maxNrOfThreads; } + get => _maxNrOfThreads; set { if (value < 0) - throw new ArgumentOutOfRangeException(nameof(value), value, "Expected a number greater than or equal to 0."); + throw new ArgumentOutOfRangeException(nameof(MaxNrOfThreads), value, "Expected a number greater than or equal to 0."); SetAndNotify(ref _maxNrOfThreads, value); } } @@ -48,7 +49,7 @@ public int MaxNrOfThreads [Description(SettingsWrapper.OptionAdditionalPdbsDescription)] public string AdditionalPdbs { - get { return _additionalPdbs; } + get => _additionalPdbs; set { var patterns = Utils.SplitAdditionalPdbs(_additionalPdbs); @@ -62,7 +63,7 @@ public string AdditionalPdbs } if (errorMessages.Any()) { - throw new Exception(string.Join(Environment.NewLine, errorMessages)); + throw new ArgumentException(string.Join(Environment.NewLine, errorMessages), nameof(AdditionalPdbs)); } SetAndNotify(ref _additionalPdbs, value); @@ -75,8 +76,8 @@ public string AdditionalPdbs [Description(SettingsWrapper.OptionWorkingDirDescription)] public string WorkingDir { - get { return _workingDirectory; } - set { SetAndNotify(ref _workingDirectory, value); } + get => _workingDirectory; + set => SetAndNotify(ref _workingDirectory, value); } private string _workingDirectory = SettingsWrapper.OptionWorkingDirDefaultValue; @@ -85,8 +86,8 @@ public string WorkingDir [Description(SettingsWrapper.OptionPathExtensionDescription)] public string PathExtension { - get { return _pathExtension; } - set { SetAndNotify(ref _pathExtension, value); } + get => _pathExtension; + set => SetAndNotify(ref _pathExtension, value); } private string _pathExtension = SettingsWrapper.OptionPathExtensionDefaultValue; @@ -95,8 +96,8 @@ public string PathExtension [Description(SettingsWrapper.OptionAdditionalTestExecutionParamsDescription)] public string AdditionalTestExecutionParams { - get { return _additionalTestExecutionParams; } - set { SetAndNotify(ref _additionalTestExecutionParams, value); } + get => _additionalTestExecutionParams; + set => SetAndNotify(ref _additionalTestExecutionParams, value); } private string _additionalTestExecutionParams = SettingsWrapper.OptionAdditionalTestExecutionParamsDefaultValue; @@ -110,8 +111,8 @@ public string AdditionalTestExecutionParams [Description(SettingsWrapper.OptionBatchForTestSetupDescription)] public string BatchForTestSetup { - get { return _batchForTestSetup; } - set { SetAndNotify(ref _batchForTestSetup, value); } + get => _batchForTestSetup; + set => SetAndNotify(ref _batchForTestSetup, value); } private string _batchForTestSetup = SettingsWrapper.OptionBatchForTestSetupDefaultValue; @@ -120,8 +121,8 @@ public string BatchForTestSetup [Description(SettingsWrapper.OptionBatchForTestTeardownDescription)] public string BatchForTestTeardown { - get { return _batchForTestTeardown; } - set { SetAndNotify(ref _batchForTestTeardown, value); } + get => _batchForTestTeardown; + set => SetAndNotify(ref _batchForTestTeardown, value); } private string _batchForTestTeardown = SettingsWrapper.OptionBatchForTestTeardownDefaultValue; @@ -135,8 +136,8 @@ public string BatchForTestTeardown [Description(SettingsWrapper.OptionKillProcessesOnCancelDescription)] public bool KillProcessesOnCancel { - get { return _killProcessesOnCancel; } - set { SetAndNotify(ref _killProcessesOnCancel, value); } + get => _killProcessesOnCancel; + set => SetAndNotify(ref _killProcessesOnCancel, value); } private bool _killProcessesOnCancel = SettingsWrapper.OptionKillProcessesOnCancelDefaultValue; @@ -145,8 +146,8 @@ public bool KillProcessesOnCancel [Description(SettingsWrapper.OptionUseNewTestExecutionFrameworkDescription)] public bool UseNewTestExecutionFramework2 { - get { return _useNewTestExecutionFramework; } - set { SetAndNotify(ref _useNewTestExecutionFramework, value); } + get => _useNewTestExecutionFramework; + set => SetAndNotify(ref _useNewTestExecutionFramework, value); } private bool _useNewTestExecutionFramework = SettingsWrapper.OptionUseNewTestExecutionFrameworkDefaultValue; @@ -155,8 +156,8 @@ public bool UseNewTestExecutionFramework2 [Description(SettingsWrapper.OptionExitCodeTestCaseDescription)] public string ExitCodeTestCase { - get { return _exitCodeTestCase; } - set { SetAndNotify(ref _exitCodeTestCase, value); } + get => _exitCodeTestCase; + set => SetAndNotify(ref _exitCodeTestCase, value); } private string _exitCodeTestCase = SettingsWrapper.OptionExitCodeTestCaseDefaultValue; From 31efa379f2c81f487c0d82afd8f6a165179e9575 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Thu, 14 Mar 2019 08:03:47 +0100 Subject: [PATCH 50/81] added missing release notes entry, removed ReleaseNotes note from settings xsd --- GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd | 1 - .../VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd b/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd index 8ddf7f113..3243a4ae1 100644 --- a/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd +++ b/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd @@ -58,7 +58,6 @@
- diff --git a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md index d73a61def..3b596f614 100644 --- a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md +++ b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md @@ -2,4 +2,5 @@ Changes in this version: * enhancement: setting the new option [*Exit code test name*](https://github.com/csoltenborn/GoogleTestAdapter#evaluating_exit_code) results in an additional test per test executable that passes if the executable's exit code is 0, and fails otherwise. Additionally, GTA parses the test executable's output for certain [tokens](https://github.com/csoltenborn/GoogleTestAdapter#evaluating_exit_code_tokens) which allow to influence the test's outcome and message. One interesting use case for this is memory leak detection; a complete, reusable [example](https://github.com/csoltenborn/GoogleTestAdapter#evaluating_exit_code_leak_example) is provided as part of GTA's [SampleTests solution](https://github.com/csoltenborn/GoogleTestAdapter/tree/master/SampleTests) ([#266](https://github.com/csoltenborn/GoogleTestAdapter/issues/266), thanks to [alfredskpoon](https://github.com/alfredskpoon) for report, example code, and testing) * enhancement: the GTA extension is now loaded asynchronically by Visual Studio; the drawback is that support for Visual Studio 2012 had to be dropped ([#243](https://github.com/csoltenborn/GoogleTestAdapter/issues/243)) * enhancement: the *Show release notes* option has been removed, and this release notes dialog has been slightly changed and now has very funny buttons ([#270](https://github.com/csoltenborn/GoogleTestAdapter/issues/270)) -* donations: thanks, John - I appreciate it! \ No newline at end of file +* maintenance: reduced code dulication of streaming and batch output parsers ([#263](https://github.com/csoltenborn/GoogleTestAdapter/issues/263)) +* donations: thanks, John and Jean-Michel - I appreciate it! \ No newline at end of file From 2865916ea377f27849d0d00822aa3ed6dee5569b Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Thu, 14 Mar 2019 18:24:24 +0100 Subject: [PATCH 51/81] corrected typo --- .../VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md index 3b596f614..a290bac01 100644 --- a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md +++ b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md @@ -2,5 +2,5 @@ Changes in this version: * enhancement: setting the new option [*Exit code test name*](https://github.com/csoltenborn/GoogleTestAdapter#evaluating_exit_code) results in an additional test per test executable that passes if the executable's exit code is 0, and fails otherwise. Additionally, GTA parses the test executable's output for certain [tokens](https://github.com/csoltenborn/GoogleTestAdapter#evaluating_exit_code_tokens) which allow to influence the test's outcome and message. One interesting use case for this is memory leak detection; a complete, reusable [example](https://github.com/csoltenborn/GoogleTestAdapter#evaluating_exit_code_leak_example) is provided as part of GTA's [SampleTests solution](https://github.com/csoltenborn/GoogleTestAdapter/tree/master/SampleTests) ([#266](https://github.com/csoltenborn/GoogleTestAdapter/issues/266), thanks to [alfredskpoon](https://github.com/alfredskpoon) for report, example code, and testing) * enhancement: the GTA extension is now loaded asynchronically by Visual Studio; the drawback is that support for Visual Studio 2012 had to be dropped ([#243](https://github.com/csoltenborn/GoogleTestAdapter/issues/243)) * enhancement: the *Show release notes* option has been removed, and this release notes dialog has been slightly changed and now has very funny buttons ([#270](https://github.com/csoltenborn/GoogleTestAdapter/issues/270)) -* maintenance: reduced code dulication of streaming and batch output parsers ([#263](https://github.com/csoltenborn/GoogleTestAdapter/issues/263)) +* maintenance: reduced code duplication of streaming and batch output parsers ([#263](https://github.com/csoltenborn/GoogleTestAdapter/issues/263)) * donations: thanks, John and Jean-Michel - I appreciate it! \ No newline at end of file From aabb24c2dc3463a3c6cb1dc16a6a2d58809ae1be Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Mon, 18 Mar 2019 20:37:25 +0100 Subject: [PATCH 52/81] options are only set if old options are read and deleted; ShowReleaseNotes option is deleted --- .../GoogleTestExtensionOptionsPage.cs | 2 +- .../ReleaseNotes/VersionProvider.cs | 21 +-- .../VsPackage.GTA/VsPackage.GTA.csproj | 3 + .../GoogleTestExtensionOptionsPage.cs | 11 +- .../Helpers/VsSettingsStorage.cs | 50 ++++++ .../OptionsPages/OptionsUpdater.cs | 142 ++++-------------- .../VsPackage.Shared.projitems | 1 + 7 files changed, 99 insertions(+), 131 deletions(-) create mode 100644 GoogleTestAdapter/VsPackage.Shared/Helpers/VsSettingsStorage.cs diff --git a/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs index 219932549..4516d9b79 100644 --- a/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs @@ -43,7 +43,7 @@ private void DisplayReleaseNotesIfNecessaryProc() private void TryDisplayReleaseNotesIfNecessary() { - var versionProvider = new VersionProvider(this); + var versionProvider = new VersionProvider(); Version formerlyInstalledVersion = versionProvider.FormerlyInstalledVersion; Version currentVersion = versionProvider.CurrentVersion; diff --git a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/VersionProvider.cs b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/VersionProvider.cs index 2e7cbbccb..e0f29886c 100644 --- a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/VersionProvider.cs +++ b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/VersionProvider.cs @@ -1,35 +1,22 @@ using System; using System.Reflection; -using Microsoft.VisualStudio.Settings; -using Microsoft.VisualStudio.Shell.Settings; +using GoogleTestAdapter.VsPackage.GTA.Helpers; namespace GoogleTestAdapter.VsPackage.ReleaseNotes { internal class VersionProvider { - public const string CollectionName = "GoogleTestAdapter"; private const string VersionPropertyName = "LastVersion"; - private readonly WritableSettingsStore _settingsStore; - - internal VersionProvider(IServiceProvider serviceProvider) - { - var settingsManager = new ShellSettingsManager(serviceProvider); - _settingsStore = settingsManager.GetWritableSettingsStore(SettingsScope.UserSettings); - - if (!_settingsStore.CollectionExists(CollectionName)) - _settingsStore.CreateCollection(CollectionName); - } - internal Version FormerlyInstalledVersion { get { - if (!_settingsStore.PropertyExists(CollectionName, VersionPropertyName)) + if (!VsSettingsStorage.Instance.PropertyExists(VersionPropertyName)) return null; - string versionString = _settingsStore.GetString(CollectionName, VersionPropertyName); + string versionString = VsSettingsStorage.Instance.GetString(VersionPropertyName); return Version.Parse(versionString); } } @@ -45,7 +32,7 @@ internal Version CurrentVersion internal void UpdateLastVersion() { - _settingsStore.SetString(CollectionName, VersionPropertyName, CurrentVersion.ToString()); + VsSettingsStorage.Instance.SetString(VersionPropertyName, CurrentVersion.ToString()); } } diff --git a/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj b/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj index b8bf6f752..bb47d69cc 100644 --- a/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj +++ b/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj @@ -408,6 +408,9 @@ TestAdapter + + + diff --git a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs index 4ef8bdedd..766172f8a 100644 --- a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs @@ -17,6 +17,7 @@ using System.Runtime.InteropServices; using System.ServiceModel; using EnvDTE; +using GoogleTestAdapter.VsPackage.GTA.Helpers; using Microsoft.VisualStudio.AsyncPackageHelpers; using VsPackage.Shared.Settings; using TestDiscoveryOptionsDialogPage = GoogleTestAdapter.VsPackage.OptionsPages.TestDiscoveryOptionsDialogPage; @@ -78,6 +79,8 @@ IVsTask IAsyncLoadablePackageInitialize.Initialize(IAsyncServiceProvider service var componentModel = await serviceProvider.GetServiceAsync(typeof(SComponentModel)); _globalRunSettings = componentModel.GetService(); + VsSettingsStorage.Init(this); + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); DoInitialize(); @@ -103,11 +106,11 @@ private void InitializeOptions() (TestExecutionOptionsDialogPage) GetDialogPage(typeof(TestExecutionOptionsDialogPage)); _googleTestOptions = (GoogleTestOptionsDialogPage) GetDialogPage(typeof(GoogleTestOptionsDialogPage)); - _globalRunSettings.RunSettings = GetRunSettingsFromOptionPages(); - - var optionsUpdater = new OptionsUpdater(_testDiscoveryOptions, _testExecutionOptions, this, new ActivityLogLogger(this, () => true)); + var optionsUpdater = new OptionsUpdater(_testDiscoveryOptions, _testExecutionOptions, new ActivityLogLogger(this, () => true)); optionsUpdater.UpdateIfNecessary(); + _globalRunSettings.RunSettings = GetRunSettingsFromOptionPages(); + _generalOptions.PropertyChanged += OptionsChanged; _testDiscoveryOptions.PropertyChanged += OptionsChanged; _testExecutionOptions.PropertyChanged += OptionsChanged; @@ -306,4 +309,4 @@ private void GetVisualStudioConfiguration(out string solutionDir, out string pla } } -} +} \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.Shared/Helpers/VsSettingsStorage.cs b/GoogleTestAdapter/VsPackage.Shared/Helpers/VsSettingsStorage.cs new file mode 100644 index 000000000..9c39031e4 --- /dev/null +++ b/GoogleTestAdapter/VsPackage.Shared/Helpers/VsSettingsStorage.cs @@ -0,0 +1,50 @@ +using System; +using Microsoft.VisualStudio.Settings; +using Microsoft.VisualStudio.Shell.Settings; + +namespace GoogleTestAdapter.VsPackage.GTA.Helpers +{ + public class VsSettingsStorage + { + private const string CollectionName = "GoogleTestAdapter"; + + public static VsSettingsStorage Instance { get; private set; } + + public static void Init(IServiceProvider serviceProvider) + { + if (Instance != null) + { + throw new Exception(); + } + Instance = new VsSettingsStorage(serviceProvider); + } + + + private readonly WritableSettingsStore _settingsStore; + + private VsSettingsStorage(IServiceProvider serviceProvider) + { + var settingsManager = new ShellSettingsManager(serviceProvider); + _settingsStore = settingsManager.GetWritableSettingsStore(SettingsScope.UserSettings); + + if (!_settingsStore.CollectionExists(CollectionName)) + _settingsStore.CreateCollection(CollectionName); + } + + public bool PropertyExists(string propertyName) + { + return _settingsStore.PropertyExists(CollectionName, propertyName); + } + + public string GetString(string propertyName) + { + return _settingsStore.GetString(CollectionName, propertyName); + } + + public void SetString(string propertyName, string newValue) + { + _settingsStore.SetString(CollectionName, propertyName, newValue); + } + + } +} \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs index 9322964a1..28ff6875f 100644 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs @@ -1,12 +1,10 @@ using System; using System.Linq; using GoogleTestAdapter.Common; -using GoogleTestAdapter.Settings; using GoogleTestAdapter.TestAdapter.Framework; +using GoogleTestAdapter.VsPackage.GTA.Helpers; using GoogleTestAdapter.VsPackage.OptionsPages; using GoogleTestAdapter.VsPackage.ReleaseNotes; -using Microsoft.VisualStudio.Settings; -using Microsoft.VisualStudio.Shell.Settings; using Microsoft.Win32; namespace VsPackage.Shared.Settings @@ -23,17 +21,13 @@ public class OptionsUpdater private readonly TestDiscoveryOptionsDialogPage _testDiscoveryOptions; private readonly TestExecutionOptionsDialogPage _testExecutionOptions; private readonly ILogger _logger; - private readonly WritableSettingsStore _settingsStore; - public OptionsUpdater(TestDiscoveryOptionsDialogPage testDiscoveryOptions, TestExecutionOptionsDialogPage testExecutionOptions, - IServiceProvider serviceProvider, ILogger logger) + public OptionsUpdater(TestDiscoveryOptionsDialogPage testDiscoveryOptions, + TestExecutionOptionsDialogPage testExecutionOptions, ILogger logger) { _testDiscoveryOptions = testDiscoveryOptions; _testExecutionOptions = testExecutionOptions; _logger = logger; - - var settingsManager = new ShellSettingsManager(serviceProvider); - _settingsStore = settingsManager.GetWritableSettingsStore(SettingsScope.UserSettings); } public void UpdateIfNecessary() @@ -50,15 +44,14 @@ public void UpdateIfNecessary() private void TryUpdateIfNecessary() { - if (_settingsStore.PropertyExists(VersionProvider.CollectionName, SettingsVersion)) + if (VsSettingsStorage.Instance.PropertyExists(SettingsVersion)) return; - UpdateSettings(); - string versionString = History.Versions.Last().ToString(); try { - _settingsStore.SetString(VersionProvider.CollectionName, SettingsVersion, versionString); + VsSettingsStorage.Instance.SetString(SettingsVersion, versionString); + UpdateSettings(); } catch (Exception e) { @@ -68,111 +61,41 @@ private void TryUpdateIfNecessary() private void UpdateSettings() { - _testDiscoveryOptions.TestDiscoveryTimeoutInSeconds = GetAndDeleteValue( - GeneralOptionsPage, - nameof(TestDiscoveryOptionsDialogPage.TestDiscoveryTimeoutInSeconds), - int.Parse, - SettingsWrapper.OptionTestDiscoveryTimeoutInSecondsDefaultValue); - _testDiscoveryOptions.TestDiscoveryRegex = GetAndDeleteValue( - GeneralOptionsPage, - nameof(TestDiscoveryOptionsDialogPage.TestDiscoveryRegex), - s => s, - SettingsWrapper.OptionTestDiscoveryRegexDefaultValue); - _testDiscoveryOptions.ParseSymbolInformation = GetAndDeleteValue( - GeneralOptionsPage, - nameof(TestDiscoveryOptionsDialogPage.ParseSymbolInformation), - bool.Parse, - SettingsWrapper.OptionParseSymbolInformationDefaultValue); - _testDiscoveryOptions.TestNameSeparator = GetAndDeleteValue( - GeneralOptionsPage, - nameof(TestDiscoveryOptionsDialogPage.TestNameSeparator), - s => s, - SettingsWrapper.OptionTestNameSeparatorDefaultValue); - _testDiscoveryOptions.TraitsRegexesBefore = GetAndDeleteValue( - GeneralOptionsPage, - nameof(TestDiscoveryOptionsDialogPage.TraitsRegexesBefore), - s => s, - SettingsWrapper.OptionTraitsRegexesDefaultValue); - _testDiscoveryOptions.TraitsRegexesAfter = GetAndDeleteValue( - GeneralOptionsPage, - nameof(TestDiscoveryOptionsDialogPage.TraitsRegexesAfter), - s => s, - SettingsWrapper.OptionTraitsRegexesDefaultValue); + if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestDiscoveryOptionsDialogPage.TestDiscoveryTimeoutInSeconds), int.Parse, out var testDiscoveryTimeoutInSeconds)) { _testDiscoveryOptions.TestDiscoveryTimeoutInSeconds = testDiscoveryTimeoutInSeconds; } + if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestDiscoveryOptionsDialogPage.TestDiscoveryRegex), s => s, out var testDiscoveryRegex)) { _testDiscoveryOptions.TestDiscoveryRegex = testDiscoveryRegex; } + if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestDiscoveryOptionsDialogPage.ParseSymbolInformation), bool.Parse, out var parseSymbolInformation)) { _testDiscoveryOptions.ParseSymbolInformation = parseSymbolInformation; } + if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestDiscoveryOptionsDialogPage.TestNameSeparator), s => s, out var testNameSeparator)) { _testDiscoveryOptions.TestNameSeparator = testNameSeparator; } + if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestDiscoveryOptionsDialogPage.TraitsRegexesBefore), s => s, out var traitsRegexesBefore)) { _testDiscoveryOptions.TraitsRegexesBefore = traitsRegexesBefore; } + if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestDiscoveryOptionsDialogPage.TraitsRegexesAfter), s => s, out var traitsRegexesAfter)) { _testDiscoveryOptions.TraitsRegexesAfter = traitsRegexesAfter; } + + if (GetAndDeleteValue(ParallelizationOptionsPage, nameof(TestExecutionOptionsDialogPage.EnableParallelTestExecution), bool.Parse, out var enableParallelTestExecution)) { _testExecutionOptions.EnableParallelTestExecution = enableParallelTestExecution; } + if (GetAndDeleteValue(ParallelizationOptionsPage, nameof(TestExecutionOptionsDialogPage.MaxNrOfThreads), int.Parse, out var maxNrOfThreads)) { _testExecutionOptions.MaxNrOfThreads = maxNrOfThreads; } + if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestExecutionOptionsDialogPage.AdditionalPdbs), s => s, out var additionalPdbs)) { _testExecutionOptions.AdditionalPdbs = additionalPdbs; } + if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestExecutionOptionsDialogPage.AdditionalTestExecutionParams), s => s, out var additionalTestExecutionParams)) { _testExecutionOptions.AdditionalTestExecutionParams = additionalTestExecutionParams; } + if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestExecutionOptionsDialogPage.BatchForTestSetup), s => s, out var batchForTestSetup)) { _testExecutionOptions.BatchForTestSetup = batchForTestSetup; } + if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestExecutionOptionsDialogPage.BatchForTestTeardown), s => s, out var batchForTestTeardown)) { _testExecutionOptions.BatchForTestTeardown = batchForTestTeardown; } + if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestExecutionOptionsDialogPage.ExitCodeTestCase), s => s, out var exitCodeTestCase)) { _testExecutionOptions.ExitCodeTestCase = exitCodeTestCase; } + if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestExecutionOptionsDialogPage.PathExtension), s => s, out var pathExtension)) { _testExecutionOptions.PathExtension = pathExtension; } + if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestExecutionOptionsDialogPage.KillProcessesOnCancel), bool.Parse, out var killProcessesOnCancel)) { _testExecutionOptions.KillProcessesOnCancel = killProcessesOnCancel; } + if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestExecutionOptionsDialogPage.UseNewTestExecutionFramework2), bool.Parse, out var useNewTestExecutionFramework2)) { _testExecutionOptions.UseNewTestExecutionFramework2 = useNewTestExecutionFramework2; } + if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestExecutionOptionsDialogPage.WorkingDir), s => s, out var workingDir)) { _testExecutionOptions.WorkingDir = workingDir; } - _testExecutionOptions.EnableParallelTestExecution = GetAndDeleteValue( - ParallelizationOptionsPage, - nameof(TestExecutionOptionsDialogPage.EnableParallelTestExecution), - bool.Parse, - SettingsWrapper.OptionEnableParallelTestExecutionDefaultValue); - _testExecutionOptions.MaxNrOfThreads = GetAndDeleteValue( - ParallelizationOptionsPage, - nameof(TestExecutionOptionsDialogPage.MaxNrOfThreads), - int.Parse, - SettingsWrapper.OptionMaxNrOfThreadsDefaultValue); - _testExecutionOptions.AdditionalPdbs = GetAndDeleteValue( - GeneralOptionsPage, - nameof(TestExecutionOptionsDialogPage.AdditionalPdbs), - s => s, - SettingsWrapper.OptionAdditionalPdbsDefaultValue); - _testExecutionOptions.AdditionalTestExecutionParams = GetAndDeleteValue( - GeneralOptionsPage, - nameof(TestExecutionOptionsDialogPage.AdditionalTestExecutionParams), - s => s, - SettingsWrapper.OptionAdditionalTestExecutionParamsDefaultValue); - _testExecutionOptions.BatchForTestSetup = GetAndDeleteValue( - GeneralOptionsPage, - nameof(TestExecutionOptionsDialogPage.BatchForTestSetup), - s => s, - SettingsWrapper.OptionBatchForTestSetupDefaultValue); - _testExecutionOptions.BatchForTestTeardown = GetAndDeleteValue( - GeneralOptionsPage, - nameof(TestExecutionOptionsDialogPage.BatchForTestTeardown), - s => s, - SettingsWrapper.OptionBatchForTestTeardownDefaultValue); - _testExecutionOptions.ExitCodeTestCase = GetAndDeleteValue( - GeneralOptionsPage, - nameof(TestExecutionOptionsDialogPage.ExitCodeTestCase), - s => s, - SettingsWrapper.OptionExitCodeTestCaseDefaultValue); - _testExecutionOptions.PathExtension = GetAndDeleteValue( - GeneralOptionsPage, - nameof(TestExecutionOptionsDialogPage.PathExtension), - s => s, - SettingsWrapper.OptionPathExtensionDefaultValue); - _testExecutionOptions.KillProcessesOnCancel = GetAndDeleteValue( - GeneralOptionsPage, - nameof(TestExecutionOptionsDialogPage.KillProcessesOnCancel), - bool.Parse, - SettingsWrapper.OptionKillProcessesOnCancelDefaultValue); - _testExecutionOptions.UseNewTestExecutionFramework2 = GetAndDeleteValue( - GeneralOptionsPage, - nameof(TestExecutionOptionsDialogPage.UseNewTestExecutionFramework2), - bool.Parse, - SettingsWrapper.OptionUseNewTestExecutionFrameworkDefaultValue); - _testExecutionOptions.WorkingDir = GetAndDeleteValue( - GeneralOptionsPage, - nameof(TestExecutionOptionsDialogPage.WorkingDir), - s => s, - SettingsWrapper.OptionWorkingDirDefaultValue); + GetAndDeleteValue(GeneralOptionsPage, "ShowReleaseNotes", bool.Parse, out _); } - private static T GetAndDeleteValue(string optionsKey, string propertyName, Func map, T defaultValue) + private static bool GetAndDeleteValue(string optionsKey, string propertyName, Func map, out T value) { try { - var registryKey = Registry.CurrentUser.OpenSubKey(optionsKey, true); - string value = registryKey?.GetValue(propertyName)?.ToString(); - if (value != null) + using (var registryKey = Registry.CurrentUser.OpenSubKey(optionsKey, true)) { - try + string valueString = registryKey?.GetValue(propertyName)?.ToString(); + if (valueString != null) { + value = map(valueString); registryKey.DeleteValue(propertyName); + return true; } - catch (Exception) - { - // so what... - } - return map(value); } } catch (Exception) @@ -180,7 +103,8 @@ private static T GetAndDeleteValue(string optionsKey, string propertyName, Fu // too bad } - return defaultValue; + value = default(T); + return false; } } diff --git a/GoogleTestAdapter/VsPackage.Shared/VsPackage.Shared.projitems b/GoogleTestAdapter/VsPackage.Shared/VsPackage.Shared.projitems index bd4e0257f..14bd107ef 100644 --- a/GoogleTestAdapter/VsPackage.Shared/VsPackage.Shared.projitems +++ b/GoogleTestAdapter/VsPackage.Shared/VsPackage.Shared.projitems @@ -18,6 +18,7 @@ + Component From 32e8d4580609a6ed341e39513fa200b27f964789 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Fri, 22 Mar 2019 06:32:45 +0100 Subject: [PATCH 53/81] fixed link in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 52c49a042..cfdf8e75c 100644 --- a/README.md +++ b/README.md @@ -127,7 +127,7 @@ Note that a test executable might be run more than once by GTA (e.g., if tests a ##### Example usage: Memory leak detection -An example usage of the *Exit code test case* can be found as part of the SampleTests solution: [Project *MemoryLeakTests*](https://github.com/csoltenborn/GoogleTestAdapter/tree/master/SampleTests/MemoryLeakTests) makes use of MS' memory leak detection facilities and reports the results to VS via an exit code test. The approach can easily be re-used for other Google Test projects: +An example usage of the *Exit code test case* can be found as part of the SampleTests solution: [Project *MemoryLeakTests*](https://github.com/csoltenborn/GoogleTestAdapter/tree/master/SampleTests/LeakCheckTests) makes use of MS' memory leak detection facilities and reports the results to VS via an exit code test. The approach can easily be re-used for other Google Test projects: * add files [`gta_leak_detection.h`](https://github.com/csoltenborn/GoogleTestAdapter/tree/master/SampleTests/LeakCheckTests/gta_leak_detection.h) and [`gta_leak_detection.cpp`](https://github.com/csoltenborn/GoogleTestAdapter/tree/master/SampleTests/LeakCheckTests/gta_leak_detection.cpp) to the project * in the project's `main` method, return the result of `gta_leak_detection::PerformLeakDetection(argc, argv, RUN_ALL_TESTS())` (instead of the result of `RUN_ALL_TESTS()`, see [example](https://github.com/csoltenborn/GoogleTestAdapter/tree/master/SampleTests/LeakCheckTests/main.cpp)) * set the following GTA options (probably through the settings file): From 67427f38dada012954ce343342882d8998392081 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sat, 30 Mar 2019 16:18:23 +0100 Subject: [PATCH 54/81] added missing VsSettingsStorage initialization --- .../VsPackage.Shared/GoogleTestExtensionOptionsPage.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs index 766172f8a..192d6bd53 100644 --- a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs @@ -62,6 +62,9 @@ protected override void Initialize() { var componentModel = (IComponentModel) GetGlobalService(typeof(SComponentModel)); _globalRunSettings = componentModel.GetService(); + + VsSettingsStorage.Init(this); + DoInitialize(); } } From bb915ede18d84ca3c86d2012c9ca2cc3e1f029f1 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sat, 30 Mar 2019 16:38:35 +0100 Subject: [PATCH 55/81] moved release notes to correct file, improved 0.14.* release notes --- .../VsPackage.GTA/Resources/ReleaseNotes/0.14.0.md | 3 --- .../VsPackage.GTA/Resources/ReleaseNotes/0.14.1.md | 3 --- .../VsPackage.GTA/Resources/ReleaseNotes/0.14.2.md | 3 --- .../VsPackage.GTA/Resources/ReleaseNotes/0.14.3.md | 3 --- .../VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md | 2 -- .../VsPackage.GTA/Resources/ReleaseNotes/0.16.0.md | 1 + GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj | 3 +++ 7 files changed, 4 insertions(+), 14 deletions(-) create mode 100644 GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.16.0.md diff --git a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.14.0.md b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.14.0.md index b8af02734..6e30a3118 100644 --- a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.14.0.md +++ b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.14.0.md @@ -1,6 +1,3 @@ -**Announcement:** Microsoft has decided to force VS extensions to make use of [asynchronous package loading](https://blogs.msdn.microsoft.com/visualstudio/2018/05/16/improving-the-responsiveness-of-critical-scenarios-by-updating-auto-load-behavior-for-extensions/). Since they only provide backwards compatibility for this down to VS2013, this will be **the last version with support for VS2012**. Support for asynchronous package loading will be added in the next version of GTA. - -Changes in this version: * enhancement: new placeholders `$(PlatformName)` and `$(ConfigurationName)` are available ([#170](https://github.com/csoltenborn/GoogleTestAdapter/issues/170)) * enhancement: the option *Use new test execution framework (experimental)* has been renamed into *Use native debugging*. It now only affects debugging of tests: native debuging supports test crash detection and printing test output ([#106](https://github.com/csoltenborn/GoogleTestAdapter/issues/106)) * bugfix: tests without source location did not receive traits by regex ([#249](https://github.com/csoltenborn/GoogleTestAdapter/issues/249)) diff --git a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.14.1.md b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.14.1.md index 8392819c7..f462f9483 100644 --- a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.14.1.md +++ b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.14.1.md @@ -1,4 +1 @@ -**Announcement:** Microsoft has decided to force VS extensions to make use of [asynchronous package loading](https://blogs.msdn.microsoft.com/visualstudio/2018/05/16/improving-the-responsiveness-of-critical-scenarios-by-updating-auto-load-behavior-for-extensions/). Since they only provide backwards compatibility for this down to VS2013, 0.14.* will be **the last version with support for VS2012**. Support for asynchronous package loading will be added in the next version of GTA. - -Changes in this version: * bugfix: a dynamically loaded class could not be instantiated any more for some reason, causing the GTA package to crash when loaded ([#250](https://github.com/csoltenborn/GoogleTestAdapter/issues/250)) diff --git a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.14.2.md b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.14.2.md index 5e2661c35..7406bdd83 100644 --- a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.14.2.md +++ b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.14.2.md @@ -1,4 +1 @@ -**Announcement:** Microsoft has decided to force VS extensions to make use of [asynchronous package loading](https://blogs.msdn.microsoft.com/visualstudio/2018/05/16/improving-the-responsiveness-of-critical-scenarios-by-updating-auto-load-behavior-for-extensions/). Since they only provide backwards compatibility for this down to VS2013, 0.14.* will be **the last version with support for VS2012**. Support for asynchronous package loading will be added in the next version of GTA. - -Changes in this version: * enhancement: GTA can now also be installed into Visual Studio 2019 ([#243](https://github.com/csoltenborn/GoogleTestAdapter/issues/243)) diff --git a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.14.3.md b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.14.3.md index 2a608d29c..e0fb8d4d7 100644 --- a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.14.3.md +++ b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.14.3.md @@ -1,5 +1,2 @@ -**Announcement:** Microsoft has decided to force VS extensions to make use of [asynchronous package loading](https://blogs.msdn.microsoft.com/visualstudio/2018/05/16/improving-the-responsiveness-of-critical-scenarios-by-updating-auto-load-behavior-for-extensions/). Since they only provide backwards compatibility for this down to VS2013, 0.14.* will be **the last version with support for VS2012**. Support for asynchronous package loading will be added in the next version of GTA. - -Changes in this version: * enhancement: GTA now also supports the (not yet released) macro `GTEST_SKIP()` ([#260](https://github.com/csoltenborn/GoogleTestAdapter/issues/260), thanks to [Sixten Hilborn](https://github.com/sixten-hilborn) for report and testing) * bugfix: some broken links of the README have been fixed ([#257](https://github.com/csoltenborn/GoogleTestAdapter/issues/257) and [#258](https://github.com/csoltenborn/GoogleTestAdapter/issues/258), thanks to [Jim Orcheson](https://github.com/jimorc) for report and pull request) diff --git a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md index df5ecc94b..55460be96 100644 --- a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md +++ b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md @@ -1,6 +1,4 @@ -Changes in this version: * enhancement: setting the new option [*Exit code test name*](https://github.com/csoltenborn/GoogleTestAdapter#evaluating_exit_code) results in an additional test per test executable that passes if the executable's exit code is 0, and fails otherwise. Additionally, GTA parses the test executable's output for certain [tokens](https://github.com/csoltenborn/GoogleTestAdapter#evaluating_exit_code_tokens) which allow to influence the test's outcome and message. One interesting use case for this is memory leak detection; a complete, reusable [example](https://github.com/csoltenborn/GoogleTestAdapter#evaluating_exit_code_leak_example) is provided as part of GTA's [SampleTests solution](https://github.com/csoltenborn/GoogleTestAdapter/tree/master/SampleTests) ([#266](https://github.com/csoltenborn/GoogleTestAdapter/issues/266), thanks to [alfredskpoon](https://github.com/alfredskpoon) for report, example code, and testing) -* usability: reorganized options ([#271](https://github.com/csoltenborn/GoogleTestAdapter/issues/271)) * enhancement: the GTA extension is now loaded asynchronically by Visual Studio; the drawback is that support for Visual Studio 2012 had to be dropped ([#243](https://github.com/csoltenborn/GoogleTestAdapter/issues/243)) * enhancement: the *Show release notes* option has been removed, and this release notes dialog has been slightly changed and now has very funny buttons ([#270](https://github.com/csoltenborn/GoogleTestAdapter/issues/270)) * maintenance: reduced code duplication of streaming and batch output parsers ([#263](https://github.com/csoltenborn/GoogleTestAdapter/issues/263)) diff --git a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.16.0.md b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.16.0.md new file mode 100644 index 000000000..7dc9acfb9 --- /dev/null +++ b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.16.0.md @@ -0,0 +1 @@ +* usability: reorganized options ([#271](https://github.com/csoltenborn/GoogleTestAdapter/issues/271)) diff --git a/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj b/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj index bb47d69cc..d023155e9 100644 --- a/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj +++ b/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj @@ -230,6 +230,9 @@ PreserveNewest + + PreserveNewest + From de72724a4285a0ee86003109553d0a239551a42a Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sat, 30 Mar 2019 21:16:09 +0100 Subject: [PATCH 56/81] refactoring --- .../Core.Tests/GoogleTestDiscovererTests.cs | 2 +- .../Runners/SequentialTestRunnerTests.cs | 4 +- .../Settings/SettingsWrapperTests.cs | 18 +- GoogleTestAdapter/Core/Core.csproj | 3 + .../Core/Settings/PlaceholderReplacer.cs | 245 ++++++ .../Core/Settings/RegexTraitPair.cs | 21 + .../Core/Settings/SettingsPrinter.cs | 48 ++ .../Core/Settings/SettingsWrapper.cs | 699 +++++++----------- .../TestExecutorTestsBase.cs | 8 +- .../TestExecutionOptionsDialogPage.cs | 2 - 10 files changed, 585 insertions(+), 465 deletions(-) create mode 100644 GoogleTestAdapter/Core/Settings/PlaceholderReplacer.cs create mode 100644 GoogleTestAdapter/Core/Settings/RegexTraitPair.cs create mode 100644 GoogleTestAdapter/Core/Settings/SettingsPrinter.cs diff --git a/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTests.cs b/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTests.cs index e6500b1fe..b04fcc68e 100644 --- a/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTests.cs +++ b/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTests.cs @@ -204,7 +204,7 @@ public void GetTestsFromExecutable_WithPathExtension_FindsTestsWithLocation() try { string targetExe = Path.Combine(baseDir, "exe", Path.GetFileName(TestResources.DllTests_ReleaseX86)); - MockOptions.Setup(o => o.PathExtension).Returns(SettingsWrapper.ExecutableDirPlaceholder + @"\..\dll"); + MockOptions.Setup(o => o.PathExtension).Returns(PlaceholderReplacer.ExecutableDirPlaceholder + @"\..\dll"); var discoverer = new GoogleTestDiscoverer(TestEnvironment.Logger, TestEnvironment.Options); IList testCases = discoverer.GetTestsFromExecutable(targetExe); diff --git a/GoogleTestAdapter/Core.Tests/Runners/SequentialTestRunnerTests.cs b/GoogleTestAdapter/Core.Tests/Runners/SequentialTestRunnerTests.cs index 2e67b498f..95a842cce 100644 --- a/GoogleTestAdapter/Core.Tests/Runners/SequentialTestRunnerTests.cs +++ b/GoogleTestAdapter/Core.Tests/Runners/SequentialTestRunnerTests.cs @@ -58,7 +58,7 @@ public void RunTests_WorkingDirNotSet_TestFails() public void RunTests_WorkingDirSetForSolution_TestPasses() { var testCase = TestDataCreator.GetTestCases("WorkingDir.IsSolutionDirectory").First(); - var settings = CreateSettings(SettingsWrapper.SolutionDirPlaceholder, null); + var settings = CreateSettings(PlaceholderReplacer.SolutionDirPlaceholder, null); var runner = new SequentialTestRunner("", 0, "", MockFrameworkReporter.Object, TestEnvironment.Logger, settings, new SchedulingAnalyzer(TestEnvironment.Logger)); runner.RunTests(testCase.Yield(), false, ProcessExecutorFactory); @@ -73,7 +73,7 @@ public void RunTests_WorkingDirSetForSolution_TestPasses() public void RunTests_WorkingDirSetForProject_TestPasses() { TestCase testCase = TestDataCreator.GetTestCases("WorkingDir.IsSolutionDirectory").First(); - var settings = CreateSettings("foo", SettingsWrapper.SolutionDirPlaceholder); + var settings = CreateSettings("foo", PlaceholderReplacer.SolutionDirPlaceholder); var runner = new SequentialTestRunner("", 0, "", MockFrameworkReporter.Object, TestEnvironment.Logger, settings, new SchedulingAnalyzer(TestEnvironment.Logger)); runner.RunTests(testCase.Yield(), false, ProcessExecutorFactory); diff --git a/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs b/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs index 418eefb03..6daa5ac68 100644 --- a/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs +++ b/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs @@ -91,28 +91,28 @@ public void MaxNrOfThreads_InvalidValue_ReturnsDefaultValue() [TestCategory(Unit)] public void AdditionalTestExecutionParam__PlaceholdersAreTreatedCorrectly() { - MockXmlOptions.Setup(o => o.AdditionalTestExecutionParam).Returns(SettingsWrapper.TestDirPlaceholder); + MockXmlOptions.Setup(o => o.AdditionalTestExecutionParam).Returns(PlaceholderReplacer.TestDirPlaceholder); string result = TheOptions.GetUserParametersForExecution("SomeExecutable.exe", "mydir", 0); result.Should().Be("mydir"); - MockXmlOptions.Setup(o => o.AdditionalTestExecutionParam).Returns(SettingsWrapper.TestDirPlaceholder + " " + SettingsWrapper.TestDirPlaceholder); + MockXmlOptions.Setup(o => o.AdditionalTestExecutionParam).Returns(PlaceholderReplacer.TestDirPlaceholder + " " + PlaceholderReplacer.TestDirPlaceholder); result = TheOptions.GetUserParametersForExecution("SomeExecutable.exe", "mydir", 0); result.Should().Be("mydir mydir"); - MockXmlOptions.Setup(o => o.AdditionalTestExecutionParam).Returns(SettingsWrapper.TestDirPlaceholder.ToLower()); + MockXmlOptions.Setup(o => o.AdditionalTestExecutionParam).Returns(PlaceholderReplacer.TestDirPlaceholder.ToLower()); result = TheOptions.GetUserParametersForExecution("SomeExecutable.exe", "mydir", 0); - result.Should().Be(SettingsWrapper.TestDirPlaceholder.ToLower()); + result.Should().Be(PlaceholderReplacer.TestDirPlaceholder.ToLower()); - MockXmlOptions.Setup(o => o.AdditionalTestExecutionParam).Returns(SettingsWrapper.ThreadIdPlaceholder); + MockXmlOptions.Setup(o => o.AdditionalTestExecutionParam).Returns(PlaceholderReplacer.ThreadIdPlaceholder); result = TheOptions.GetUserParametersForExecution("SomeExecutable.exe", "mydir", 4711); result.Should().Be("4711"); - MockXmlOptions.Setup(o => o.AdditionalTestExecutionParam).Returns(SettingsWrapper.TestDirPlaceholder + ", " + SettingsWrapper.ThreadIdPlaceholder); + MockXmlOptions.Setup(o => o.AdditionalTestExecutionParam).Returns(PlaceholderReplacer.TestDirPlaceholder + ", " + PlaceholderReplacer.ThreadIdPlaceholder); result = TheOptions.GetUserParametersForExecution("SomeExecutable.exe", "mydir", 4711); result.Should().Be("mydir, 4711"); MockXmlOptions.Setup(o => o.SolutionDir).Returns(@"C:\\TheSolutionDir"); - MockXmlOptions.Setup(o => o.AdditionalTestExecutionParam).Returns(SettingsWrapper.TestDirPlaceholder + ", " + SettingsWrapper.ThreadIdPlaceholder + ", " + SettingsWrapper.SolutionDirPlaceholder + ", " + SettingsWrapper.ExecutablePlaceholder); + MockXmlOptions.Setup(o => o.AdditionalTestExecutionParam).Returns(PlaceholderReplacer.TestDirPlaceholder + ", " + PlaceholderReplacer.ThreadIdPlaceholder + ", " + PlaceholderReplacer.SolutionDirPlaceholder + ", " + PlaceholderReplacer.ExecutablePlaceholder); result = TheOptions.GetUserParametersForExecution("SomeExecutable.exe", "mydir", 4711); result.Should().Be(@"mydir, 4711, C:\\TheSolutionDir, SomeExecutable.exe"); } @@ -264,7 +264,7 @@ public void PathExtension__ReturnsValueOrDefault() [TestCategory(Unit)] public void GetPathExtension__PlaceholderIsReplaced() { - MockXmlOptions.Setup(o => o.PathExtension).Returns("Foo;" + SettingsWrapper.ExecutableDirPlaceholder + ";Bar"); + MockXmlOptions.Setup(o => o.PathExtension).Returns("Foo;" + PlaceholderReplacer.ExecutableDirPlaceholder + ";Bar"); string result = TheOptions.GetPathExtension(TestResources.Tests_DebugX86); // ReSharper disable once PossibleNullReferenceException @@ -295,7 +295,7 @@ public void GetPathExtension__PlatformAndConfigurationNamePlaceholdersAreReplace MockXmlOptions.Setup(o => o.PlatformName).Returns("Debug"); MockXmlOptions.Setup(o => o.ConfigurationName).Returns("x86"); MockXmlOptions.Setup(o => o.PathExtension).Returns( - $"P:{SettingsWrapper.PlatformNamePlaceholder}, C:{SettingsWrapper.ConfigurationNamePlaceholder}"); + $"P:{PlaceholderReplacer.PlatformNamePlaceholder}, C:{PlaceholderReplacer.ConfigurationNamePlaceholder}"); string result = TheOptions.GetPathExtension(TestResources.LoadTests_ReleaseX86); diff --git a/GoogleTestAdapter/Core/Core.csproj b/GoogleTestAdapter/Core/Core.csproj index 2c8018403..9da1a1442 100644 --- a/GoogleTestAdapter/Core/Core.csproj +++ b/GoogleTestAdapter/Core/Core.csproj @@ -73,7 +73,10 @@ + + + diff --git a/GoogleTestAdapter/Core/Settings/PlaceholderReplacer.cs b/GoogleTestAdapter/Core/Settings/PlaceholderReplacer.cs new file mode 100644 index 000000000..ab9f43ec7 --- /dev/null +++ b/GoogleTestAdapter/Core/Settings/PlaceholderReplacer.cs @@ -0,0 +1,245 @@ +using System; +using System.IO; + +namespace GoogleTestAdapter.Settings +{ + public class PlaceholderReplacer + { + private const string OnlyInsideVs = " (only available inside VS)"; + private const string TestExecutionOnly = " (test execution only)"; + + public const string SolutionDirPlaceholder = "$(SolutionDir)"; + private const string DescriptionOfSolutionDirPlaceHolder = SolutionDirPlaceholder + " - directory of the solution" + OnlyInsideVs; + + public const string PlatformNamePlaceholder = "$(PlatformName)"; + private const string DescriptionOfPlatformNamePlaceholder = PlatformNamePlaceholder + " - the name of the solution's current platform" + OnlyInsideVs; + + public const string ConfigurationNamePlaceholder = "$(ConfigurationName)"; + private const string DescriptionOfConfigurationNamePlaceholder = ConfigurationNamePlaceholder + " - the name of the solution's current configuration" + OnlyInsideVs; + + public const string ExecutablePlaceholder = "$(Executable)"; + private const string DescriptionOfExecutablePlaceHolder = ExecutablePlaceholder + " - executable containing the tests"; + + public const string ExecutableDirPlaceholder = "$(ExecutableDir)"; + public const string DescriptionOfExecutableDirPlaceHolder = ExecutableDirPlaceholder + " - directory containing the test executable"; + + public const string TestDirPlaceholder = "$(TestDir)"; + private const string DescriptionOfTestDirPlaceholder = TestDirPlaceholder + " - path of a directory which can be used by the tests"; + + public const string ThreadIdPlaceholder = "$(ThreadId)"; + private const string DescriptionOfThreadIdPlaceholder = ThreadIdPlaceholder + " - id of thread executing the current tests"; + + private const string DescriptionOfEnvVarPlaceholders = "Environment variables are also possible, e.g. %PATH%"; + + + private readonly Func _getSolutionDir; + private readonly Func _getSettings; + + private string SolutionDir => _getSolutionDir(); + private IGoogleTestAdapterSettings Settings => _getSettings(); + + public PlaceholderReplacer(Func getSolutionDir, Func getSettings) + { + _getSolutionDir = getSolutionDir; + _getSettings = getSettings; + } + + + public const string AdditionalPdbsPlaceholders = "Placeholders:\n" + + DescriptionOfSolutionDirPlaceHolder + "\n" + + DescriptionOfPlatformNamePlaceholder + "\n" + + DescriptionOfConfigurationNamePlaceholder + "\n" + + DescriptionOfExecutableDirPlaceHolder + "\n" + + DescriptionOfExecutablePlaceHolder + "\n" + + DescriptionOfEnvVarPlaceholders; + + public string ReplaceAdditionalPdbsPlaceholders(string executable, string pdb) + { + return ReplaceEnvironmentVariables( + ReplaceSolutionDirPlaceholder( + ReplacePlatformAndConfigurationPlaceholders( + ReplaceExecutablePlaceholders(pdb.Trim(), executable)))); + } + + + public const string WorkingDirPlaceholders = "Placeholders:\n" + + DescriptionOfSolutionDirPlaceHolder + "\n" + + DescriptionOfPlatformNamePlaceholder + "\n" + + DescriptionOfConfigurationNamePlaceholder + "\n" + + DescriptionOfExecutableDirPlaceHolder + "\n" + + DescriptionOfExecutablePlaceHolder + "\n" + + DescriptionOfTestDirPlaceholder + TestExecutionOnly + "\n" + + DescriptionOfThreadIdPlaceholder + TestExecutionOnly + "\n" + + DescriptionOfEnvVarPlaceholders; + + public string ReplaceWorkingDirPlaceholdersForDiscovery(string executable, string workingDir) + { + return ReplaceEnvironmentVariables( + ReplaceSolutionDirPlaceholder( + ReplacePlatformAndConfigurationPlaceholders( + RemoveTestDirAndThreadIdPlaceholders( + ReplaceExecutablePlaceholders(workingDir, executable))))); + } + + public string ReplaceWorkingDirPlaceholdersForExecution(string executable, string workingDir, string testDirectory, int threadId) + { + return ReplaceEnvironmentVariables( + ReplaceSolutionDirPlaceholder( + ReplacePlatformAndConfigurationPlaceholders( + ReplaceExecutablePlaceholders( + ReplaceTestDirAndThreadIdPlaceholders(workingDir, testDirectory, threadId), executable)))); + } + + + public const string PathExtensionPlaceholders = "Placeholders:\n" + + DescriptionOfSolutionDirPlaceHolder + "\n" + + DescriptionOfPlatformNamePlaceholder + "\n" + + DescriptionOfConfigurationNamePlaceholder + "\n" + + DescriptionOfExecutableDirPlaceHolder + "\n" + + DescriptionOfExecutablePlaceHolder + "\n" + + DescriptionOfEnvVarPlaceholders; + + public string ReplacePathExtensionPlaceholders(string pathExtension, string executable) + { + return ReplaceEnvironmentVariables( + ReplaceSolutionDirPlaceholder( + ReplacePlatformAndConfigurationPlaceholders( + ReplaceExecutablePlaceholders(pathExtension, executable)))); + } + + + public const string AdditionalTestExecutionParamPlaceholders = "Placeholders:\n" + + DescriptionOfSolutionDirPlaceHolder + "\n" + + DescriptionOfPlatformNamePlaceholder + "\n" + + DescriptionOfConfigurationNamePlaceholder + "\n" + + DescriptionOfExecutableDirPlaceHolder + "\n" + + DescriptionOfExecutablePlaceHolder + "\n" + + DescriptionOfTestDirPlaceholder + TestExecutionOnly + "\n" + + DescriptionOfThreadIdPlaceholder + TestExecutionOnly + "\n" + + DescriptionOfEnvVarPlaceholders; + + public string ReplaceAdditionalTestExecutionParamPlaceholdersForDiscovery(string additionalTestExecutionParam, string executable) + { + return ReplaceEnvironmentVariables( + ReplaceSolutionDirPlaceholder( + ReplacePlatformAndConfigurationPlaceholders( + RemoveTestDirAndThreadIdPlaceholders( + ReplaceExecutablePlaceholders(additionalTestExecutionParam, executable))))); + } + + public string ReplaceAdditionalTestExecutionParamPlaceholdersForExecution(string additionalTestExecutionParam, string executable, string testDirectory, int threadId) + { + return ReplaceEnvironmentVariables( + ReplaceSolutionDirPlaceholder( + ReplacePlatformAndConfigurationPlaceholders( + ReplaceExecutablePlaceholders( + ReplaceTestDirAndThreadIdPlaceholders(additionalTestExecutionParam, testDirectory, threadId), executable)))); + } + + + + public const string BatchesPlaceholders = "Placeholders:\n" + + DescriptionOfSolutionDirPlaceHolder + "\n" + + DescriptionOfPlatformNamePlaceholder + "\n" + + DescriptionOfConfigurationNamePlaceholder + "\n" + + DescriptionOfTestDirPlaceholder + "\n" + + DescriptionOfThreadIdPlaceholder + "\n" + + DescriptionOfEnvVarPlaceholders; + + public string ReplaceBatchForTestSetupPlaceholders(string batchForTestSetup, string testDirectory, int threadId) + { + return ReplaceEnvironmentVariables( + ReplaceSolutionDirPlaceholder( + ReplacePlatformAndConfigurationPlaceholders( + ReplaceTestDirAndThreadIdPlaceholders(batchForTestSetup, testDirectory, threadId)))); + } + + public string ReplaceBatchForTestTeardownPlaceholders(string batchForTestTeardown, string testDirectory, int threadId) + { + return ReplaceEnvironmentVariables( + ReplaceSolutionDirPlaceholder( + ReplacePlatformAndConfigurationPlaceholders( + ReplaceTestDirAndThreadIdPlaceholders(batchForTestTeardown, testDirectory, threadId)))); + } + + + private string ReplaceSolutionDirPlaceholder(string theString) + { + if (string.IsNullOrWhiteSpace(theString)) + { + return ""; + } + + return string.IsNullOrWhiteSpace(SolutionDir) + ? theString.Replace(SolutionDirPlaceholder, "") + : theString.Replace(SolutionDirPlaceholder, SolutionDir); + } + + private string ReplacePlatformAndConfigurationPlaceholders(string theString) + { + if (string.IsNullOrWhiteSpace(theString)) + { + return ""; + } + + string result = theString; + + result = string.IsNullOrWhiteSpace(Settings.PlatformName) + ? result.Replace(PlatformNamePlaceholder, "") + : result.Replace(PlatformNamePlaceholder, Settings.PlatformName); + result = string.IsNullOrWhiteSpace(Settings.ConfigurationName) + ? result.Replace(ConfigurationNamePlaceholder, "") + : result.Replace(ConfigurationNamePlaceholder, Settings.ConfigurationName); + + return result; + } + + private string ReplaceExecutablePlaceholders(string theString, string executable) + { + if (string.IsNullOrWhiteSpace(theString)) + { + return ""; + } + + // ReSharper disable once PossibleNullReferenceException + string executableDir = new FileInfo(executable).Directory.FullName; + return theString + .Replace(ExecutableDirPlaceholder, executableDir) + .Replace(ExecutablePlaceholder, executable); + } + + private string ReplaceTestDirAndThreadIdPlaceholders(string theString, string testDirectory, int threadId) + { + return ReplaceTestDirAndThreadIdPlaceholders(theString, testDirectory, threadId.ToString()); + } + + private string RemoveTestDirAndThreadIdPlaceholders(string theString) + { + return ReplaceTestDirAndThreadIdPlaceholders(theString, "", ""); + } + + private string ReplaceEnvironmentVariables(string theString) + { + if (string.IsNullOrWhiteSpace(theString)) + { + return ""; + } + + return Environment.ExpandEnvironmentVariables(theString); + } + + private string ReplaceTestDirAndThreadIdPlaceholders(string theString, string testDirectory, string threadId) + { + if (string.IsNullOrWhiteSpace(theString)) + { + return ""; + } + + return theString + .Replace(TestDirPlaceholder, testDirectory) + .Replace(ThreadIdPlaceholder, threadId); + } + + } + +} \ No newline at end of file diff --git a/GoogleTestAdapter/Core/Settings/RegexTraitPair.cs b/GoogleTestAdapter/Core/Settings/RegexTraitPair.cs new file mode 100644 index 000000000..d23394f86 --- /dev/null +++ b/GoogleTestAdapter/Core/Settings/RegexTraitPair.cs @@ -0,0 +1,21 @@ +using GoogleTestAdapter.Model; + +namespace GoogleTestAdapter.Settings +{ + public class RegexTraitPair + { + public string Regex { get; } + public Trait Trait { get; } + + public RegexTraitPair(string regex, string name, string value) + { + Regex = regex; + Trait = new Trait(name, value); + } + + public override string ToString() + { + return $"'{Regex}': {Trait}"; + } + } +} \ No newline at end of file diff --git a/GoogleTestAdapter/Core/Settings/SettingsPrinter.cs b/GoogleTestAdapter/Core/Settings/SettingsPrinter.cs new file mode 100644 index 000000000..d7709a7ab --- /dev/null +++ b/GoogleTestAdapter/Core/Settings/SettingsPrinter.cs @@ -0,0 +1,48 @@ +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace GoogleTestAdapter.Settings +{ + public class SettingsPrinter + { + private static readonly string[] NotPrintedProperties = + { + nameof(SettingsWrapper.RegexTraitParser), + nameof(SettingsWrapper.DebuggingNamedPipeId), + nameof(SettingsWrapper.SolutionDir) + }; + + private static readonly PropertyInfo[] PropertiesToPrint = typeof(SettingsWrapper) + .GetProperties() + .Where(pi => !NotPrintedProperties.Contains(pi.Name)) + .OrderBy(p => p.Name) + .ToArray(); + + + private readonly SettingsWrapper _settings; + + public SettingsPrinter(SettingsWrapper settings) + { + _settings = settings; + } + + public string ToReadableString() + { + return string.Join(", ", PropertiesToPrint.Select(ToString)); + } + + private string ToString(PropertyInfo propertyInfo) + { + var value = propertyInfo.GetValue(_settings); + if (value is string) + return $"{propertyInfo.Name}: '{value}'"; + + if (value is IEnumerable pairs) + return $"{propertyInfo.Name}: {{{string.Join(", ", pairs)}}}"; + + return $"{propertyInfo.Name}: {value}"; + } + + } +} \ No newline at end of file diff --git a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs index 8d0cca3e0..1b32aa993 100644 --- a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs +++ b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs @@ -2,66 +2,39 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Reflection; using System.Threading; using GoogleTestAdapter.Common; using GoogleTestAdapter.Helpers; -using GoogleTestAdapter.Model; namespace GoogleTestAdapter.Settings { - public class RegexTraitPair - { - public string Regex { get; } - public Trait Trait { get; } - - public RegexTraitPair(string regex, string name, string value) - { - Regex = regex; - Trait = new Trait(name, value); - } - - public override string ToString() - { - return $"'{Regex}': {Trait}"; - } - } - public class SettingsWrapper { - private const string DescriptionTestExecutionOnly = " (test execution only)"; - private readonly object _lock = new object(); - private static readonly string[] NotPrintedProperties = - { - nameof(RegexTraitParser), - nameof(DebuggingNamedPipeId), - nameof(SolutionDir) - }; - - private static readonly PropertyInfo[] PropertiesToPrint = typeof(SettingsWrapper) - .GetProperties() - .Where(pi => !NotPrintedProperties.Contains(pi.Name)) - .OrderBy(p => p.Name) - .ToArray(); - + public RegexTraitParser RegexTraitParser { private get; set; } private readonly IGoogleTestAdapterSettingsContainer _settingsContainer; private readonly string _solutionDir; - public RegexTraitParser RegexTraitParser { private get; set; } + private readonly PlaceholderReplacer _placeholderReplacer; + private readonly SettingsPrinter _settingsPrinter; private int _nrOfRunningExecutions; private string _currentExecutable; private Thread _currentThread; private IGoogleTestAdapterSettings _currentSettings; + // needed for mocking + // ReSharper disable once UnusedMember.Global + public SettingsWrapper() { } + public SettingsWrapper(IGoogleTestAdapterSettingsContainer settingsContainer, string solutionDir = null) { _settingsContainer = settingsContainer; _solutionDir = solutionDir; _currentSettings = _settingsContainer.SolutionSettings; + _placeholderReplacer = new PlaceholderReplacer(() => SolutionDir, () => _currentSettings); + _settingsPrinter = new SettingsPrinter(this); } public virtual SettingsWrapper Clone() @@ -69,9 +42,12 @@ public virtual SettingsWrapper Clone() return new SettingsWrapper(_settingsContainer, _solutionDir) { RegexTraitParser = RegexTraitParser }; } - // needed for mocking - // ReSharper disable once UnusedMember.Global - public SettingsWrapper() { } + public override string ToString() + { + return _settingsPrinter.ToReadableString(); + } + + #region Handling of execution settings public void ExecuteWithSettingsForExecutable(string executable, ILogger logger, Action action) { @@ -82,27 +58,9 @@ public void ExecuteWithSettingsForExecutable(string executable, ILogger logger, _nrOfRunningExecutions++; if (_nrOfRunningExecutions == 1) { - _currentExecutable = executable; - _currentThread = Thread.CurrentThread; - - var projectSettings = _settingsContainer.GetSettingsForExecutable(executable); - if (projectSettings != null) - { - _currentSettings = projectSettings; - string settingsString = ToString(); - _currentSettings = _settingsContainer.SolutionSettings; - logger.DebugInfo($"Settings for test executable '{executable}': {settingsString}"); - - _currentSettings = projectSettings; - } - else - { - logger.DebugInfo($"No settings configured for test executable '{executable}'; running with solution settings: {this}"); - } + EnableSettingsForExecutable(); } - } - try { action.Invoke(); @@ -114,16 +72,44 @@ public void ExecuteWithSettingsForExecutable(string executable, ILogger logger, _nrOfRunningExecutions--; if (_nrOfRunningExecutions == 0) { - _currentExecutable = null; - _currentThread = null; - if (_currentSettings != _settingsContainer.SolutionSettings) - { - _currentSettings = _settingsContainer.SolutionSettings; - logger.DebugInfo($"Back to solution settings: {this}"); - } + ReenableSolutionSettings(); } } } + + void EnableSettingsForExecutable() + { + _currentExecutable = executable; + _currentThread = Thread.CurrentThread; + + var projectSettings = _settingsContainer.GetSettingsForExecutable(executable); + if (projectSettings != null) + { + _currentSettings = projectSettings; + string settingsString = ToString(); + _currentSettings = _settingsContainer.SolutionSettings; + logger.DebugInfo($"Settings for test executable '{executable}': {settingsString}"); + + _currentSettings = projectSettings; + } + else + { + logger.DebugInfo( + $"No settings configured for test executable '{executable}'; running with solution settings: {this}"); + } + } + + void ReenableSolutionSettings() + { + _currentExecutable = null; + _currentThread = null; + if (_currentSettings != _settingsContainer.SolutionSettings) + { + _currentSettings = _settingsContainer.SolutionSettings; + logger.DebugInfo($"Back to solution settings: {this}"); + } + } + } // public virtual for mocking @@ -143,233 +129,171 @@ public virtual void CheckCorrectUsage(string executable) $"Execution is already running with settings for executable {_currentExecutable}, can not switch to settings for {executable}"); } - public override string ToString() - { - return string.Join(", ", PropertiesToPrint.Select(ToString)); - } + #endregion - private string ToString(PropertyInfo propertyInfo) - { - var value = propertyInfo.GetValue(this); - if (value is string) - return $"{propertyInfo.Name}: '{value}'"; + #region Page and category names - if (value is IEnumerable pairs) - return $"{propertyInfo.Name}: {{{string.Join(", ", pairs)}}}"; + public const string PageGeneralName = "General"; + public const string PageGoogleTestName = "Google Test"; + public const string PageTestDiscovery = "Test Discovery"; + public const string PageTestExecution = "Test Execution"; - return $"{propertyInfo.Name}: {value}"; - } + public const string CategoryTestExecutionName = "Test execution"; + public const string CategoryTraitsName = "Regexes for trait assignment"; + public const string CategoryRuntimeBehaviorName = "Runtime behavior"; + public const string CategoryParallelizationName = "Parallelization"; + public const string CategoryMiscName = "Misc"; + public const string CategoryOutputName = "Output"; + public const string CategorySecurityName = "Security"; + public const string CategoryRunConfigurationName = "Run configuration (also applies to test discovery)"; + public const string CategorySetupAndTeardownName = "Setup and teardown"; - private const string OnlyInsideVs = " (only available inside VS)"; + #endregion - public const string SolutionDirPlaceholder = "$(SolutionDir)"; - private const string DescriptionOfSolutionDirPlaceHolder = - SolutionDirPlaceholder + " - directory of the solution" + OnlyInsideVs; + #region GeneralOptionsPage - public const string PlatformNamePlaceholder = "$(PlatformName)"; - private const string DescriptionOfPlatformNamePlaceholder = - PlatformNamePlaceholder + " - the name of the solution's current platform" + OnlyInsideVs; + public const string OptionPrintTestOutput = "Print test output"; + public const string OptionPrintTestOutputDescription = + "Print the output of the Google Test executable(s) to the Tests Output window."; + public const bool OptionPrintTestOutputDefaultValue = false; - public const string ConfigurationNamePlaceholder = "$(ConfigurationName)"; - private const string DescriptionOfConfigurationNamePlaceholder = - ConfigurationNamePlaceholder + " - the name of the solution's current configuration" + OnlyInsideVs; + public virtual bool PrintTestOutput => _currentSettings.PrintTestOutput ?? OptionPrintTestOutputDefaultValue; - private string ReplaceSolutionDirPlaceholder(string theString) - { - if (string.IsNullOrWhiteSpace(theString)) - { - return ""; - } - return string.IsNullOrWhiteSpace(SolutionDir) - ? theString.Replace(SolutionDirPlaceholder, "") - : theString.Replace(SolutionDirPlaceholder, SolutionDir); - } + public const string OptionDebugMode = "Print debug info"; + public const string OptionDebugModeDescription = + "If true, debug output will be printed to the test console."; + public const bool OptionDebugModeDefaultValue = false; - private string ReplacePlatformAndConfigurationPlaceholders(string theString) - { - if (string.IsNullOrWhiteSpace(theString)) - { - return ""; - } + public virtual bool DebugMode => _currentSettings.DebugMode ?? OptionDebugModeDefaultValue; - string result = theString; - result = string.IsNullOrWhiteSpace(_currentSettings.PlatformName) - ? result.Replace(PlatformNamePlaceholder, "") - : result.Replace(PlatformNamePlaceholder, _currentSettings.PlatformName); - result = string.IsNullOrWhiteSpace(_currentSettings.ConfigurationName) - ? result.Replace(ConfigurationNamePlaceholder, "") - : result.Replace(ConfigurationNamePlaceholder, _currentSettings.ConfigurationName); + public const string OptionTimestampOutput = "Timestamp output"; + public const string OptionTimestampOutputDescription = + "If true, a timestamp is added to test and debug output."; + public const bool OptionTimestampOutputDefaultValue = false; - return result; - } + public virtual bool TimestampOutput => _currentSettings.TimestampOutput ?? OptionTimestampOutputDefaultValue; - - public const string ExecutablePlaceholder = "$(Executable)"; - private const string DescriptionOfExecutablePlaceHolder = - ExecutablePlaceholder + " - executable containing the tests"; - public const string ExecutableDirPlaceholder = "$(ExecutableDir)"; - private const string DescriptionOfExecutableDirPlaceHolder = - ExecutableDirPlaceholder + " - directory containing the test executable"; + public const string OptionSkipOriginCheck = "Skip check of file origin"; + public const string OptionSkipOriginCheckDescription = + "If true, it will not be checked whether executables originate from this computer. Note that this might impose security risks, e.g. when building downloaded solutions. This setting can only be changed via VS Options."; + public const bool OptionSkipOriginCheckDefaultValue = false; - private string ReplaceExecutablePlaceholders(string theString, string executable) - { - if (string.IsNullOrWhiteSpace(theString)) - { - return ""; - } + public virtual bool SkipOriginCheck => _currentSettings.SkipOriginCheck ?? OptionSkipOriginCheckDefaultValue; - // ReSharper disable once PossibleNullReferenceException - string executableDir = new FileInfo(executable).Directory.FullName; - return theString - .Replace(ExecutableDirPlaceholder, executableDir) - .Replace(ExecutablePlaceholder, executable); - } - - public const string TestDirPlaceholder = "$(TestDir)"; - private const string DescriptionOfTestDirPlaceholder = - TestDirPlaceholder + " - path of a directory which can be used by the tests"; + #endregion - public const string ThreadIdPlaceholder = "$(ThreadId)"; - private const string DescriptionOfThreadIdPlaceholder = - ThreadIdPlaceholder + " - id of thread executing the current tests"; + #region GoogleTestOptionsPage - private string ReplaceTestDirAndThreadIdPlaceholders(string theString, string testDirectory, string threadId) - { - if (string.IsNullOrWhiteSpace(theString)) - { - return ""; - } + public const string OptionCatchExceptions = "Catch exceptions"; + public const string OptionCatchExceptionsDescription = + "Google Test catches exceptions by default; the according test fails and test execution continues. Choosing false lets exceptions pass through, allowing the debugger to catch them.\n" + + "Google Test option:" + GoogleTestConstants.CatchExceptions; + public const bool OptionCatchExceptionsDefaultValue = true; - return theString - .Replace(TestDirPlaceholder, testDirectory) - .Replace(ThreadIdPlaceholder, threadId); - } + public virtual bool CatchExceptions => _currentSettings.CatchExceptions ?? OptionCatchExceptionsDefaultValue; - private string ReplaceTestDirAndThreadIdPlaceholders(string theString, string testDirectory, int threadId) - { - return ReplaceTestDirAndThreadIdPlaceholders(theString, testDirectory, threadId.ToString()); - } - private string RemoveTestDirAndThreadIdPlaceholders(string theString) - { - return ReplaceTestDirAndThreadIdPlaceholders(theString, "", ""); - } + public const string OptionBreakOnFailure = "Break on failure"; + public const string OptionBreakOnFailureDescription = + "If enabled, a potentially attached debugger will catch assertion failures and automatically drop into interactive mode.\n" + + "Google Test option:" + GoogleTestConstants.BreakOnFailure; + public const bool OptionBreakOnFailureDefaultValue = false; + public virtual bool BreakOnFailure => _currentSettings.BreakOnFailure ?? OptionBreakOnFailureDefaultValue; - private const string DescriptionOfEnvVarPlaceholders = "Environment variables are also possible, e.g. %PATH%"; - private string ReplaceEnvironmentVariables(string theString) + public const string OptionRunDisabledTests = "Also run disabled tests"; + public const string OptionRunDisabledTestsDescription = + "If true, all (selected) tests will be run, even if they have been disabled.\n" + + "Google Test option:" + GoogleTestConstants.AlsoRunDisabledTestsOption; + public const bool OptionRunDisabledTestsDefaultValue = false; + + public virtual bool RunDisabledTests => _currentSettings.RunDisabledTests ?? OptionRunDisabledTestsDefaultValue; + + + public const string OptionNrOfTestRepetitions = "Number of test repetitions"; + public const string OptionNrOfTestRepetitionsDescription = + "Tests will be run for the selected number of times (-1: infinite).\n" + + "Google Test option:" + GoogleTestConstants.NrOfRepetitionsOption; + public const int OptionNrOfTestRepetitionsDefaultValue = 1; + + public virtual int NrOfTestRepetitions { - if (string.IsNullOrWhiteSpace(theString)) + get { - return ""; + int nrOfRepetitions = _currentSettings.NrOfTestRepetitions ?? OptionNrOfTestRepetitionsDefaultValue; + if (nrOfRepetitions == 0 || nrOfRepetitions < -1) + { + nrOfRepetitions = OptionNrOfTestRepetitionsDefaultValue; + } + return nrOfRepetitions; } - - return Environment.ExpandEnvironmentVariables(theString); } - public const string PageGeneralName = "General"; - public const string PageGoogleTestName = "Google Test"; - public const string PageTestDiscovery = "Test Discovery"; - public const string PageTestExecution = "Test Execution"; + public const string OptionShuffleTests = "Shuffle tests per execution"; + public const string OptionShuffleTestsDescription = + "If true, tests will be executed in random order. Note that a true randomized order is only given when executing all tests in non-parallel fashion. Otherwise, the test excutables will most likely be executed more than once - random order is than restricted to the according executions.\n" + + "Google Test option:" + GoogleTestConstants.ShuffleTestsOption; + public const bool OptionShuffleTestsDefaultValue = false; - public const string CategoryTestExecutionName = "Test execution"; - public const string CategoryTraitsName = "Regexes for trait assignment"; - public const string CategoryRuntimeBehaviorName = "Runtime behavior"; - public const string CategoryParallelizationName = "Parallelization"; - public const string CategoryMiscName = "Misc"; - public const string CategoryOutputName = "Output"; - public const string CategorySecurityName = "Security"; - public const string CategoryRunConfigurationName = "Run configuration (also applies to test discovery)"; - public const string CategorySetupAndTeardownName = "Setup and teardown"; + public virtual bool ShuffleTests => _currentSettings.ShuffleTests ?? OptionShuffleTestsDefaultValue; - #region GeneralOptionsPage - public virtual string DebuggingNamedPipeId => _currentSettings.DebuggingNamedPipeId; - public virtual string SolutionDir => _solutionDir ?? _currentSettings.SolutionDir; + public const string OptionShuffleTestsSeed = "Shuffle tests: Seed"; + public const string OptionShuffleTestsSeedDescription = "0: Seed is computed from system time, 1<=n<=" + + GoogleTestConstants.ShuffleTestsSeedMaxValueAsString + + ": The given seed is used. See note of option '" + + OptionShuffleTests + + "'.\n" + + "Google Test option:" + GoogleTestConstants.ShuffleTestsSeedOption; + public const int OptionShuffleTestsSeedDefaultValue = GoogleTestConstants.ShuffleTestsSeedDefaultValue; + + public virtual int ShuffleTestsSeed + { + get + { + int seed = _currentSettings.ShuffleTestsSeed ?? OptionShuffleTestsSeedDefaultValue; + if (seed < GoogleTestConstants.ShuffleTestsSeedMinValue || seed > GoogleTestConstants.ShuffleTestsSeedMaxValue) + { + seed = OptionShuffleTestsSeedDefaultValue; + } + return seed; + } + } + + #endregion + + #region TestExecutionOptionsPage public const string OptionUseNewTestExecutionFramework = "Use native debugging"; - public const bool OptionUseNewTestExecutionFrameworkDefaultValue = true; public const string OptionUseNewTestExecutionFrameworkDescription = "Make use of native debugging (in contrast to debugging provided by the VsTest framework). Advantages: test crash detection and test output printing also work in debug mode."; + public const bool OptionUseNewTestExecutionFrameworkDefaultValue = true; public virtual bool UseNewTestExecutionFramework => _currentSettings.UseNewTestExecutionFramework ?? OptionUseNewTestExecutionFrameworkDefaultValue; - public const string OptionPrintTestOutput = "Print test output"; - public const bool OptionPrintTestOutputDefaultValue = false; - public const string OptionPrintTestOutputDescription = - "Print the output of the Google Test executable(s) to the Tests Output window."; - - public virtual bool PrintTestOutput => _currentSettings.PrintTestOutput ?? OptionPrintTestOutputDefaultValue; - - - public const string OptionTestDiscoveryRegex = "Regex for test discovery"; - public const string OptionTestDiscoveryRegexDefaultValue = ""; - public const string OptionTestDiscoveryRegexDescription = - "If non-empty, this regex will be used to identify the Google Test executables containing your tests, and the executable itself will not be scanned."; - - public virtual string TestDiscoveryRegex => _currentSettings.TestDiscoveryRegex ?? OptionTestDiscoveryRegexDefaultValue; - - public const string OptionAdditionalPdbs = "Additional PDBs"; - public const string OptionAdditionalPdbsDefaultValue = ""; - public const string OptionAdditionalPdbsDescription = "Files matching the provided file patterns are scanned for additional source locations. This can be useful if the PDBs containing the necessary information can not be found by scanning the executables.\n" + - "File part of each pattern may contain '*' and '?'; patterns are separated by ';'. Example: " + ExecutableDirPlaceholder + "\\pdbs\\*.pdb\n" + - "Placeholders:\n" + - DescriptionOfSolutionDirPlaceHolder + "\n" + - DescriptionOfPlatformNamePlaceholder + "\n" + - DescriptionOfConfigurationNamePlaceholder + "\n" + - DescriptionOfExecutableDirPlaceHolder + "\n" + - DescriptionOfExecutablePlaceHolder + "\n" + - DescriptionOfEnvVarPlaceholders; + "File part of each pattern may contain '*' and '?'; patterns are separated by ';'. Example: " + PlaceholderReplacer.ExecutableDirPlaceholder + "\\pdbs\\*.pdb\n" + PlaceholderReplacer.AdditionalPdbsPlaceholders; + public const string OptionAdditionalPdbsDefaultValue = ""; public virtual string AdditionalPdbs => _currentSettings.AdditionalPdbs ?? OptionAdditionalPdbsDefaultValue; - public IEnumerable GetAdditionalPdbs(string executable) => Utils.SplitAdditionalPdbs(AdditionalPdbs) - .Select(p => - ReplaceEnvironmentVariables( - ReplaceSolutionDirPlaceholder( - ReplacePlatformAndConfigurationPlaceholders( - ReplaceExecutablePlaceholders(p.Trim(), executable))))); - - - public const string OptionTestDiscoveryTimeoutInSeconds = "Test discovery timeout in s"; - public const int OptionTestDiscoveryTimeoutInSecondsDefaultValue = 30; - public const string OptionTestDiscoveryTimeoutInSecondsDescription = - "Number of seconds after which test discovery of an executable will be assumed to have failed. 0: Infinite timeout"; - - public virtual int TestDiscoveryTimeoutInSeconds { - get - { - int timeout = _currentSettings.TestDiscoveryTimeoutInSeconds ?? OptionTestDiscoveryTimeoutInSecondsDefaultValue; - if (timeout < 0) - timeout = OptionTestDiscoveryTimeoutInSecondsDefaultValue; + .Select(p => _placeholderReplacer.ReplaceAdditionalPdbsPlaceholders(executable, p)); - return timeout == 0 ? int.MaxValue : timeout; - } - } public const string OptionWorkingDir = "Working directory"; - public const string OptionWorkingDirDefaultValue = ExecutableDirPlaceholder; public const string OptionWorkingDirDescription = - "If non-empty, will set the working directory for running the tests (default: " + DescriptionOfExecutableDirPlaceHolder + ").\nExample: " + SolutionDirPlaceholder + "\\MyTestDir\nPlaceholders:\n" + - DescriptionOfSolutionDirPlaceHolder + "\n" + - DescriptionOfPlatformNamePlaceholder + "\n" + - DescriptionOfConfigurationNamePlaceholder + "\n" + - DescriptionOfExecutableDirPlaceHolder + "\n" + - DescriptionOfExecutablePlaceHolder + "\n" + - DescriptionOfTestDirPlaceholder + DescriptionTestExecutionOnly + "\n" + - DescriptionOfThreadIdPlaceholder + DescriptionTestExecutionOnly + "\n" + - DescriptionOfEnvVarPlaceholders; + "If non-empty, will set the working directory for running the tests (default: " + PlaceholderReplacer.DescriptionOfExecutableDirPlaceHolder + ").\nExample: " + PlaceholderReplacer.SolutionDirPlaceholder + "\\MyTestDir\n" + PlaceholderReplacer.WorkingDirPlaceholders; + public const string OptionWorkingDirDefaultValue = PlaceholderReplacer.ExecutableDirPlaceholder; public virtual string WorkingDir => string.IsNullOrWhiteSpace(_currentSettings.WorkingDir) ? OptionWorkingDirDefaultValue @@ -377,224 +301,93 @@ public virtual int TestDiscoveryTimeoutInSeconds { public string GetWorkingDirForExecution(string executable, string testDirectory, int threadId) { - return ReplaceEnvironmentVariables( - ReplaceSolutionDirPlaceholder( - ReplacePlatformAndConfigurationPlaceholders( - ReplaceExecutablePlaceholders( - ReplaceTestDirAndThreadIdPlaceholders(WorkingDir, testDirectory, threadId), executable)))); + return _placeholderReplacer.ReplaceWorkingDirPlaceholdersForExecution(executable, WorkingDir, testDirectory, threadId); } public string GetWorkingDirForDiscovery(string executable) { - return ReplaceEnvironmentVariables( - ReplaceSolutionDirPlaceholder( - ReplacePlatformAndConfigurationPlaceholders( - RemoveTestDirAndThreadIdPlaceholders( - ReplaceExecutablePlaceholders(WorkingDir, executable))))); + return _placeholderReplacer.ReplaceWorkingDirPlaceholdersForDiscovery(executable, WorkingDir); } - public const string OptionPathExtension = "PATH extension"; - public const string OptionPathExtensionDefaultValue = ""; public const string OptionPathExtensionDescription = - "If non-empty, the content will be appended to the PATH variable of the test execution and discovery processes.\nExample: C:\\MyBins;" + ExecutableDirPlaceholder + "\\MyOtherBins;\nPlaceholders:\n" + - DescriptionOfSolutionDirPlaceHolder + "\n" + - DescriptionOfPlatformNamePlaceholder + "\n" + - DescriptionOfConfigurationNamePlaceholder + "\n" + - DescriptionOfExecutableDirPlaceHolder + "\n" + - DescriptionOfExecutablePlaceHolder + "\n" + - DescriptionOfEnvVarPlaceholders; + "If non-empty, the content will be appended to the PATH variable of the test execution and discovery processes.\nExample: C:\\MyBins;" + PlaceholderReplacer.ExecutableDirPlaceholder + "\\MyOtherBins;\n" + PlaceholderReplacer.PathExtensionPlaceholders; + public const string OptionPathExtensionDefaultValue = ""; public virtual string PathExtension => _currentSettings.PathExtension ?? OptionPathExtensionDefaultValue; public string GetPathExtension(string executable) - => ReplaceEnvironmentVariables( - ReplaceSolutionDirPlaceholder( - ReplacePlatformAndConfigurationPlaceholders( - ReplaceExecutablePlaceholders(PathExtension, executable)))); - - - public const string TraitsRegexesPairSeparator = "//||//"; - public const string TraitsRegexesRegexSeparator = "///"; - public const string TraitsRegexesTraitSeparator = ","; - public const string OptionTraitsRegexesDefaultValue = ""; - public const string OptionTraitsDescription = "Allows to override/add traits for testcases matching a regex. Traits are build up in 3 phases: 1st, traits are assigned to tests according to the 'Traits before' option. 2nd, the tests' traits (defined via the macros in GTA_Traits.h) are added to the tests, overriding traits from phase 1 with new values. 3rd, the 'Traits after' option is evaluated, again in an overriding manner.\nSyntax: " - + TraitsRegexesRegexSeparator + - " separates the regex from the traits, the trait's name and value are separated by " - + TraitsRegexesTraitSeparator + - " and each pair of regex and trait is separated by " - + TraitsRegexesPairSeparator + ".\nExample: " + - @"MySuite\.*" - + TraitsRegexesRegexSeparator + "Type" - + TraitsRegexesTraitSeparator + "Small" - + TraitsRegexesPairSeparator + - @"MySuite2\.*|MySuite3\.*" - + TraitsRegexesRegexSeparator + "Type" - + TraitsRegexesTraitSeparator + "Medium"; - - public const string OptionTraitsRegexesBefore = "Before test discovery"; - - public virtual List TraitsRegexesBefore - { - get - { - string option = _currentSettings.TraitsRegexesBefore ?? OptionTraitsRegexesDefaultValue; - return RegexTraitParser.ParseTraitsRegexesString(option); - } - } - - public const string OptionTraitsRegexesAfter = "After test discovery"; - - public virtual List TraitsRegexesAfter - { - get - { - string option = _currentSettings.TraitsRegexesAfter ?? OptionTraitsRegexesDefaultValue; - return RegexTraitParser.ParseTraitsRegexesString(option); - } - } - - - public const string OptionTestNameSeparator = "Test name separator"; - public const string OptionTestNameSeparatorDefaultValue = ""; - public const string OptionTestNameSeparatorDescription = - "Test names produced by Google Test might contain the character '/', which makes VS cut the name after the '/' if the test explorer window is not wide enough. This option's value, if non-empty, will replace the '/' character to avoid that behavior. Note that '\\', ' ', '|', and '-' produce the same behavior ('.', '_', ':', and '::' are known to work - there might be more). Note also that traits regexes are evaluated against the tests' display names (and must thus be consistent with this option)."; - - public virtual string TestNameSeparator => _currentSettings.TestNameSeparator ?? OptionTestNameSeparatorDefaultValue; - - - public const string OptionParseSymbolInformation = "Parse symbol information"; - public const bool OptionParseSymbolInformationDefaultValue = true; - public const string OptionParseSymbolInformationDescription = - "Parse debug symbol information for test executables to obtain source location information and traits (defined via the macros in GTA_Traits.h).\n" + - "If this is set to false step 2 of traits discovery will be left out and only traits regexes will be effective."; - - public virtual bool ParseSymbolInformation => _currentSettings.ParseSymbolInformation ?? OptionParseSymbolInformationDefaultValue; - - public const string OptionDebugMode = "Print debug info"; - public const bool OptionDebugModeDefaultValue = false; - public const string OptionDebugModeDescription = - "If true, debug output will be printed to the test console."; - - public virtual bool DebugMode => _currentSettings.DebugMode ?? OptionDebugModeDefaultValue; - - - public const string OptionTimestampOutput = "Timestamp output"; - public const bool OptionTimestampOutputDefaultValue = false; - public const string OptionTimestampOutputDescription = - "If true, a timestamp is added to test and debug output."; - - public virtual bool TimestampOutput => _currentSettings.TimestampOutput ?? OptionTimestampOutputDefaultValue; + => _placeholderReplacer.ReplacePathExtensionPlaceholders(PathExtension, executable); public const string OptionAdditionalTestExecutionParams = "Additional test execution parameters"; - public const string OptionAdditionalTestExecutionParamsDefaultValue = ""; public const string OptionAdditionalTestExecutionParamsDescription = - "Additional parameters for Google Test executable during test execution. Placeholders:\n" + - DescriptionOfSolutionDirPlaceHolder + "\n" + - DescriptionOfPlatformNamePlaceholder + "\n" + - DescriptionOfConfigurationNamePlaceholder + "\n" + - DescriptionOfExecutableDirPlaceHolder + "\n" + - DescriptionOfExecutablePlaceHolder + "\n" + - DescriptionOfTestDirPlaceholder + DescriptionTestExecutionOnly + "\n" + - DescriptionOfThreadIdPlaceholder + DescriptionTestExecutionOnly + "\n" + - DescriptionOfEnvVarPlaceholders; + "Additional parameters for Google Test executable during test execution. " + PlaceholderReplacer.AdditionalTestExecutionParamPlaceholders; + public const string OptionAdditionalTestExecutionParamsDefaultValue = ""; public virtual string AdditionalTestExecutionParam => _currentSettings.AdditionalTestExecutionParam ?? OptionAdditionalTestExecutionParamsDefaultValue; public string GetUserParametersForExecution(string executable, string testDirectory, int threadId) - => ReplaceEnvironmentVariables( - ReplaceSolutionDirPlaceholder( - ReplacePlatformAndConfigurationPlaceholders( - ReplaceExecutablePlaceholders( - ReplaceTestDirAndThreadIdPlaceholders(AdditionalTestExecutionParam, testDirectory, threadId), executable)))); + => _placeholderReplacer.ReplaceAdditionalTestExecutionParamPlaceholdersForExecution( + AdditionalTestExecutionParam, executable, testDirectory, threadId); public string GetUserParametersForDiscovery(string executable) - => ReplaceEnvironmentVariables( - ReplaceSolutionDirPlaceholder( - ReplacePlatformAndConfigurationPlaceholders( - RemoveTestDirAndThreadIdPlaceholders( - ReplaceExecutablePlaceholders(AdditionalTestExecutionParam, executable))))); - + => _placeholderReplacer.ReplaceAdditionalTestExecutionParamPlaceholdersForDiscovery( + AdditionalTestExecutionParam, executable); - private const string DescriptionOfPlaceholdersForBatches = - DescriptionOfSolutionDirPlaceHolder + "\n" + - DescriptionOfPlatformNamePlaceholder + "\n" + - DescriptionOfConfigurationNamePlaceholder + "\n" + - DescriptionOfTestDirPlaceholder + "\n" + - DescriptionOfThreadIdPlaceholder + "\n" + - DescriptionOfEnvVarPlaceholders; public const string OptionBatchForTestSetup = "Test setup batch file"; public const string OptionBatchForTestSetupDefaultValue = ""; public const string OptionBatchForTestSetupDescription = - "Batch file to be executed before test execution. If tests are executed in parallel, the batch file will be executed once per thread. Placeholders:\n" + - DescriptionOfPlaceholdersForBatches; + "Batch file to be executed before test execution. If tests are executed in parallel, the batch file will be executed once per thread. " + PlaceholderReplacer.BatchesPlaceholders; public virtual string BatchForTestSetup => _currentSettings.BatchForTestSetup ?? OptionBatchForTestSetupDefaultValue; public string GetBatchForTestSetup(string testDirectory, int threadId) - => ReplaceEnvironmentVariables( - ReplaceSolutionDirPlaceholder( - ReplacePlatformAndConfigurationPlaceholders( - ReplaceTestDirAndThreadIdPlaceholders(BatchForTestSetup, testDirectory, threadId)))); + => _placeholderReplacer.ReplaceBatchForTestSetupPlaceholders(BatchForTestSetup, testDirectory, threadId); public const string OptionBatchForTestTeardown = "Test teardown batch file"; - public const string OptionBatchForTestTeardownDefaultValue = ""; public const string OptionBatchForTestTeardownDescription = - "Batch file to be executed after test execution. If tests are executed in parallel, the batch file will be executed once per thread. Placeholders:\n" + - DescriptionOfPlaceholdersForBatches; + "Batch file to be executed after test execution. If tests are executed in parallel, the batch file will be executed once per thread. " + PlaceholderReplacer.BatchesPlaceholders; + public const string OptionBatchForTestTeardownDefaultValue = ""; public virtual string BatchForTestTeardown => _currentSettings.BatchForTestTeardown ?? OptionBatchForTestTeardownDefaultValue; public string GetBatchForTestTeardown(string testDirectory, int threadId) - => ReplaceEnvironmentVariables( - ReplaceSolutionDirPlaceholder( - ReplacePlatformAndConfigurationPlaceholders( - ReplaceTestDirAndThreadIdPlaceholders(BatchForTestTeardown, testDirectory, threadId)))); + => _placeholderReplacer.ReplaceBatchForTestTeardownPlaceholders(BatchForTestTeardown, testDirectory, + threadId); public const string OptionKillProcessesOnCancel = "Kill processes on cancel"; - public const bool OptionKillProcessesOnCancelDefaultValue = false; public const string OptionKillProcessesOnCancelDescription = "If true, running test executables are actively killed if the test execution is canceled. Note that killing a test process might have all kinds of side effects; in particular, Google Test will not be able to perform any shutdown tasks."; + public const bool OptionKillProcessesOnCancelDefaultValue = false; public virtual bool KillProcessesOnCancel => _currentSettings.KillProcessesOnCancel ?? OptionKillProcessesOnCancelDefaultValue; - public const string OptionSkipOriginCheck = "Skip check of file origin"; - public const bool OptionSkipOriginCheckDefaultValue = false; - public const string OptionSkipOriginCheckDescription = - "If true, it will not be checked whether executables originate from this computer. Note that this might impose security risks, e.g. when building downloaded solutions. This setting can only be changed via VS Options."; - - public virtual bool SkipOriginCheck => _currentSettings.SkipOriginCheck ?? OptionSkipOriginCheckDefaultValue; - - public const string OptionExitCodeTestCase = "Exit code test case"; - public const string OptionExitCodeTestCaseDefaultValue = ""; public const string OptionExitCodeTestCaseDescription = "If non-empty, an additional test case will be generated per test executable that passes if and only if the test executable returns exit code 0."; + public const string OptionExitCodeTestCaseDefaultValue = ""; public virtual string ExitCodeTestCase => _currentSettings.ExitCodeTestCase ?? OptionExitCodeTestCaseDefaultValue; - #endregion - - #region ParallelizationOptionsPage public const string OptionEnableParallelTestExecution = "Parallel test execution"; - public const bool OptionEnableParallelTestExecutionDefaultValue = false; public const string OptionEnableParallelTestExecutionDescription = "Parallel test execution is achieved by means of different threads, each of which is assigned a number of tests to be executed. The threads will then sequentially invoke the necessary executables to produce the according test results."; + public const bool OptionEnableParallelTestExecutionDefaultValue = false; public virtual bool ParallelTestExecution => _currentSettings.ParallelTestExecution ?? OptionEnableParallelTestExecutionDefaultValue; public const string OptionMaxNrOfThreads = "Maximum number of threads"; - public const int OptionMaxNrOfThreadsDefaultValue = 0; public const string OptionMaxNrOfThreadsDescription = "Maximum number of threads to be used for test execution (0: one thread for each processor)."; + public const int OptionMaxNrOfThreadsDefaultValue = 0; public virtual int MaxNrOfThreads { @@ -611,86 +404,98 @@ public virtual int MaxNrOfThreads #endregion - #region GoogleTestOptionsPage - - public const string OptionCatchExceptions = "Catch exceptions"; - public const bool OptionCatchExceptionsDefaultValue = true; - public const string OptionCatchExceptionsDescription = - "Google Test catches exceptions by default; the according test fails and test execution continues. Choosing false lets exceptions pass through, allowing the debugger to catch them.\n" - + "Google Test option:" + GoogleTestConstants.CatchExceptions; + #region TestDiscoveryOptionsPage - public virtual bool CatchExceptions => _currentSettings.CatchExceptions ?? OptionCatchExceptionsDefaultValue; + public const string OptionTestDiscoveryRegex = "Regex for test discovery"; + public const string OptionTestDiscoveryRegexDescription = + "If non-empty, this regex will be used to identify the Google Test executables containing your tests, and the executable itself will not be scanned."; + public const string OptionTestDiscoveryRegexDefaultValue = ""; + public virtual string TestDiscoveryRegex => _currentSettings.TestDiscoveryRegex ?? OptionTestDiscoveryRegexDefaultValue; - public const string OptionBreakOnFailure = "Break on failure"; - public const bool OptionBreakOnFailureDefaultValue = false; - public const string OptionBreakOnFailureDescription = - "If enabled, a potentially attached debugger will catch assertion failures and automatically drop into interactive mode.\n" - + "Google Test option:" + GoogleTestConstants.BreakOnFailure; - public virtual bool BreakOnFailure => _currentSettings.BreakOnFailure ?? OptionBreakOnFailureDefaultValue; + public const string OptionTestDiscoveryTimeoutInSeconds = "Test discovery timeout in s"; + public const string OptionTestDiscoveryTimeoutInSecondsDescription = + "Number of seconds after which test discovery of an executable will be assumed to have failed. 0: Infinite timeout"; + public const int OptionTestDiscoveryTimeoutInSecondsDefaultValue = 30; + public virtual int TestDiscoveryTimeoutInSeconds { + get + { + int timeout = _currentSettings.TestDiscoveryTimeoutInSeconds ?? OptionTestDiscoveryTimeoutInSecondsDefaultValue; + if (timeout < 0) + timeout = OptionTestDiscoveryTimeoutInSecondsDefaultValue; - public const string OptionRunDisabledTests = "Also run disabled tests"; - public const bool OptionRunDisabledTestsDefaultValue = false; - public const string OptionRunDisabledTestsDescription = - "If true, all (selected) tests will be run, even if they have been disabled.\n" - + "Google Test option:" + GoogleTestConstants.AlsoRunDisabledTestsOption; + return timeout == 0 ? int.MaxValue : timeout; + } + } - public virtual bool RunDisabledTests => _currentSettings.RunDisabledTests ?? OptionRunDisabledTestsDefaultValue; + public const string TraitsRegexesPairSeparator = "//||//"; + public const string TraitsRegexesRegexSeparator = "///"; + public const string TraitsRegexesTraitSeparator = ","; + public const string OptionTraitsDescription = "Allows to override/add traits for testcases matching a regex. Traits are build up in 3 phases: 1st, traits are assigned to tests according to the 'Traits before' option. 2nd, the tests' traits (defined via the macros in GTA_Traits.h) are added to the tests, overriding traits from phase 1 with new values. 3rd, the 'Traits after' option is evaluated, again in an overriding manner.\nSyntax: " + + TraitsRegexesRegexSeparator + + " separates the regex from the traits, the trait's name and value are separated by " + + TraitsRegexesTraitSeparator + + " and each pair of regex and trait is separated by " + + TraitsRegexesPairSeparator + ".\nExample: " + + @"MySuite\.*" + + TraitsRegexesRegexSeparator + "Type" + + TraitsRegexesTraitSeparator + "Small" + + TraitsRegexesPairSeparator + + @"MySuite2\.*|MySuite3\.*" + + TraitsRegexesRegexSeparator + "Type" + + TraitsRegexesTraitSeparator + "Medium"; + public const string OptionTraitsRegexesDefaultValue = ""; - public const string OptionNrOfTestRepetitions = "Number of test repetitions"; - public const int OptionNrOfTestRepetitionsDefaultValue = 1; - public const string OptionNrOfTestRepetitionsDescription = - "Tests will be run for the selected number of times (-1: infinite).\n" - + "Google Test option:" + GoogleTestConstants.NrOfRepetitionsOption; + public const string OptionTraitsRegexesBefore = "Before test discovery"; - public virtual int NrOfTestRepetitions + public virtual List TraitsRegexesBefore { get { - int nrOfRepetitions = _currentSettings.NrOfTestRepetitions ?? OptionNrOfTestRepetitionsDefaultValue; - if (nrOfRepetitions == 0 || nrOfRepetitions < -1) - { - nrOfRepetitions = OptionNrOfTestRepetitionsDefaultValue; - } - return nrOfRepetitions; + string option = _currentSettings.TraitsRegexesBefore ?? OptionTraitsRegexesDefaultValue; + return RegexTraitParser.ParseTraitsRegexesString(option); } } + public const string OptionTraitsRegexesAfter = "After test discovery"; - public const string OptionShuffleTests = "Shuffle tests per execution"; - public const bool OptionShuffleTestsDefaultValue = false; - public const string OptionShuffleTestsDescription = - "If true, tests will be executed in random order. Note that a true randomized order is only given when executing all tests in non-parallel fashion. Otherwise, the test excutables will most likely be executed more than once - random order is than restricted to the according executions.\n" - + "Google Test option:" + GoogleTestConstants.ShuffleTestsOption; - - public virtual bool ShuffleTests => _currentSettings.ShuffleTests ?? OptionShuffleTestsDefaultValue; - - - public const string OptionShuffleTestsSeed = "Shuffle tests: Seed"; - public const int OptionShuffleTestsSeedDefaultValue = GoogleTestConstants.ShuffleTestsSeedDefaultValue; - public const string OptionShuffleTestsSeedDescription = "0: Seed is computed from system time, 1<=n<=" - + GoogleTestConstants.ShuffleTestsSeedMaxValueAsString - + ": The given seed is used. See note of option '" - + OptionShuffleTests - + "'.\n" - + "Google Test option:" + GoogleTestConstants.ShuffleTestsSeedOption; - - public virtual int ShuffleTestsSeed + public virtual List TraitsRegexesAfter { get { - int seed = _currentSettings.ShuffleTestsSeed ?? OptionShuffleTestsSeedDefaultValue; - if (seed < GoogleTestConstants.ShuffleTestsSeedMinValue || seed > GoogleTestConstants.ShuffleTestsSeedMaxValue) - { - seed = OptionShuffleTestsSeedDefaultValue; - } - return seed; + string option = _currentSettings.TraitsRegexesAfter ?? OptionTraitsRegexesDefaultValue; + return RegexTraitParser.ParseTraitsRegexesString(option); } } + + public const string OptionTestNameSeparator = "Test name separator"; + public const string OptionTestNameSeparatorDescription = + "Test names produced by Google Test might contain the character '/', which makes VS cut the name after the '/' if the test explorer window is not wide enough. This option's value, if non-empty, will replace the '/' character to avoid that behavior. Note that '\\', ' ', '|', and '-' produce the same behavior ('.', '_', ':', and '::' are known to work - there might be more). Note also that traits regexes are evaluated against the tests' display names (and must thus be consistent with this option)."; + public const string OptionTestNameSeparatorDefaultValue = ""; + + public virtual string TestNameSeparator => _currentSettings.TestNameSeparator ?? OptionTestNameSeparatorDefaultValue; + + + public const string OptionParseSymbolInformation = "Parse symbol information"; + public const string OptionParseSymbolInformationDescription = + "Parse debug symbol information for test executables to obtain source location information and traits (defined via the macros in GTA_Traits.h).\n" + + "If this is set to false step 2 of traits discovery will be left out and only traits regexes will be effective."; + public const bool OptionParseSymbolInformationDefaultValue = true; + + public virtual bool ParseSymbolInformation => _currentSettings.ParseSymbolInformation ?? OptionParseSymbolInformationDefaultValue; + + + #endregion + + #region Internal properties + + public virtual string DebuggingNamedPipeId => _currentSettings.DebuggingNamedPipeId; + public virtual string SolutionDir => _solutionDir ?? _currentSettings.SolutionDir; + #endregion } diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs index 092868d1c..f96afa921 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs @@ -84,7 +84,7 @@ public virtual void RunTests_TestDirectoryViaUserParams_IsPassedViaCommandLineAr MockFrameworkHandle.Reset(); SetUpMockFrameworkHandle(); - MockOptions.Setup(o => o.AdditionalTestExecutionParam).Returns("-testdirectory=\"" + SettingsWrapper.TestDirPlaceholder + "\""); + MockOptions.Setup(o => o.AdditionalTestExecutionParam).Returns("-testdirectory=\"" + PlaceholderReplacer.TestDirPlaceholder + "\""); RunAndVerifySingleTest(testCase, VsTestOutcome.Passed); } @@ -95,12 +95,12 @@ public virtual void RunTests_WorkingDir_IsSetCorrectly() { TestCase testCase = TestDataCreator.GetTestCases("WorkingDir.IsSolutionDirectory").First(); - MockOptions.Setup(o => o.WorkingDir).Returns(SettingsWrapper.ExecutableDirPlaceholder); + MockOptions.Setup(o => o.WorkingDir).Returns(PlaceholderReplacer.ExecutableDirPlaceholder); RunAndVerifySingleTest(testCase, VsTestOutcome.Failed); MockFrameworkHandle.Reset(); SetUpMockFrameworkHandle(); - MockOptions.Setup(o => o.WorkingDir).Returns(SettingsWrapper.SolutionDirPlaceholder); + MockOptions.Setup(o => o.WorkingDir).Returns(PlaceholderReplacer.SolutionDirPlaceholder); RunAndVerifySingleTest(testCase, VsTestOutcome.Passed); } @@ -271,7 +271,7 @@ public virtual void RunTests_WithPathExtension_ExecutionOk() try { string targetExe = TestDataCreator.GetPathExtensionExecutable(baseDir); - MockOptions.Setup(o => o.PathExtension).Returns(SettingsWrapper.ExecutableDirPlaceholder + @"\..\dll"); + MockOptions.Setup(o => o.PathExtension).Returns(PlaceholderReplacer.ExecutableDirPlaceholder + @"\..\dll"); var executor = new TestExecutor(TestEnvironment.Logger, TestEnvironment.Options, MockDebuggerAttacher.Object); executor.RunTests(targetExe.Yield(), MockRunContext.Object, MockFrameworkHandle.Object); diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestExecutionOptionsDialogPage.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestExecutionOptionsDialogPage.cs index 11638f28e..e0353eb50 100644 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestExecutionOptionsDialogPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestExecutionOptionsDialogPage.cs @@ -103,7 +103,6 @@ public string AdditionalTestExecutionParams #endregion - #region Setup and teardown [Category(SettingsWrapper.CategorySetupAndTeardownName)] @@ -128,7 +127,6 @@ public string BatchForTestTeardown #endregion - #region Misc [Category(SettingsWrapper.CategoryMiscName)] From 31992480fe33cc17b735ae1738e15d572fdf85b5 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Thu, 4 Apr 2019 06:13:37 +0200 Subject: [PATCH 57/81] DebugMode can now be None, Info, Debug, or Verbose --- GoogleTestAdapter/Common/ILogger.cs | 2 ++ GoogleTestAdapter/Common/LoggerBase.cs | 33 ++++++++++++------- .../Helpers/TestEnvironmentTests.cs | 7 ++-- .../Settings/SettingsWrapperTests.cs | 11 ++++--- .../TestCases/TestCaseResolverTests.cs | 3 +- .../TestResults/XmlTestResultParserTests.cs | 5 +-- .../Settings/IGoogleTestAdapterSettings.cs | 4 ++- .../Core/Settings/RunSettings.cs | 6 ++-- .../Core/Settings/SettingsWrapper.cs | 4 +-- .../DiaResolver.Tests/DiaResolverTests.cs | 4 +-- .../DiaResolver.Tests/PdbLocatorTests.cs | 7 ++-- .../Resources/AllTestSettings.gta.runsettings | 1 - .../TestAdapter.Tests/TestDiscovererTests.cs | 1 + .../TestExecutorTestsBase.cs | 5 +-- .../TestAdapter/CommonFunctions.cs | 4 +-- .../Framework/VsTestFrameworkLogger.cs | 4 +-- .../Tests.Common/Fakes/FakeLogger.cs | 4 +-- .../GoogleTestExtensionOptionsPage.cs | 3 +- .../GoogleTestExtensionOptionsPage.cs | 12 +++++-- .../Helpers/ActivityLogLogger.cs | 2 +- .../OptionsPages/GeneralOptionsDialogPage.cs | 5 +-- .../OptionsPages/OptionsUpdater.cs | 22 +++++++++---- 22 files changed, 92 insertions(+), 57 deletions(-) diff --git a/GoogleTestAdapter/Common/ILogger.cs b/GoogleTestAdapter/Common/ILogger.cs index 44b489420..372c05d53 100644 --- a/GoogleTestAdapter/Common/ILogger.cs +++ b/GoogleTestAdapter/Common/ILogger.cs @@ -4,6 +4,7 @@ namespace GoogleTestAdapter.Common { public enum Severity { Info, Warning, Error } + public enum OutputMode { None = 0, Info = 10, Debug = 20, Verbose = 30 } public interface ILogger { @@ -13,6 +14,7 @@ public interface ILogger void DebugInfo(string message); void DebugWarning(string message); void DebugError(string message); + void VerboseInfo(string message); IList GetMessages(params Severity[] severities); diff --git a/GoogleTestAdapter/Common/LoggerBase.cs b/GoogleTestAdapter/Common/LoggerBase.cs index 86d59dcba..55839c5d2 100644 --- a/GoogleTestAdapter/Common/LoggerBase.cs +++ b/GoogleTestAdapter/Common/LoggerBase.cs @@ -15,11 +15,11 @@ protected class LogEntry private readonly IList _messages = new List(); - private readonly Func _inDebugMode; + private readonly Func _outputMode; - protected LoggerBase(Func inDebugMode) + protected LoggerBase(Func outputMode) { - _inDebugMode = inDebugMode; + _outputMode = outputMode; } public abstract void Log(Severity severity, string message); @@ -45,35 +45,44 @@ public IList GetMessages(params Severity[] severities) public virtual void LogInfo(string message) { - Log(Severity.Info, message); + if (_outputMode() >= OutputMode.Info) + Log(Severity.Info, message); } public virtual void LogWarning(string message) { - Log(Severity.Warning, message); + if (_outputMode() >= OutputMode.Info) + Log(Severity.Warning, message); } public virtual void LogError(string message) { - Log(Severity.Error, message); + if (_outputMode() >= OutputMode.Info) + Log(Severity.Error, message); } public void DebugInfo(string message) { - if (_inDebugMode()) - LogInfo(message); + if (_outputMode() >= OutputMode.Debug) + Log(Severity.Info, message); } public void DebugWarning(string message) { - if (_inDebugMode()) - LogWarning(message); + if (_outputMode() >= OutputMode.Debug) + Log(Severity.Warning, message); } public void DebugError(string message) { - if (_inDebugMode()) - LogError(message); + if (_outputMode() >= OutputMode.Debug) + Log(Severity.Error, message); + } + + public void VerboseInfo(string message) + { + if (_outputMode() >= OutputMode.Verbose) + Log(Severity.Info, message); } } diff --git a/GoogleTestAdapter/Core.Tests/Helpers/TestEnvironmentTests.cs b/GoogleTestAdapter/Core.Tests/Helpers/TestEnvironmentTests.cs index fdd816528..64ce0cde2 100644 --- a/GoogleTestAdapter/Core.Tests/Helpers/TestEnvironmentTests.cs +++ b/GoogleTestAdapter/Core.Tests/Helpers/TestEnvironmentTests.cs @@ -1,4 +1,5 @@ -using GoogleTestAdapter.Tests.Common; +using GoogleTestAdapter.Common; +using GoogleTestAdapter.Tests.Common; using GoogleTestAdapter.Tests.Common.Helpers; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -42,7 +43,7 @@ public void LogError_ProducesErrorOnLogger() [TestCategory(Unit)] public void DebugInfo_InDebugMode_ProducesInfoOnLogger() { - MockOptions.Setup(o => o.DebugMode).Returns(true); + MockOptions.Setup(o => o.DebugMode).Returns(OutputMode.Verbose); _environment.Logger.DebugInfo("bar"); MockLogger.Verify(l => l.DebugInfo(It.Is(s => s.Contains("bar"))), Times.Exactly(1)); } @@ -50,7 +51,7 @@ public void DebugInfo_InDebugMode_ProducesInfoOnLogger() [TestCategory(Unit)] public void DebugInfo_NotInDebugMode_DoesNotProduceLogging() { - MockOptions.Setup(o => o.DebugMode).Returns(false); + MockOptions.Setup(o => o.DebugMode).Returns(OutputMode.Info); _environment.Logger.DebugInfo("bar"); MockLogger.Verify(l => l.LogInfo(It.Is(s => s.Contains("bar"))), Times.Never()); } diff --git a/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs b/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs index 6daa5ac68..9ca36553a 100644 --- a/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs +++ b/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using FluentAssertions; +using GoogleTestAdapter.Common; using GoogleTestAdapter.Helpers; using GoogleTestAdapter.Tests.Common; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -199,13 +200,13 @@ public void ShuffleTests__ReturnsValueOrDefault() [TestCategory(Unit)] public void DebugMode__ReturnsValueOrDefault() { - MockXmlOptions.Setup(o => o.DebugMode).Returns((bool?)null); - bool result = TheOptions.DebugMode; + MockXmlOptions.Setup(o => o.DebugMode).Returns((OutputMode?)null); + OutputMode result = TheOptions.DebugMode; result.Should().Be(SettingsWrapper.OptionDebugModeDefaultValue); - MockXmlOptions.Setup(o => o.DebugMode).Returns(!SettingsWrapper.OptionDebugModeDefaultValue); + MockXmlOptions.Setup(o => o.DebugMode).Returns(OutputMode.Verbose); result = TheOptions.DebugMode; - result.Should().Be(!SettingsWrapper.OptionDebugModeDefaultValue); + result.Should().Be(OutputMode.Verbose); } [TestMethod] @@ -520,7 +521,7 @@ public void ToString_PrintsCorrectly() optionsString.Should().Contain("TraitsRegexesAfter: {}"); optionsString.Should().Contain("TestNameSeparator: ''"); optionsString.Should().Contain("ParseSymbolInformation: True"); - optionsString.Should().Contain("DebugMode: False"); + optionsString.Should().Contain("DebugMode: Info"); optionsString.Should().Contain("TimestampOutput: False"); optionsString.Should().Contain("AdditionalTestExecutionParam: ''"); optionsString.Should().Contain("BatchForTestSetup: 'C:\\\\myfolder\\myfile.xml'"); diff --git a/GoogleTestAdapter/Core.Tests/TestCases/TestCaseResolverTests.cs b/GoogleTestAdapter/Core.Tests/TestCases/TestCaseResolverTests.cs index 4c20f3686..d8853d7da 100644 --- a/GoogleTestAdapter/Core.Tests/TestCases/TestCaseResolverTests.cs +++ b/GoogleTestAdapter/Core.Tests/TestCases/TestCaseResolverTests.cs @@ -1,5 +1,6 @@ using System.Linq; using FluentAssertions; +using GoogleTestAdapter.Common; using GoogleTestAdapter.DiaResolver; using GoogleTestAdapter.Helpers; using GoogleTestAdapter.Tests.Common; @@ -18,7 +19,7 @@ public class TestCaseResolverTests : TestsBase [TestInitialize] public void Setup() { - _fakeLogger = new FakeLogger(() => true, false); + _fakeLogger = new FakeLogger(() => OutputMode.Verbose, false); } [TestMethod] diff --git a/GoogleTestAdapter/Core.Tests/TestResults/XmlTestResultParserTests.cs b/GoogleTestAdapter/Core.Tests/TestResults/XmlTestResultParserTests.cs index 6a83b06aa..b19d42801 100644 --- a/GoogleTestAdapter/Core.Tests/TestResults/XmlTestResultParserTests.cs +++ b/GoogleTestAdapter/Core.Tests/TestResults/XmlTestResultParserTests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using FluentAssertions; +using GoogleTestAdapter.Common; using GoogleTestAdapter.Helpers; using GoogleTestAdapter.Tests.Common; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -33,7 +34,7 @@ public void GetTestResults_InvalidFile_WarningAndEmptyResult() { IEnumerable testCases = TestDataCreator.CreateDummyTestCases("GoogleTestSuiteName1.TestMethod_001", "GoogleTestSuiteName1.TestMethod_002"); - MockOptions.Setup(o => o.DebugMode).Returns(true); + MockOptions.Setup(o => o.DebugMode).Returns(OutputMode.Verbose); var parser = new XmlTestResultParser(testCases, "someexecutable", TestResources.XmlFileBroken, TestEnvironment.Logger); List results = parser.GetTestResults(); @@ -48,7 +49,7 @@ public void GetTestResults_FileWithInvalidStatusAttribute_WarningAndEmptyResult( { IEnumerable testCases = TestDataCreator.CreateDummyTestCases("GoogleTestSuiteName1.TestMethod_001", "GoogleTestSuiteName1.TestMethod_002"); - MockOptions.Setup(o => o.DebugMode).Returns(true); + MockOptions.Setup(o => o.DebugMode).Returns(OutputMode.Verbose); var parser = new XmlTestResultParser(testCases, "someexecutable", TestResources.XmlFileBroken_InvalidStatusAttibute, TestEnvironment.Logger); List results = parser.GetTestResults(); diff --git a/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs b/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs index 0534985df..79bba71a4 100644 --- a/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs +++ b/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs @@ -1,5 +1,7 @@ // This file has been modified by Microsoft on 6/2017. +using GoogleTestAdapter.Common; + namespace GoogleTestAdapter.Settings { @@ -40,7 +42,7 @@ public interface IGoogleTestAdapterSettings string TraitsRegexesBefore { get; set; } string TestNameSeparator { get; set; } bool? ParseSymbolInformation { get; set; } - bool? DebugMode { get; set; } + OutputMode? DebugMode { get; set; } bool? TimestampOutput { get; set; } bool? KillProcessesOnCancel { get; set; } bool? SkipOriginCheck { get; set; } diff --git a/GoogleTestAdapter/Core/Settings/RunSettings.cs b/GoogleTestAdapter/Core/Settings/RunSettings.cs index 5ecc7a4b9..b7074a7e2 100644 --- a/GoogleTestAdapter/Core/Settings/RunSettings.cs +++ b/GoogleTestAdapter/Core/Settings/RunSettings.cs @@ -1,6 +1,7 @@ // This file has been modified by Microsoft on 6/2017. using System.Xml.Serialization; +using GoogleTestAdapter.Common; namespace GoogleTestAdapter.Settings { @@ -62,15 +63,12 @@ public RunSettings(string projectRegex) public virtual string TestNameSeparator { get; set; } public bool ShouldSerializeTestNameSeparator() { return TestNameSeparator != null; } - public virtual bool? DebugMode { get; set; } + public virtual OutputMode? DebugMode { get; set; } public bool ShouldSerializeDebugMode() { return DebugMode != null; } public virtual bool? TimestampOutput { get; set; } public bool ShouldSerializeTimestampOutput() { return TimestampOutput != null; } - public virtual bool? ShowReleaseNotes { get; set; } - public bool ShouldSerializeShowReleaseNotes() { return ShowReleaseNotes != null; } - public virtual bool? ParseSymbolInformation { get; set; } public bool ShouldSerializeParseSymbolInformation() { return ParseSymbolInformation != null; } diff --git a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs index 1b32aa993..b9924d035 100644 --- a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs +++ b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs @@ -163,9 +163,9 @@ public virtual void CheckCorrectUsage(string executable) public const string OptionDebugMode = "Print debug info"; public const string OptionDebugModeDescription = "If true, debug output will be printed to the test console."; - public const bool OptionDebugModeDefaultValue = false; + public const OutputMode OptionDebugModeDefaultValue = OutputMode.Info; - public virtual bool DebugMode => _currentSettings.DebugMode ?? OptionDebugModeDefaultValue; + public virtual OutputMode DebugMode => _currentSettings.DebugMode ?? OptionDebugModeDefaultValue; public const string OptionTimestampOutput = "Timestamp output"; diff --git a/GoogleTestAdapter/DiaResolver.Tests/DiaResolverTests.cs b/GoogleTestAdapter/DiaResolver.Tests/DiaResolverTests.cs index fb0474d6d..752cd4dd4 100644 --- a/GoogleTestAdapter/DiaResolver.Tests/DiaResolverTests.cs +++ b/GoogleTestAdapter/DiaResolver.Tests/DiaResolverTests.cs @@ -78,7 +78,7 @@ public void GetFunctions_ExeWithoutPdb_ErrorIsLogged() renamedPdb.AsFileInfo().Should().NotExist(); var locations = new List(); - var fakeLogger = new FakeLogger(() => true); + var fakeLogger = new FakeLogger(() => OutputMode.Verbose); try { File.Move(pdb, renamedPdb); @@ -102,7 +102,7 @@ public void GetFunctions_ExeWithoutPdb_ErrorIsLogged() private void DoResolveTest(string executable, string filter, int expectedLocations, int expectedErrorMessages, bool disposeResolver = true) { var locations = new List(); - var fakeLogger = new FakeLogger(() => false); + var fakeLogger = new FakeLogger(() => OutputMode.Info); string pdb = PdbLocator.FindPdbFile(executable, "", fakeLogger); IDiaResolver resolver = DefaultDiaResolverFactory.Instance.Create(executable, pdb, fakeLogger); diff --git a/GoogleTestAdapter/DiaResolver.Tests/PdbLocatorTests.cs b/GoogleTestAdapter/DiaResolver.Tests/PdbLocatorTests.cs index cfdf347f9..3b4cd2899 100644 --- a/GoogleTestAdapter/DiaResolver.Tests/PdbLocatorTests.cs +++ b/GoogleTestAdapter/DiaResolver.Tests/PdbLocatorTests.cs @@ -2,6 +2,7 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using FluentAssertions; +using GoogleTestAdapter.Common; using GoogleTestAdapter.Tests.Common; using GoogleTestAdapter.Tests.Common.Assertions; using GoogleTestAdapter.Tests.Common.Fakes; @@ -19,7 +20,7 @@ public void FindPdbFile_ExeWithPdb_FindsPdb() { string executable = Path.GetFullPath(TestResources.LoadTests_ReleaseX86); executable.AsFileInfo().Should().Exist(); - var fakeLogger = new FakeLogger(() => true); + var fakeLogger = new FakeLogger(() => OutputMode.Verbose); string pdbFound = PdbLocator.FindPdbFile(executable, "", fakeLogger); @@ -40,7 +41,7 @@ public void FindPdbFile_ExeWithoutPdb_AttemptsToFindPdbAreLogged() renamedPdb.AsFileInfo().Should().NotExist(); string pdbFound; - var fakeLogger = new FakeLogger(() => true); + var fakeLogger = new FakeLogger(() => OutputMode.Verbose); try { File.Move(pdb, renamedPdb); @@ -72,7 +73,7 @@ public void FindPdbFile_PATHcontainsInvalidChars_ErrorIsLogged() renamedPdb.AsFileInfo().Should().NotExist(); string pdbFound; - var fakeLogger = new FakeLogger(() => true); + var fakeLogger = new FakeLogger(() => OutputMode.Verbose); var currentPath = Environment.GetEnvironmentVariable("PATH"); try { diff --git a/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings b/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings index 40b9d756e..80731dd3c 100644 --- a/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings +++ b/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings @@ -10,7 +10,6 @@ true false false - true 4 1 false diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestDiscovererTests.cs b/GoogleTestAdapter/TestAdapter.Tests/TestDiscovererTests.cs index 7f88bce05..f3eacde33 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestDiscovererTests.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestDiscovererTests.cs @@ -80,6 +80,7 @@ public void DiscoverTests_UntrustedExecutableWithSkipOriginCheck_IsRun() var semPath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(TestResources.SemaphoreExe), "SemaphoreExe.sem")); // ReSharper disable once AssignNullToNotNullAttribute var temp2Exe = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(TestResources.SemaphoreExe), "Temp2.exe")); + temp2Exe.AsFileInfo().Should().NotExist(); // Verify untrusted exe is run MockOptions.Setup(o => o.SkipOriginCheck).Returns(true); diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs index f96afa921..9820ab3f8 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using FluentAssertions; +using GoogleTestAdapter.Common; using GoogleTestAdapter.DiaResolver; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -131,7 +132,7 @@ public virtual void RunTests_ExternallyLinkedX86Tests_CorrectTestResults() public virtual void RunTests_ExternallyLinkedX86TestsInDebugMode_CorrectTestResults() { // for at least having the debug messaging code executed once - MockOptions.Setup(o => o.DebugMode).Returns(true); + MockOptions.Setup(o => o.DebugMode).Returns(OutputMode.Verbose); RunAndVerifyTests(TestResources.DllTests_ReleaseX86, 1, 1, 0); } @@ -165,7 +166,7 @@ public virtual void RunTests_StaticallyLinkedX64Tests_CorrectTestResults() public virtual void RunTests_StaticallyLinkedX64Tests_OutputIsPrintedAtMostOnce() { MockOptions.Setup(o => o.PrintTestOutput).Returns(true); - MockOptions.Setup(o => o.DebugMode).Returns(false); + MockOptions.Setup(o => o.DebugMode).Returns(OutputMode.Info); RunAndVerifyTests(TestResources.Tests_ReleaseX64, TestResources.NrOfPassingTests, TestResources.NrOfFailingTests, 0); diff --git a/GoogleTestAdapter/TestAdapter/CommonFunctions.cs b/GoogleTestAdapter/TestAdapter/CommonFunctions.cs index 9352ac004..23be151cc 100644 --- a/GoogleTestAdapter/TestAdapter/CommonFunctions.cs +++ b/GoogleTestAdapter/TestAdapter/CommonFunctions.cs @@ -15,14 +15,14 @@ public static class CommonFunctions { public const string GtaSettingsEnvVariable = "GTA_FALLBACK_SETTINGS"; - public static void ReportErrors(ILogger logger, string phase, bool isDebugModeEnabled) + public static void ReportErrors(ILogger logger, string phase, OutputMode outputMode) { IList errors = logger.GetMessages(Severity.Error, Severity.Warning); if (errors.Count == 0) return; bool hasErrors = logger.GetMessages(Severity.Error).Count > 0; - string hint = isDebugModeEnabled + string hint = outputMode > OutputMode.Info ? "" : " (enable debug mode for more information)"; string jointErrors = string.Join(Environment.NewLine, errors); diff --git a/GoogleTestAdapter/TestAdapter/Framework/VsTestFrameworkLogger.cs b/GoogleTestAdapter/TestAdapter/Framework/VsTestFrameworkLogger.cs index d6711b5ca..512f23fb6 100644 --- a/GoogleTestAdapter/TestAdapter/Framework/VsTestFrameworkLogger.cs +++ b/GoogleTestAdapter/TestAdapter/Framework/VsTestFrameworkLogger.cs @@ -11,8 +11,8 @@ public class VsTestFrameworkLogger : LoggerBase private readonly IMessageLogger _logger; private readonly Func _timeStampOutput; - public VsTestFrameworkLogger(IMessageLogger logger, Func inDebugMode, Func timestampOutput) - : base(inDebugMode) + public VsTestFrameworkLogger(IMessageLogger logger, Func outputMode, Func timestampOutput) + : base(outputMode) { _logger = logger; _timeStampOutput = timestampOutput; diff --git a/GoogleTestAdapter/Tests.Common/Fakes/FakeLogger.cs b/GoogleTestAdapter/Tests.Common/Fakes/FakeLogger.cs index 4e6b2770b..e1de975ab 100644 --- a/GoogleTestAdapter/Tests.Common/Fakes/FakeLogger.cs +++ b/GoogleTestAdapter/Tests.Common/Fakes/FakeLogger.cs @@ -16,8 +16,8 @@ public class FakeLogger : LoggerBase public IList All => GetMessages(Enum.GetValues(typeof(Severity)).Cast().ToArray()); - public FakeLogger(Func inDebugMode, bool timestampLogMessages = true) - : base(inDebugMode) + public FakeLogger(Func outputMode, bool timestampLogMessages = true) + : base(outputMode) { _timeStampLogMessages = timestampLogMessages; } diff --git a/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs index 4516d9b79..49cfe09bf 100644 --- a/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs @@ -4,6 +4,7 @@ using System; using System.IO; using System.Threading; +using GoogleTestAdapter.Common; using GoogleTestAdapter.VsPackage.GTA.ReleaseNotes; using GoogleTestAdapter.VsPackage.Helpers; @@ -31,7 +32,7 @@ private void DisplayReleaseNotesIfNecessaryProc() string msg = $"Exception while trying to update last version and show release notes:{Environment.NewLine}{e}"; try { - new ActivityLogLogger(this, () => true).LogError(msg); + new ActivityLogLogger(this, () => OutputMode.Verbose).LogError(msg); } catch (Exception) { diff --git a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs index 192d6bd53..417cce4e8 100644 --- a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs @@ -17,6 +17,7 @@ using System.Runtime.InteropServices; using System.ServiceModel; using EnvDTE; +using GoogleTestAdapter.Common; using GoogleTestAdapter.VsPackage.GTA.Helpers; using Microsoft.VisualStudio.AsyncPackageHelpers; using VsPackage.Shared.Settings; @@ -109,8 +110,13 @@ private void InitializeOptions() (TestExecutionOptionsDialogPage) GetDialogPage(typeof(TestExecutionOptionsDialogPage)); _googleTestOptions = (GoogleTestOptionsDialogPage) GetDialogPage(typeof(GoogleTestOptionsDialogPage)); - var optionsUpdater = new OptionsUpdater(_testDiscoveryOptions, _testExecutionOptions, new ActivityLogLogger(this, () => true)); - optionsUpdater.UpdateIfNecessary(); + var optionsUpdater = new OptionsUpdater(_testDiscoveryOptions, _testExecutionOptions, _generalOptions, new ActivityLogLogger(this, () => OutputMode.Verbose)); + if (optionsUpdater.UpdateIfNecessary()) + { + _testDiscoveryOptions.SaveSettingsToStorage(); + _testExecutionOptions.SaveSettingsToStorage(); + _generalOptions.SaveSettingsToStorage(); + } _globalRunSettings.RunSettings = GetRunSettingsFromOptionPages(); @@ -279,7 +285,7 @@ private RunSettings GetRunSettingsFromOptionPages() private void GetVisualStudioConfiguration(out string solutionDir, out string platformName, out string configurationName) { - var logger = new ActivityLogLogger(this, () => true); + var logger = new ActivityLogLogger(this, () => OutputMode.Verbose); solutionDir = platformName = configurationName = null; try diff --git a/GoogleTestAdapter/VsPackage.Shared/Helpers/ActivityLogLogger.cs b/GoogleTestAdapter/VsPackage.Shared/Helpers/ActivityLogLogger.cs index f3f75cc61..34a403377 100644 --- a/GoogleTestAdapter/VsPackage.Shared/Helpers/ActivityLogLogger.cs +++ b/GoogleTestAdapter/VsPackage.Shared/Helpers/ActivityLogLogger.cs @@ -10,7 +10,7 @@ public class ActivityLogLogger : LoggerBase { private readonly GoogleTestExtensionOptionsPage _package; - public ActivityLogLogger(GoogleTestExtensionOptionsPage package, Func inDebugMode) : base(inDebugMode) + public ActivityLogLogger(GoogleTestExtensionOptionsPage package, Func outputMode) : base(outputMode) { _package = package; } diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs index 39e981e00..abd2307b9 100644 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs @@ -3,6 +3,7 @@ using GoogleTestAdapter.Settings; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; +using GoogleTestAdapter.Common; namespace GoogleTestAdapter.VsPackage.OptionsPages { @@ -25,12 +26,12 @@ public bool PrintTestOutput [Category(SettingsWrapper.CategoryOutputName)] [DisplayName(SettingsWrapper.OptionDebugMode)] [Description(SettingsWrapper.OptionDebugModeDescription)] - public bool DebugMode + public OutputMode DebugMode { get => _debugMode; set => SetAndNotify(ref _debugMode, value); } - private bool _debugMode = SettingsWrapper.OptionDebugModeDefaultValue; + private OutputMode _debugMode = SettingsWrapper.OptionDebugModeDefaultValue; [Category(SettingsWrapper.CategoryOutputName)] [DisplayName(SettingsWrapper.OptionTimestampOutput)] diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs index 28ff6875f..97d6b9666 100644 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs @@ -20,42 +20,50 @@ public class OptionsUpdater private readonly TestDiscoveryOptionsDialogPage _testDiscoveryOptions; private readonly TestExecutionOptionsDialogPage _testExecutionOptions; + private readonly GeneralOptionsDialogPage _generalOptions; private readonly ILogger _logger; - public OptionsUpdater(TestDiscoveryOptionsDialogPage testDiscoveryOptions, - TestExecutionOptionsDialogPage testExecutionOptions, ILogger logger) + public OptionsUpdater( + TestDiscoveryOptionsDialogPage testDiscoveryOptions, + TestExecutionOptionsDialogPage testExecutionOptions, + GeneralOptionsDialogPage generalOptions, + ILogger logger) { _testDiscoveryOptions = testDiscoveryOptions; _testExecutionOptions = testExecutionOptions; + _generalOptions = generalOptions; _logger = logger; } - public void UpdateIfNecessary() + public bool UpdateIfNecessary() { try { - TryUpdateIfNecessary(); + return TryUpdateIfNecessary(); } catch (Exception e) { _logger.LogError($"Error while updating options: {e}"); + return false; } } - private void TryUpdateIfNecessary() + private bool TryUpdateIfNecessary() { if (VsSettingsStorage.Instance.PropertyExists(SettingsVersion)) - return; + return false; string versionString = History.Versions.Last().ToString(); try { VsSettingsStorage.Instance.SetString(SettingsVersion, versionString); UpdateSettings(); + return true; } catch (Exception e) { _logger.LogError($"Exception caught while saving SettingsVersion. versionString: {versionString}. Exception:{Environment.NewLine}{e}"); + return false; } } @@ -79,6 +87,8 @@ private void UpdateSettings() if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestExecutionOptionsDialogPage.KillProcessesOnCancel), bool.Parse, out var killProcessesOnCancel)) { _testExecutionOptions.KillProcessesOnCancel = killProcessesOnCancel; } if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestExecutionOptionsDialogPage.UseNewTestExecutionFramework2), bool.Parse, out var useNewTestExecutionFramework2)) { _testExecutionOptions.UseNewTestExecutionFramework2 = useNewTestExecutionFramework2; } if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestExecutionOptionsDialogPage.WorkingDir), s => s, out var workingDir)) { _testExecutionOptions.WorkingDir = workingDir; } + + if (GetAndDeleteValue(GeneralOptionsPage, nameof(GeneralOptionsDialogPage.DebugMode), bool.Parse, out var debugMode)) { _generalOptions.DebugMode = debugMode ? OutputMode.Debug : OutputMode.Info; } GetAndDeleteValue(GeneralOptionsPage, "ShowReleaseNotes", bool.Parse, out _); } From cca6c5ff9c58df614daac7a85a0a44f9d43e6ee6 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Fri, 5 Apr 2019 17:55:50 +0200 Subject: [PATCH 58/81] properties are deprecated now --- .../Helpers/TestEnvironmentTests.cs | 4 +- .../Settings/SettingsWrapperTests.cs | 12 ++-- .../TestResults/XmlTestResultParserTests.cs | 4 +- .../Settings/IGoogleTestAdapterSettings.cs | 6 +- .../Core/Settings/RunSettings.cs | 8 ++- .../Core/Settings/SettingsWrapper.cs | 12 ++-- .../TestAdapter.Tests/CommonFunctionsTests.cs | 58 ++++++++++++++++++- .../Framework/VsTestFrameworkLoggerTests.cs | 2 +- .../TestExecutorTestsBase.cs | 4 +- .../TestAdapter/CommonFunctions.cs | 29 +++++++++- .../TestAdapter/GoogleTestAdapterSettings.xsd | 21 ++++++- .../Settings/RunSettingsContainer.cs | 3 +- .../Settings/RunSettingsProvider.cs | 3 +- .../TestAdapter/TestDiscoverer.cs | 2 +- GoogleTestAdapter/TestAdapter/TestExecutor.cs | 4 +- GoogleTestAdapter/Tests.Common/TestsBase.cs | 2 +- .../GoogleTestExtensionOptionsPage.cs | 4 +- .../OptionsPages/GeneralOptionsDialogPage.cs | 12 ++-- .../OptionsPages/OptionsUpdater.cs | 6 +- 19 files changed, 155 insertions(+), 41 deletions(-) diff --git a/GoogleTestAdapter/Core.Tests/Helpers/TestEnvironmentTests.cs b/GoogleTestAdapter/Core.Tests/Helpers/TestEnvironmentTests.cs index 64ce0cde2..d402bf729 100644 --- a/GoogleTestAdapter/Core.Tests/Helpers/TestEnvironmentTests.cs +++ b/GoogleTestAdapter/Core.Tests/Helpers/TestEnvironmentTests.cs @@ -43,7 +43,7 @@ public void LogError_ProducesErrorOnLogger() [TestCategory(Unit)] public void DebugInfo_InDebugMode_ProducesInfoOnLogger() { - MockOptions.Setup(o => o.DebugMode).Returns(OutputMode.Verbose); + MockOptions.Setup(o => o.OutputMode).Returns(OutputMode.Verbose); _environment.Logger.DebugInfo("bar"); MockLogger.Verify(l => l.DebugInfo(It.Is(s => s.Contains("bar"))), Times.Exactly(1)); } @@ -51,7 +51,7 @@ public void DebugInfo_InDebugMode_ProducesInfoOnLogger() [TestCategory(Unit)] public void DebugInfo_NotInDebugMode_DoesNotProduceLogging() { - MockOptions.Setup(o => o.DebugMode).Returns(OutputMode.Info); + MockOptions.Setup(o => o.OutputMode).Returns(OutputMode.Info); _environment.Logger.DebugInfo("bar"); MockLogger.Verify(l => l.LogInfo(It.Is(s => s.Contains("bar"))), Times.Never()); } diff --git a/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs b/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs index 9ca36553a..5e30e477e 100644 --- a/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs +++ b/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs @@ -200,12 +200,12 @@ public void ShuffleTests__ReturnsValueOrDefault() [TestCategory(Unit)] public void DebugMode__ReturnsValueOrDefault() { - MockXmlOptions.Setup(o => o.DebugMode).Returns((OutputMode?)null); - OutputMode result = TheOptions.DebugMode; - result.Should().Be(SettingsWrapper.OptionDebugModeDefaultValue); + MockXmlOptions.Setup(o => o.OutputMode).Returns((OutputMode?)null); + OutputMode result = TheOptions.OutputMode; + result.Should().Be(SettingsWrapper.OptionOutputModeDefaultValue); - MockXmlOptions.Setup(o => o.DebugMode).Returns(OutputMode.Verbose); - result = TheOptions.DebugMode; + MockXmlOptions.Setup(o => o.OutputMode).Returns(OutputMode.Verbose); + result = TheOptions.OutputMode; result.Should().Be(OutputMode.Verbose); } @@ -521,7 +521,7 @@ public void ToString_PrintsCorrectly() optionsString.Should().Contain("TraitsRegexesAfter: {}"); optionsString.Should().Contain("TestNameSeparator: ''"); optionsString.Should().Contain("ParseSymbolInformation: True"); - optionsString.Should().Contain("DebugMode: Info"); + optionsString.Should().Contain("OutputMode: Info"); optionsString.Should().Contain("TimestampOutput: False"); optionsString.Should().Contain("AdditionalTestExecutionParam: ''"); optionsString.Should().Contain("BatchForTestSetup: 'C:\\\\myfolder\\myfile.xml'"); diff --git a/GoogleTestAdapter/Core.Tests/TestResults/XmlTestResultParserTests.cs b/GoogleTestAdapter/Core.Tests/TestResults/XmlTestResultParserTests.cs index b19d42801..9927f9bf0 100644 --- a/GoogleTestAdapter/Core.Tests/TestResults/XmlTestResultParserTests.cs +++ b/GoogleTestAdapter/Core.Tests/TestResults/XmlTestResultParserTests.cs @@ -34,7 +34,7 @@ public void GetTestResults_InvalidFile_WarningAndEmptyResult() { IEnumerable testCases = TestDataCreator.CreateDummyTestCases("GoogleTestSuiteName1.TestMethod_001", "GoogleTestSuiteName1.TestMethod_002"); - MockOptions.Setup(o => o.DebugMode).Returns(OutputMode.Verbose); + MockOptions.Setup(o => o.OutputMode).Returns(OutputMode.Verbose); var parser = new XmlTestResultParser(testCases, "someexecutable", TestResources.XmlFileBroken, TestEnvironment.Logger); List results = parser.GetTestResults(); @@ -49,7 +49,7 @@ public void GetTestResults_FileWithInvalidStatusAttribute_WarningAndEmptyResult( { IEnumerable testCases = TestDataCreator.CreateDummyTestCases("GoogleTestSuiteName1.TestMethod_001", "GoogleTestSuiteName1.TestMethod_002"); - MockOptions.Setup(o => o.DebugMode).Returns(OutputMode.Verbose); + MockOptions.Setup(o => o.OutputMode).Returns(OutputMode.Verbose); var parser = new XmlTestResultParser(testCases, "someexecutable", TestResources.XmlFileBroken_InvalidStatusAttibute, TestEnvironment.Logger); List results = parser.GetTestResults(); diff --git a/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs b/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs index 79bba71a4..5bdfcbe03 100644 --- a/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs +++ b/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs @@ -42,8 +42,10 @@ public interface IGoogleTestAdapterSettings string TraitsRegexesBefore { get; set; } string TestNameSeparator { get; set; } bool? ParseSymbolInformation { get; set; } - OutputMode? DebugMode { get; set; } + bool? DebugMode { get; set; } + OutputMode? OutputMode { get; set; } bool? TimestampOutput { get; set; } + bool? ShowReleaseNotes { get; set; } bool? KillProcessesOnCancel { get; set; } bool? SkipOriginCheck { get; set; } string ExitCodeTestCase { get; set; } @@ -83,7 +85,9 @@ public static void GetUnsetValuesFrom(this IGoogleTestAdapterSettings self, IGoo self.TestNameSeparator = self.TestNameSeparator ?? other.TestNameSeparator; self.ParseSymbolInformation = self.ParseSymbolInformation ?? other.ParseSymbolInformation; self.DebugMode = self.DebugMode ?? other.DebugMode; + self.OutputMode = self.OutputMode ?? other.OutputMode; self.TimestampOutput = self.TimestampOutput ?? other.TimestampOutput; + self.ShowReleaseNotes = self.ShowReleaseNotes ?? other.ShowReleaseNotes; self.KillProcessesOnCancel = self.KillProcessesOnCancel ?? other.KillProcessesOnCancel; self.SkipOriginCheck = self.SkipOriginCheck ?? other.SkipOriginCheck; self.ExitCodeTestCase = self.ExitCodeTestCase ?? other.ExitCodeTestCase; diff --git a/GoogleTestAdapter/Core/Settings/RunSettings.cs b/GoogleTestAdapter/Core/Settings/RunSettings.cs index b7074a7e2..294295f85 100644 --- a/GoogleTestAdapter/Core/Settings/RunSettings.cs +++ b/GoogleTestAdapter/Core/Settings/RunSettings.cs @@ -63,12 +63,18 @@ public RunSettings(string projectRegex) public virtual string TestNameSeparator { get; set; } public bool ShouldSerializeTestNameSeparator() { return TestNameSeparator != null; } - public virtual OutputMode? DebugMode { get; set; } + public virtual bool? DebugMode { get; set; } public bool ShouldSerializeDebugMode() { return DebugMode != null; } + public virtual OutputMode? OutputMode { get; set; } + public bool ShouldSerializeOutputMode() { return OutputMode != null; } + public virtual bool? TimestampOutput { get; set; } public bool ShouldSerializeTimestampOutput() { return TimestampOutput != null; } + public virtual bool? ShowReleaseNotes { get; set; } + public bool ShouldSerializeShowReleaseNotes() { return ShowReleaseNotes != null; } + public virtual bool? ParseSymbolInformation { get; set; } public bool ShouldSerializeParseSymbolInformation() { return ParseSymbolInformation != null; } diff --git a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs index b9924d035..9a880121d 100644 --- a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs +++ b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs @@ -160,17 +160,17 @@ public virtual void CheckCorrectUsage(string executable) public virtual bool PrintTestOutput => _currentSettings.PrintTestOutput ?? OptionPrintTestOutputDefaultValue; - public const string OptionDebugMode = "Print debug info"; - public const string OptionDebugModeDescription = - "If true, debug output will be printed to the test console."; - public const OutputMode OptionDebugModeDefaultValue = OutputMode.Info; + public const string OptionOutputMode = "Output mode"; + public const string OptionOutputModeDescription = + "Controls the amount of output printed to the Tests Output window"; + public const OutputMode OptionOutputModeDefaultValue = OutputMode.Info; - public virtual OutputMode DebugMode => _currentSettings.DebugMode ?? OptionDebugModeDefaultValue; + public virtual OutputMode OutputMode => _currentSettings.OutputMode ?? OptionOutputModeDefaultValue; public const string OptionTimestampOutput = "Timestamp output"; public const string OptionTimestampOutputDescription = - "If true, a timestamp is added to test and debug output."; + "If true, a timestamp is added to the output."; public const bool OptionTimestampOutputDefaultValue = false; public virtual bool TimestampOutput => _currentSettings.TimestampOutput ?? OptionTimestampOutputDefaultValue; diff --git a/GoogleTestAdapter/TestAdapter.Tests/CommonFunctionsTests.cs b/GoogleTestAdapter/TestAdapter.Tests/CommonFunctionsTests.cs index 83cd6a1fd..f5d33e491 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/CommonFunctionsTests.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/CommonFunctionsTests.cs @@ -6,6 +6,7 @@ using Moq; using GoogleTestAdapter.Common; using GoogleTestAdapter.Settings; +using GoogleTestAdapter.TestAdapter.Settings; using GoogleTestAdapter.Tests.Common; using static GoogleTestAdapter.Tests.Common.TestMetadata.TestCategories; @@ -131,7 +132,6 @@ private void RunWithEnvVariable(string variable, string value, Action action) try { Environment.SetEnvironmentVariable(variable, value); - action(); } finally @@ -140,5 +140,61 @@ private void RunWithEnvVariable(string variable, string value, Action action) } } + [TestMethod] + [TestCategory(Unit)] + public void CreateEnvironment_DeprecatedSettingsAreNotSet_NoWarningIsLogged() + { + SetupRunSettingsAndCheckAssertions( + mockGtaSettings => + { + mockGtaSettings.Setup(s => s.DebugMode).Returns((bool?) null); + mockGtaSettings.Setup(s => s.ShowReleaseNotes).Returns((bool?) null); + }, + () => _mockMessageLogger.Verify(l => l.SendMessage( + It.Is(level => level > TestMessageLevel.Informational), + It.IsAny()), Times.Never)); + } + + [TestMethod] + [TestCategory(Unit)] + public void CreateEnvironment_DeprecatedSettingDebugMode_WarningIsLogged() + { + SetupRunSettingsAndCheckAssertions( + mockRunSettings => mockRunSettings.Setup(s => s.DebugMode).Returns(true), + () => _mockMessageLogger.Verify(l => l.SendMessage( + It.Is(level => level == TestMessageLevel.Warning), + It.Is(s => s.Contains(nameof(RunSettings.DebugMode)))))); + } + + [TestMethod] + [TestCategory(Unit)] + public void CreateEnvironment_DeprecatedSettingShowReleaseNotes_WarningIsLogged() + { + SetupRunSettingsAndCheckAssertions( + mockRunSettings => mockRunSettings.Setup(s => s.ShowReleaseNotes).Returns(true), + () => _mockMessageLogger.Verify(l => l.SendMessage( + It.Is(level => level == TestMessageLevel.Warning), + It.Is(s => s.Contains(nameof(RunSettings.ShowReleaseNotes)))))); + } + + private void SetupRunSettingsAndCheckAssertions(Action> setup, Action assertions) + { + var mockSettingsProvider = new Mock(); + _mockRunSettings.Setup(rs => rs.GetSettings(It.Is(s => s == GoogleTestConstants.SettingsName))) + .Returns(mockSettingsProvider.Object); + + var mockRunSettingsContainer = new Mock(); + mockSettingsProvider.Setup(p => p.SettingsContainer).Returns(mockRunSettingsContainer.Object); + + var mockGtaSettings = new Mock(); + mockRunSettingsContainer.Setup(c => c.SolutionSettings).Returns(mockGtaSettings.Object); + + setup(mockGtaSettings); + + CommonFunctions.CreateEnvironment(_mockRunSettings.Object, _mockMessageLogger.Object, out _, out _); + + assertions(); + } + } } \ No newline at end of file diff --git a/GoogleTestAdapter/TestAdapter.Tests/Framework/VsTestFrameworkLoggerTests.cs b/GoogleTestAdapter/TestAdapter.Tests/Framework/VsTestFrameworkLoggerTests.cs index e051b0d2f..b0c48cb23 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/Framework/VsTestFrameworkLoggerTests.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/Framework/VsTestFrameworkLoggerTests.cs @@ -16,7 +16,7 @@ public override void SetUp() { base.SetUp(); - _logger = new VsTestFrameworkLogger(MockVsLogger.Object, () => MockOptions.Object.DebugMode, () => MockOptions.Object.TimestampOutput); + _logger = new VsTestFrameworkLogger(MockVsLogger.Object, () => MockOptions.Object.OutputMode, () => MockOptions.Object.TimestampOutput); } diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs index 9820ab3f8..512a39daa 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs @@ -132,7 +132,7 @@ public virtual void RunTests_ExternallyLinkedX86Tests_CorrectTestResults() public virtual void RunTests_ExternallyLinkedX86TestsInDebugMode_CorrectTestResults() { // for at least having the debug messaging code executed once - MockOptions.Setup(o => o.DebugMode).Returns(OutputMode.Verbose); + MockOptions.Setup(o => o.OutputMode).Returns(OutputMode.Verbose); RunAndVerifyTests(TestResources.DllTests_ReleaseX86, 1, 1, 0); } @@ -166,7 +166,7 @@ public virtual void RunTests_StaticallyLinkedX64Tests_CorrectTestResults() public virtual void RunTests_StaticallyLinkedX64Tests_OutputIsPrintedAtMostOnce() { MockOptions.Setup(o => o.PrintTestOutput).Returns(true); - MockOptions.Setup(o => o.DebugMode).Returns(OutputMode.Info); + MockOptions.Setup(o => o.OutputMode).Returns(OutputMode.Info); RunAndVerifyTests(TestResources.Tests_ReleaseX64, TestResources.NrOfPassingTests, TestResources.NrOfFailingTests, 0); diff --git a/GoogleTestAdapter/TestAdapter/CommonFunctions.cs b/GoogleTestAdapter/TestAdapter/CommonFunctions.cs index 23be151cc..4cbef3c50 100644 --- a/GoogleTestAdapter/TestAdapter/CommonFunctions.cs +++ b/GoogleTestAdapter/TestAdapter/CommonFunctions.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; +using System.Reflection; using GoogleTestAdapter.Common; using GoogleTestAdapter.Helpers; using GoogleTestAdapter.Settings; @@ -54,10 +56,12 @@ public static void CreateEnvironment(IRunSettings runSettings, IMessageLogger me var settingsWrapper = new SettingsWrapper(ourRunSettings, solutionDir); - var loggerAdapter = new VsTestFrameworkLogger(messageLogger, () => settingsWrapper.DebugMode, () => settingsWrapper.TimestampOutput); + var loggerAdapter = new VsTestFrameworkLogger(messageLogger, () => settingsWrapper.OutputMode, () => settingsWrapper.TimestampOutput); var regexParser = new RegexTraitParser(loggerAdapter); settingsWrapper.RegexTraitParser = regexParser; + LogWarningsForDeprecatedSettings(ourRunSettings, loggerAdapter); + settings = settingsWrapper; logger = loggerAdapter; } @@ -147,6 +151,29 @@ private static RunSettingsContainer GetRunSettingsFromEnvVariable(IMessageLogger } } + private static void LogWarningsForDeprecatedSettings(RunSettingsContainer runSettingsContainer, ILogger logger) + { + var debugModeProperty = typeof(RunSettings).GetProperty(nameof(RunSettings.DebugMode)); + if (HasSetting(runSettingsContainer, debugModeProperty)) + { + logger.LogWarning($"GTA option '{nameof(IGoogleTestAdapterSettings.DebugMode)}' is deprecated and will be ignored - check your settings files and replace any occurence with new option '{nameof(IGoogleTestAdapterSettings.OutputMode)}' as follows:"); + logger.LogWarning("False => Info"); + logger.LogWarning("True => Verbose (consider using Debug)"); + } + + var showReleaseNotesProperty = typeof(RunSettings).GetProperty(nameof(RunSettings.ShowReleaseNotes)); + if (HasSetting(runSettingsContainer, showReleaseNotesProperty)) + { + logger.LogWarning($"GTA option '{nameof(IGoogleTestAdapterSettings.ShowReleaseNotes)}' is deprecated - check your settings files and remove any occurence."); + } + } + + private static bool HasSetting(RunSettingsContainer runSettingsContainer, PropertyInfo propertyInfo) + { + return propertyInfo.GetValue(runSettingsContainer.SolutionSettings) != null || + runSettingsContainer.ProjectSettings.Any(s => propertyInfo.GetValue(s) != null); + } + public static void LogVisualStudioVersion(ILogger logger) { VsVersion version = VsVersionUtils.GetVisualStudioVersion(logger); diff --git a/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd b/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd index 3243a4ae1..7f60f63c1 100644 --- a/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd +++ b/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd @@ -56,8 +56,27 @@ - + + + Deprecated - use OutputMode instead + + + + + + + + + + + + + + + Deprecated + + diff --git a/GoogleTestAdapter/TestAdapter/Settings/RunSettingsContainer.cs b/GoogleTestAdapter/TestAdapter/Settings/RunSettingsContainer.cs index 8e43c75e3..5ac50a502 100644 --- a/GoogleTestAdapter/TestAdapter/Settings/RunSettingsContainer.cs +++ b/GoogleTestAdapter/TestAdapter/Settings/RunSettingsContainer.cs @@ -34,7 +34,8 @@ protected InvalidRunSettingsException( public class RunSettingsContainer : TestRunSettings, IGoogleTestAdapterSettingsContainer { - public RunSettings SolutionSettings { get; } + // virtual for mocking + public virtual RunSettings SolutionSettings { get; } public List ProjectSettings { get; } = new List(); diff --git a/GoogleTestAdapter/TestAdapter/Settings/RunSettingsProvider.cs b/GoogleTestAdapter/TestAdapter/Settings/RunSettingsProvider.cs index bb98cf6e0..83fc692ff 100644 --- a/GoogleTestAdapter/TestAdapter/Settings/RunSettingsProvider.cs +++ b/GoogleTestAdapter/TestAdapter/Settings/RunSettingsProvider.cs @@ -12,7 +12,8 @@ namespace GoogleTestAdapter.TestAdapter.Settings [SettingsName(GoogleTestConstants.SettingsName)] public class RunSettingsProvider : ISettingsProvider { - public RunSettingsContainer SettingsContainer { get; private set; } + // virtual for mocking + public virtual RunSettingsContainer SettingsContainer { get; private set; } public string Name { get; private set; } = GoogleTestConstants.SettingsName; diff --git a/GoogleTestAdapter/TestAdapter/TestDiscoverer.cs b/GoogleTestAdapter/TestAdapter/TestDiscoverer.cs index ca1fd17b2..f57d24a2c 100644 --- a/GoogleTestAdapter/TestAdapter/TestDiscoverer.cs +++ b/GoogleTestAdapter/TestAdapter/TestDiscoverer.cs @@ -63,7 +63,7 @@ public void DiscoverTests(IEnumerable executables, IDiscoveryContext dis _logger.LogError($"Exception while discovering tests: {e}"); } - CommonFunctions.ReportErrors(_logger, "test discovery", _settings.DebugMode); + CommonFunctions.ReportErrors(_logger, "test discovery", _settings.OutputMode); } private bool IsSupportedVisualStudioVersion() diff --git a/GoogleTestAdapter/TestAdapter/TestExecutor.cs b/GoogleTestAdapter/TestAdapter/TestExecutor.cs index a76991915..1aae57a28 100644 --- a/GoogleTestAdapter/TestAdapter/TestExecutor.cs +++ b/GoogleTestAdapter/TestAdapter/TestExecutor.cs @@ -56,7 +56,7 @@ public void RunTests(IEnumerable executables, IRunContext runContext, IF _logger.LogError($"Exception while running tests: {e}"); } - CommonFunctions.ReportErrors(_logger, "test execution", _settings.DebugMode); + CommonFunctions.ReportErrors(_logger, "test execution", _settings.OutputMode); } public void RunTests(IEnumerable vsTestCasesToRun, IRunContext runContext, IFrameworkHandle frameworkHandle) @@ -70,7 +70,7 @@ public void RunTests(IEnumerable vsTestCasesToRun, IRunContext runCo _logger.LogError("Exception while running tests: " + e); } - CommonFunctions.ReportErrors(_logger, "test execution", _settings.DebugMode); + CommonFunctions.ReportErrors(_logger, "test execution", _settings.OutputMode); } public void Cancel() diff --git a/GoogleTestAdapter/Tests.Common/TestsBase.cs b/GoogleTestAdapter/Tests.Common/TestsBase.cs index 96bd82639..a6cf46d79 100644 --- a/GoogleTestAdapter/Tests.Common/TestsBase.cs +++ b/GoogleTestAdapter/Tests.Common/TestsBase.cs @@ -78,7 +78,7 @@ public static void SetupOptions(Mock mockOptions) mockOptions.Setup(o => o.ShuffleTests).Returns(SettingsWrapper.OptionShuffleTestsDefaultValue); mockOptions.Setup(o => o.ShuffleTestsSeed).Returns(SettingsWrapper.OptionShuffleTestsSeedDefaultValue); mockOptions.Setup(o => o.ParseSymbolInformation).Returns(SettingsWrapper.OptionParseSymbolInformationDefaultValue); - mockOptions.Setup(o => o.DebugMode).Returns(SettingsWrapper.OptionDebugModeDefaultValue); + mockOptions.Setup(o => o.OutputMode).Returns(SettingsWrapper.OptionOutputModeDefaultValue); mockOptions.Setup(o => o.TimestampOutput).Returns(SettingsWrapper.OptionTimestampOutputDefaultValue); mockOptions.Setup(o => o.AdditionalTestExecutionParam) .Returns(SettingsWrapper.OptionAdditionalTestExecutionParamsDefaultValue); diff --git a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs index 417cce4e8..8779aed74 100644 --- a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs @@ -136,7 +136,7 @@ private void InitializeCommands() private void InitializeDebuggerAttacherService() { - var logger = new ActivityLogLogger(this, () => _generalOptions.DebugMode); + var logger = new ActivityLogLogger(this, () => _generalOptions.OutputMode); var debuggerAttacher = new VsDebuggerAttacher(this); _debuggerAttacherServiceHost = new DebuggerAttacherServiceHost(_debuggingNamedPipeId, debuggerAttacher, logger); try @@ -246,7 +246,7 @@ private RunSettings GetRunSettingsFromOptionPages() return new RunSettings { PrintTestOutput = _generalOptions.PrintTestOutput, - DebugMode = _generalOptions.DebugMode, + OutputMode = _generalOptions.OutputMode, TimestampOutput = _generalOptions.TimestampOutput, SkipOriginCheck = _generalOptions.SkipOriginCheck, diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs index abd2307b9..eb932d484 100644 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs @@ -24,14 +24,14 @@ public bool PrintTestOutput private bool _printTestOutput = SettingsWrapper.OptionPrintTestOutputDefaultValue; [Category(SettingsWrapper.CategoryOutputName)] - [DisplayName(SettingsWrapper.OptionDebugMode)] - [Description(SettingsWrapper.OptionDebugModeDescription)] - public OutputMode DebugMode + [DisplayName(SettingsWrapper.OptionOutputMode)] + [Description(SettingsWrapper.OptionOutputModeDescription)] + public OutputMode OutputMode { - get => _debugMode; - set => SetAndNotify(ref _debugMode, value); + get => _outputMode; + set => SetAndNotify(ref _outputMode, value); } - private OutputMode _debugMode = SettingsWrapper.OptionDebugModeDefaultValue; + private OutputMode _outputMode = SettingsWrapper.OptionOutputModeDefaultValue; [Category(SettingsWrapper.CategoryOutputName)] [DisplayName(SettingsWrapper.OptionTimestampOutput)] diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs index 97d6b9666..dc0e1be65 100644 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using GoogleTestAdapter.Common; +using GoogleTestAdapter.Settings; using GoogleTestAdapter.TestAdapter.Framework; using GoogleTestAdapter.VsPackage.GTA.Helpers; using GoogleTestAdapter.VsPackage.OptionsPages; @@ -88,9 +89,8 @@ private void UpdateSettings() if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestExecutionOptionsDialogPage.UseNewTestExecutionFramework2), bool.Parse, out var useNewTestExecutionFramework2)) { _testExecutionOptions.UseNewTestExecutionFramework2 = useNewTestExecutionFramework2; } if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestExecutionOptionsDialogPage.WorkingDir), s => s, out var workingDir)) { _testExecutionOptions.WorkingDir = workingDir; } - if (GetAndDeleteValue(GeneralOptionsPage, nameof(GeneralOptionsDialogPage.DebugMode), bool.Parse, out var debugMode)) { _generalOptions.DebugMode = debugMode ? OutputMode.Debug : OutputMode.Info; } - - GetAndDeleteValue(GeneralOptionsPage, "ShowReleaseNotes", bool.Parse, out _); + if (GetAndDeleteValue(GeneralOptionsPage, nameof(IGoogleTestAdapterSettings.DebugMode), bool.Parse, out var debugMode)) { _generalOptions.OutputMode = debugMode ? OutputMode.Debug : OutputMode.Info; } + GetAndDeleteValue(GeneralOptionsPage, nameof(IGoogleTestAdapterSettings.ShowReleaseNotes), bool.Parse, out _); } private static bool GetAndDeleteValue(string optionsKey, string propertyName, Func map, out T value) From 190f1712694e19c5337562d3a09063390c981238 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sat, 6 Apr 2019 09:05:51 +0200 Subject: [PATCH 59/81] added .vs folder to .gitignore of SampleTests solution --- SampleTests/.gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SampleTests/.gitignore b/SampleTests/.gitignore index ca08c8708..9a192f59a 100644 --- a/SampleTests/.gitignore +++ b/SampleTests/.gitignore @@ -1,3 +1,4 @@ SampleTests.VC.db SampleTests.VC.VC.opendb -packages \ No newline at end of file +packages +.vs \ No newline at end of file From 6033618238eff5c6c7f0fcad8b66194e672f8321 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sat, 13 Apr 2019 09:48:51 +0200 Subject: [PATCH 60/81] added VS2019 toolset to test executables --- GoogleTestAdapter/CrashingExe/CrashingExe.vcxproj | 4 ++++ GoogleTestAdapter/FailingExe/FailingExe.vcxproj | 4 ++++ .../FakeGtestDll/FakeGtestDllApplication-x64.vcxproj | 2 ++ .../FakeGtestDll/FakeGtestDllApplication.vcxproj | 2 ++ .../FakeGtestDll/FakeGtestDllLibrary-x64.vcxproj | 2 ++ GoogleTestAdapter/FakeGtestDll/FakeGtestDllLibrary.vcxproj | 2 ++ GoogleTestAdapter/SemaphoreExe/SemaphoreExe.vcxproj | 3 ++- 7 files changed, 18 insertions(+), 1 deletion(-) diff --git a/GoogleTestAdapter/CrashingExe/CrashingExe.vcxproj b/GoogleTestAdapter/CrashingExe/CrashingExe.vcxproj index c8326f7bb..984759271 100644 --- a/GoogleTestAdapter/CrashingExe/CrashingExe.vcxproj +++ b/GoogleTestAdapter/CrashingExe/CrashingExe.vcxproj @@ -34,6 +34,7 @@ v120 v140 v141 + v142 Unicode @@ -44,6 +45,7 @@ v120 v140 v141 + v142 true Unicode @@ -55,6 +57,7 @@ v120 v140 v141 + v142 Unicode @@ -65,6 +68,7 @@ v120 v140 v141 + v142 true Unicode diff --git a/GoogleTestAdapter/FailingExe/FailingExe.vcxproj b/GoogleTestAdapter/FailingExe/FailingExe.vcxproj index fd1aae81c..aa5843170 100644 --- a/GoogleTestAdapter/FailingExe/FailingExe.vcxproj +++ b/GoogleTestAdapter/FailingExe/FailingExe.vcxproj @@ -34,6 +34,7 @@ v120 v140 v141 + v142 Unicode @@ -44,6 +45,7 @@ v120 v140 v141 + v142 true Unicode @@ -55,6 +57,7 @@ v120 v140 v141 + v142 Unicode @@ -65,6 +68,7 @@ v120 v140 v141 + v142 true Unicode diff --git a/GoogleTestAdapter/FakeGtestDll/FakeGtestDllApplication-x64.vcxproj b/GoogleTestAdapter/FakeGtestDll/FakeGtestDllApplication-x64.vcxproj index 75991a89d..acfba1f1f 100644 --- a/GoogleTestAdapter/FakeGtestDll/FakeGtestDllApplication-x64.vcxproj +++ b/GoogleTestAdapter/FakeGtestDll/FakeGtestDllApplication-x64.vcxproj @@ -26,6 +26,7 @@ v120 v140 v141 + v142 Unicode @@ -36,6 +37,7 @@ v120 v140 v141 + v142 true Unicode diff --git a/GoogleTestAdapter/FakeGtestDll/FakeGtestDllApplication.vcxproj b/GoogleTestAdapter/FakeGtestDll/FakeGtestDllApplication.vcxproj index 49430806f..46475fbbb 100644 --- a/GoogleTestAdapter/FakeGtestDll/FakeGtestDllApplication.vcxproj +++ b/GoogleTestAdapter/FakeGtestDll/FakeGtestDllApplication.vcxproj @@ -26,6 +26,7 @@ v120 v140 v141 + v142 Unicode @@ -36,6 +37,7 @@ v120 v140 v141 + v142 true Unicode diff --git a/GoogleTestAdapter/FakeGtestDll/FakeGtestDllLibrary-x64.vcxproj b/GoogleTestAdapter/FakeGtestDll/FakeGtestDllLibrary-x64.vcxproj index 9a69bc133..d9463f3bc 100644 --- a/GoogleTestAdapter/FakeGtestDll/FakeGtestDllLibrary-x64.vcxproj +++ b/GoogleTestAdapter/FakeGtestDll/FakeGtestDllLibrary-x64.vcxproj @@ -26,6 +26,7 @@ v120 v140 v141 + v142 Unicode @@ -36,6 +37,7 @@ v120 v140 v141 + v142 true Unicode diff --git a/GoogleTestAdapter/FakeGtestDll/FakeGtestDllLibrary.vcxproj b/GoogleTestAdapter/FakeGtestDll/FakeGtestDllLibrary.vcxproj index ee54d657c..646f6ec07 100644 --- a/GoogleTestAdapter/FakeGtestDll/FakeGtestDllLibrary.vcxproj +++ b/GoogleTestAdapter/FakeGtestDll/FakeGtestDllLibrary.vcxproj @@ -26,6 +26,7 @@ v120 v140 v141 + v142 Unicode @@ -36,6 +37,7 @@ v120 v140 v141 + v142 true Unicode diff --git a/GoogleTestAdapter/SemaphoreExe/SemaphoreExe.vcxproj b/GoogleTestAdapter/SemaphoreExe/SemaphoreExe.vcxproj index 9c657d7a9..09fddff84 100644 --- a/GoogleTestAdapter/SemaphoreExe/SemaphoreExe.vcxproj +++ b/GoogleTestAdapter/SemaphoreExe/SemaphoreExe.vcxproj @@ -28,7 +28,8 @@ Application - v141 + v141 + v142 Unicode From 12251a0858f859892c7f39bbf0dce52f856f2660 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Tue, 16 Apr 2019 18:37:35 +0200 Subject: [PATCH 61/81] improvements for test output --- GoogleTestAdapter/Core/GoogleTestDiscoverer.cs | 4 ++-- GoogleTestAdapter/Core/Settings/SettingsWrapper.cs | 7 ++++--- GoogleTestAdapter/TestAdapter/TestAdapter.csproj | 2 -- .../Settings/RunSettingsServiceTests.cs | 2 +- .../VsPackage.Shared/Settings/RunSettingsService.cs | 9 +++++++-- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/GoogleTestAdapter/Core/GoogleTestDiscoverer.cs b/GoogleTestAdapter/Core/GoogleTestDiscoverer.cs index 5ca35fbed..4c5eed25d 100644 --- a/GoogleTestAdapter/Core/GoogleTestDiscoverer.cs +++ b/GoogleTestAdapter/Core/GoogleTestDiscoverer.cs @@ -56,7 +56,7 @@ private static void DiscoverTests(string executable, ITestFrameworkReporter repo void ReportTestCases(TestCase testCase) { reporter.ReportTestsFound(testCase.Yield()); - logger.DebugInfo("Added testcase " + testCase.DisplayName); + logger.VerboseInfo("Added testcase " + testCase.DisplayName); nrOfTestCases++; } @@ -73,7 +73,7 @@ public IList GetTestsFromExecutable(string executable) foreach (TestCase testCase in testCases) { - _logger.DebugInfo("Added testcase " + testCase.DisplayName); + _logger.VerboseInfo("Added testcase " + testCase.DisplayName); } _logger.LogInfo("Found " + testCases.Count + " tests in executable " + executable); diff --git a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs index 9a880121d..0940e5c09 100644 --- a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs +++ b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs @@ -88,14 +88,15 @@ void EnableSettingsForExecutable() _currentSettings = projectSettings; string settingsString = ToString(); _currentSettings = _settingsContainer.SolutionSettings; - logger.DebugInfo($"Settings for test executable '{executable}': {settingsString}"); + logger.DebugInfo($"Test executable '{executable}': Project settings apply, regex: {projectSettings.ProjectRegex}"); + logger.VerboseInfo($"Settings for test executable '{executable}': {settingsString}"); _currentSettings = projectSettings; } else { logger.DebugInfo( - $"No settings configured for test executable '{executable}'; running with solution settings: {this}"); + $"No settings configured for test executable '{executable}'; running with solution settings"); } } @@ -106,7 +107,7 @@ void ReenableSolutionSettings() if (_currentSettings != _settingsContainer.SolutionSettings) { _currentSettings = _settingsContainer.SolutionSettings; - logger.DebugInfo($"Back to solution settings: {this}"); + logger.DebugInfo($"Back to solution settings"); } } diff --git a/GoogleTestAdapter/TestAdapter/TestAdapter.csproj b/GoogleTestAdapter/TestAdapter/TestAdapter.csproj index 580b4f984..c5d071707 100644 --- a/GoogleTestAdapter/TestAdapter/TestAdapter.csproj +++ b/GoogleTestAdapter/TestAdapter/TestAdapter.csproj @@ -31,7 +31,6 @@ prompt 4 true - true pdbonly @@ -40,7 +39,6 @@ prompt 4 true - true diff --git a/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/Settings/RunSettingsServiceTests.cs b/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/Settings/RunSettingsServiceTests.cs index 4fb64d4e4..0674e6798 100644 --- a/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/Settings/RunSettingsServiceTests.cs +++ b/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/Settings/RunSettingsServiceTests.cs @@ -78,7 +78,7 @@ public void AddRunSettings_BrokenSolutionSettings_Warning() AssertContainsSetting(xml, "ShuffleTestsSeed", "3"); AssertContainsSetting(xml, "TraitsRegexesBefore", "User///A,B"); - mockLogger.Verify(l => l.Log(It.Is(ml => ml == MessageLevel.Warning), It.Is(s => s.Contains("could not be parsed"))), + mockLogger.Verify(l => l.Log(It.Is(ml => ml == MessageLevel.Error), It.Is(s => s.Contains("could not be parsed"))), Times.Exactly(1)); } diff --git a/GoogleTestAdapter/VsPackage.Shared/Settings/RunSettingsService.cs b/GoogleTestAdapter/VsPackage.Shared/Settings/RunSettingsService.cs index f18f9e759..52bf9e324 100644 --- a/GoogleTestAdapter/VsPackage.Shared/Settings/RunSettingsService.cs +++ b/GoogleTestAdapter/VsPackage.Shared/Settings/RunSettingsService.cs @@ -84,10 +84,15 @@ private void GetValuesFromSolutionSettingsFile(RunSettingsContainer settingsCont } } } + catch (InvalidRunSettingsException e) when (e.InnerException != null) + { + logger.Log(MessageLevel.Error, + $"Solution test settings file could not be parsed, check file '{solutionRunSettingsFile}'. Error message: {e.InnerException.Message}"); + } catch (Exception e) { - logger.Log(MessageLevel.Warning, - $"Solution test settings file could not be parsed, check file: {solutionRunSettingsFile}{Environment.NewLine}Exception: {e}"); + logger.Log(MessageLevel.Error, + $"Solution test settings file could not be parsed, check file '{solutionRunSettingsFile}'. Exception:{Environment.NewLine}{e}"); } } From 03d1fb50720b5a40f797b76367ae1758d82601df Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sat, 6 Apr 2019 12:11:42 +0200 Subject: [PATCH 62/81] debugger attacher supports engines Native and ManagedAndNative --- .../Common/IDebuggerAttacherService.cs | 9 ++++++++- .../Contracts/IDebuggedProcessExecutorFactory.cs | 2 +- .../Core/Runners/SequentialTestRunner.cs | 4 +++- .../NativeDebuggedProcessExecutorTests.cs | 6 +++--- .../TestAdapter.Tests/TestExecutorTestsBase.cs | 2 +- .../DebuggedProcessExecutorFactory.cs | 4 ++-- .../ProcessExecution/IDebuggerAttacher.cs | 6 ++++-- .../MessageBasedDebuggerAttacher.cs | 4 ++-- .../NativeDebuggedProcessExecutor.cs | 11 +++++++---- GoogleTestAdapter/Tests.Common/TestsBase.cs | 2 +- .../Debugging/DebuggerAttacherServiceTests.cs | 11 ++++------- .../MessageBasedDebuggerAttacherTests.cs | 15 ++++++--------- .../Debugging/DebuggerAttacherService.cs | 7 +++---- .../Debugging/VsDebuggerAttacher.cs | 10 ++++++---- 14 files changed, 51 insertions(+), 42 deletions(-) diff --git a/GoogleTestAdapter/Common/IDebuggerAttacherService.cs b/GoogleTestAdapter/Common/IDebuggerAttacherService.cs index 4d86519c5..716edfd53 100644 --- a/GoogleTestAdapter/Common/IDebuggerAttacherService.cs +++ b/GoogleTestAdapter/Common/IDebuggerAttacherService.cs @@ -7,6 +7,12 @@ namespace GoogleTestAdapter.Common { + public enum DebuggerEngine + { + Native, ManagedAndNative + } + + /// /// Interface of DebuggerAttacherService. /// @@ -17,9 +23,10 @@ public interface IDebuggerAttacherService /// Attaches the debugger to the specified process. ///
/// ID of a process to attach to + /// Engine kind to be attached [OperationContract] [FaultContract(typeof(DebuggerAttacherServiceFault))] - void AttachDebugger(int processId); + void AttachDebugger(int processId, DebuggerEngine debuggerEngine); } /// diff --git a/GoogleTestAdapter/Core/ProcessExecution/Contracts/IDebuggedProcessExecutorFactory.cs b/GoogleTestAdapter/Core/ProcessExecution/Contracts/IDebuggedProcessExecutorFactory.cs index 0dc939cfc..4af128193 100644 --- a/GoogleTestAdapter/Core/ProcessExecution/Contracts/IDebuggedProcessExecutorFactory.cs +++ b/GoogleTestAdapter/Core/ProcessExecution/Contracts/IDebuggedProcessExecutorFactory.cs @@ -6,6 +6,6 @@ public interface IDebuggedProcessExecutorFactory : IProcessExecutorFactory { IDebuggedProcessExecutor CreateFrameworkDebuggingExecutor(bool printTestOutput, ILogger logger); - IDebuggedProcessExecutor CreateNativeDebuggingExecutor(bool printTestOutput, ILogger logger); + IDebuggedProcessExecutor CreateNativeDebuggingExecutor(DebuggerEngine debuggerEngine, bool printTestOutput, ILogger logger); } } diff --git a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs index 1984d6dd7..d30fbd8c4 100644 --- a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs @@ -191,7 +191,9 @@ void OnNewOutputLine(string line) _processExecutor = isBeingDebugged ? _settings.UseNewTestExecutionFramework - ? processExecutorFactory.CreateNativeDebuggingExecutor(printTestOutput, _logger) + ? processExecutorFactory.CreateNativeDebuggingExecutor( + DebuggerEngine.Native, + printTestOutput, _logger) : processExecutorFactory.CreateFrameworkDebuggingExecutor(printTestOutput, _logger) : processExecutorFactory.CreateExecutor(printTestOutput, _logger); int exitCode = _processExecutor.ExecuteCommandBlocking( diff --git a/GoogleTestAdapter/TestAdapter.Tests/ProcessExecution/NativeDebuggedProcessExecutorTests.cs b/GoogleTestAdapter/TestAdapter.Tests/ProcessExecution/NativeDebuggedProcessExecutorTests.cs index ac4f0f87f..9b41e9a0d 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/ProcessExecution/NativeDebuggedProcessExecutorTests.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/ProcessExecution/NativeDebuggedProcessExecutorTests.cs @@ -1,4 +1,4 @@ -using GoogleTestAdapter.ProcessExecution; +using GoogleTestAdapter.Common; using GoogleTestAdapter.Tests.Common; using GoogleTestAdapter.Tests.Common.Tests; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -14,8 +14,8 @@ public class NativeDebuggedProcessExecutorTests : ProcessExecutorTests [TestInitialize] public void Setup() { - _mockDebuggerAttacher.Setup(a => a.AttachDebugger(It.IsAny())).Returns(true); - ProcessExecutor = new NativeDebuggedProcessExecutor(_mockDebuggerAttacher.Object, true, MockLogger.Object); + _mockDebuggerAttacher.Setup(a => a.AttachDebugger(It.IsAny(), It.IsAny())).Returns(true); + ProcessExecutor = new NativeDebuggedProcessExecutor(_mockDebuggerAttacher.Object, DebuggerEngine.Native, true, MockLogger.Object); } [TestCleanup] diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs index 512a39daa..b366747e3 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs @@ -60,7 +60,7 @@ public override void SetUp() MockOptions.Setup(o => o.MaxNrOfThreads).Returns(_maxNrOfThreads); MockDebuggerAttacher.Reset(); - MockDebuggerAttacher.Setup(a => a.AttachDebugger(It.IsAny())).Returns(true); + MockDebuggerAttacher.Setup(a => a.AttachDebugger(It.IsAny(), It.IsAny())).Returns(true); } private void RunAndVerifySingleTest(TestCase testCase, VsTestOutcome expectedOutcome) diff --git a/GoogleTestAdapter/TestAdapter/ProcessExecution/DebuggedProcessExecutorFactory.cs b/GoogleTestAdapter/TestAdapter/ProcessExecution/DebuggedProcessExecutorFactory.cs index b2464b02a..e60b0925a 100644 --- a/GoogleTestAdapter/TestAdapter/ProcessExecution/DebuggedProcessExecutorFactory.cs +++ b/GoogleTestAdapter/TestAdapter/ProcessExecution/DebuggedProcessExecutorFactory.cs @@ -16,9 +16,9 @@ public DebuggedProcessExecutorFactory(IFrameworkHandle frameworkHandle, IDebugge _debuggerAttacher = debuggerAttacher; } - public IDebuggedProcessExecutor CreateNativeDebuggingExecutor(bool printTestOutput, ILogger logger) + public IDebuggedProcessExecutor CreateNativeDebuggingExecutor(DebuggerEngine debuggerEngine, bool printTestOutput, ILogger logger) { - return new NativeDebuggedProcessExecutor(_debuggerAttacher, printTestOutput, logger); + return new NativeDebuggedProcessExecutor(_debuggerAttacher, debuggerEngine, printTestOutput, logger); } public IDebuggedProcessExecutor CreateFrameworkDebuggingExecutor(bool printTestOutput, ILogger logger) diff --git a/GoogleTestAdapter/TestAdapter/ProcessExecution/IDebuggerAttacher.cs b/GoogleTestAdapter/TestAdapter/ProcessExecution/IDebuggerAttacher.cs index 43a98e6b5..0f8bf9dc2 100644 --- a/GoogleTestAdapter/TestAdapter/ProcessExecution/IDebuggerAttacher.cs +++ b/GoogleTestAdapter/TestAdapter/ProcessExecution/IDebuggerAttacher.cs @@ -1,7 +1,9 @@ -namespace GoogleTestAdapter.TestAdapter.ProcessExecution +using GoogleTestAdapter.Common; + +namespace GoogleTestAdapter.TestAdapter.ProcessExecution { public interface IDebuggerAttacher { - bool AttachDebugger(int processId); + bool AttachDebugger(int processId, DebuggerEngine debuggerEngine); } } \ No newline at end of file diff --git a/GoogleTestAdapter/TestAdapter/ProcessExecution/MessageBasedDebuggerAttacher.cs b/GoogleTestAdapter/TestAdapter/ProcessExecution/MessageBasedDebuggerAttacher.cs index fb68276c6..5063936dd 100644 --- a/GoogleTestAdapter/TestAdapter/ProcessExecution/MessageBasedDebuggerAttacher.cs +++ b/GoogleTestAdapter/TestAdapter/ProcessExecution/MessageBasedDebuggerAttacher.cs @@ -26,7 +26,7 @@ public MessageBasedDebuggerAttacher(string debuggingNamedPipeId, ILogger logger) { } - public bool AttachDebugger(int processId) + public bool AttachDebugger(int processId, DebuggerEngine debuggerEngine) { try { @@ -35,7 +35,7 @@ public bool AttachDebugger(int processId) var proxy = DebuggerAttacherServiceConfiguration.CreateProxy(_debuggingNamedPipeId, _timeout); using (var client = new DebuggerAttacherServiceProxyWrapper(proxy)) { - client.Service.AttachDebugger(processId); + client.Service.AttachDebugger(processId, debuggerEngine); stopWatch.Stop(); _logger.DebugInfo($"Debugger attached to process {processId}, took {stopWatch.ElapsedMilliseconds} ms"); return true; diff --git a/GoogleTestAdapter/TestAdapter/ProcessExecution/NativeDebuggedProcessExecutor.cs b/GoogleTestAdapter/TestAdapter/ProcessExecution/NativeDebuggedProcessExecutor.cs index b61951de0..3a244ecc9 100644 --- a/GoogleTestAdapter/TestAdapter/ProcessExecution/NativeDebuggedProcessExecutor.cs +++ b/GoogleTestAdapter/TestAdapter/ProcessExecution/NativeDebuggedProcessExecutor.cs @@ -24,12 +24,14 @@ public class NativeDebuggedProcessExecutor : IDebuggedProcessExecutor public const int ExecutionFailed = int.MaxValue; private readonly IDebuggerAttacher _debuggerAttacher; + private readonly DebuggerEngine _debuggerEngine; private readonly bool _printTestOutput; private readonly ILogger _logger; - public NativeDebuggedProcessExecutor(IDebuggerAttacher debuggerAttacher, bool printTestOutput, ILogger logger) + public NativeDebuggedProcessExecutor(IDebuggerAttacher debuggerAttacher, DebuggerEngine debuggerEngine, bool printTestOutput, ILogger logger) { _debuggerAttacher = debuggerAttacher ?? throw new ArgumentNullException(nameof(debuggerAttacher)); + _debuggerEngine = debuggerEngine; _printTestOutput = printTestOutput; _logger = logger; } @@ -38,7 +40,7 @@ public int ExecuteCommandBlocking(string command, string parameters, string work { try { - int exitCode = NativeMethods.ExecuteCommandBlocking(command, parameters, workingDir, pathExtension, _debuggerAttacher, _logger, _printTestOutput, reportOutputLine, processId => _processId = processId); + int exitCode = NativeMethods.ExecuteCommandBlocking(command, parameters, workingDir, pathExtension, _debuggerAttacher, _debuggerEngine, _logger, _printTestOutput, reportOutputLine, processId => _processId = processId); _logger.DebugInfo($"Executable {command} returned with exit code {exitCode}"); return exitCode; } @@ -103,7 +105,8 @@ protected override void Dispose(bool disposing) internal static int ExecuteCommandBlocking( string command, string parameters, string workingDir, string pathExtension, - IDebuggerAttacher debuggerAttacher, ILogger logger, bool printTestOutput, Action reportOutputLine, Action reportProcessId) + IDebuggerAttacher debuggerAttacher, DebuggerEngine debuggerEngine, + ILogger logger, bool printTestOutput, Action reportOutputLine, Action reportProcessId) { ProcessOutputPipeStream pipeStream = null; try @@ -118,7 +121,7 @@ internal static int ExecuteCommandBlocking( pipeStream.ConnectedToChildProcess(); logger.DebugInfo($"Attaching debugger to '{command}' via native implementation"); - if (!debuggerAttacher.AttachDebugger(processInfo.dwProcessId)) + if (!debuggerAttacher.AttachDebugger(processInfo.dwProcessId, debuggerEngine)) { logger.LogError($"Could not attach debugger to process {processInfo.dwProcessId}"); } diff --git a/GoogleTestAdapter/Tests.Common/TestsBase.cs b/GoogleTestAdapter/Tests.Common/TestsBase.cs index a6cf46d79..706e45bc5 100644 --- a/GoogleTestAdapter/Tests.Common/TestsBase.cs +++ b/GoogleTestAdapter/Tests.Common/TestsBase.cs @@ -21,7 +21,7 @@ public IDebuggedProcessExecutor CreateFrameworkDebuggingExecutor(bool printTestO throw new NotImplementedException(); } - public IDebuggedProcessExecutor CreateNativeDebuggingExecutor(bool printTestOutput, ILogger logger) + public IDebuggedProcessExecutor CreateNativeDebuggingExecutor(DebuggerEngine engine, bool printTestOutput, ILogger logger) { throw new NotImplementedException(); } diff --git a/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/Debugging/DebuggerAttacherServiceTests.cs b/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/Debugging/DebuggerAttacherServiceTests.cs index a40a6efbe..5e615c301 100644 --- a/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/Debugging/DebuggerAttacherServiceTests.cs +++ b/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/Debugging/DebuggerAttacherServiceTests.cs @@ -2,14 +2,11 @@ using FluentAssertions; using GoogleTestAdapter.Common; -using GoogleTestAdapter.Framework; -using GoogleTestAdapter.TestAdapter.Framework; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using System; using System.Collections.Generic; using System.ServiceModel; -using GoogleTestAdapter.ProcessExecution.Contracts; using GoogleTestAdapter.TestAdapter.ProcessExecution; using static GoogleTestAdapter.Tests.Common.TestMetadata.TestCategories; @@ -38,7 +35,7 @@ public void Setup() public void DebuggerAttacherService_ReceivesMessage_AnswersImmediately() { MockDebuggerAttacher - .Setup(a => a.AttachDebugger(It.IsAny())) + .Setup(a => a.AttachDebugger(It.IsAny(), It.IsAny())) .Returns(MessageBasedDebuggerAttacherTests.GetAttachDebuggerAction(() => true)); DoTest(null); } @@ -48,7 +45,7 @@ public void DebuggerAttacherService_ReceivesMessage_AnswersImmediately() public void DebuggerAttacherService_AttacherThrows_AnswerIncludesExceptionMessage() { MockDebuggerAttacher - .Setup(a => a.AttachDebugger(It.IsAny())) + .Setup(a => a.AttachDebugger(It.IsAny(), It.IsAny())) .Returns(MessageBasedDebuggerAttacherTests.GetAttachDebuggerAction(() => { throw new Exception("my message"); })); DoTest("my message"); } @@ -58,7 +55,7 @@ public void DebuggerAttacherService_AttacherThrows_AnswerIncludesExceptionMessag public void DebuggerAttacherService_AttacherReturnsFalse_AnswerWithoutReason() { MockDebuggerAttacher - .Setup(a => a.AttachDebugger(It.IsAny())) + .Setup(a => a.AttachDebugger(It.IsAny(), It.IsAny())) .Returns(MessageBasedDebuggerAttacherTests.GetAttachDebuggerAction(() => false)); DoTest("unknown reasons"); } @@ -80,7 +77,7 @@ private void DoTest(string expectedErrorMessagePart) client.Should().NotBeNull(); client.Service.Should().NotBeNull(); - Action attaching = () => client.Service.AttachDebugger(debuggeeProcessId); + Action attaching = () => client.Service.AttachDebugger(debuggeeProcessId, DebuggerEngine.Native); if (expectedErrorMessagePart == null) { attaching.Should().NotThrow(); diff --git a/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/Debugging/MessageBasedDebuggerAttacherTests.cs b/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/Debugging/MessageBasedDebuggerAttacherTests.cs index 67b270696..25b330a2c 100644 --- a/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/Debugging/MessageBasedDebuggerAttacherTests.cs +++ b/GoogleTestAdapter/VsPackage.GTA.Tests.Unit/Debugging/MessageBasedDebuggerAttacherTests.cs @@ -2,15 +2,12 @@ using FluentAssertions; using GoogleTestAdapter.Common; -using GoogleTestAdapter.Framework; -using GoogleTestAdapter.TestAdapter.Framework; using GoogleTestAdapter.Tests.Common; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using System; using System.ServiceModel; using System.Threading; -using GoogleTestAdapter.ProcessExecution.Contracts; using GoogleTestAdapter.TestAdapter.ProcessExecution; using static GoogleTestAdapter.Tests.Common.TestMetadata.TestCategories; @@ -37,7 +34,7 @@ public void Setup() public void AttachDebugger_AttachingSucceeds_DebugOutputGenerated() { MockDebuggerAttacher - .Setup(a => a.AttachDebugger(It.IsAny())) + .Setup(a => a.AttachDebugger(It.IsAny(), It.IsAny())) .Returns(GetAttachDebuggerAction(() => true)); DoTest(true); @@ -51,7 +48,7 @@ public void AttachDebugger_AttachingSucceeds_DebugOutputGenerated() public void AttachDebugger_AttachingFails_ErrorOutputGenerated() { MockDebuggerAttacher - .Setup(a => a.AttachDebugger(It.IsAny())) + .Setup(a => a.AttachDebugger(It.IsAny(), It.IsAny())) .Returns(GetAttachDebuggerAction(() => false)); DoTest(false); @@ -64,7 +61,7 @@ public void AttachDebugger_AttachingFails_ErrorOutputGenerated() public void AttachDebugger_AttachingThrows_ErrorOutputGenerated() { MockDebuggerAttacher - .Setup(a => a.AttachDebugger(It.IsAny())) + .Setup(a => a.AttachDebugger(It.IsAny(), It.IsAny())) .Returns(GetAttachDebuggerAction(() => { throw new Exception("my message"); })); DoTest(false); @@ -77,7 +74,7 @@ public void AttachDebugger_AttachingThrows_ErrorOutputGenerated() public void AttachDebugger_NoPipeAvailable_ErrorOutputGenerated() { var client = new MessageBasedDebuggerAttacher(Guid.NewGuid().ToString(), Timeout, MockLogger.Object); - client.AttachDebugger(2017).Should().BeFalse(); + client.AttachDebugger(2017, DebuggerEngine.Native).Should().BeFalse(); MockLogger.Verify(l => l.LogError(It.Is(s => s.Contains("EndpointNotFoundException"))), Times.Once); } @@ -95,9 +92,9 @@ private void DoTest(bool expectedResult) var client = new MessageBasedDebuggerAttacher(pipeId, Timeout, MockLogger.Object); - client.AttachDebugger(debuggeeProcessId).Should().Be(expectedResult); + client.AttachDebugger(debuggeeProcessId, DebuggerEngine.Native).Should().Be(expectedResult); - MockDebuggerAttacher.Verify(a => a.AttachDebugger(It.Is(processId => processId == debuggeeProcessId)), + MockDebuggerAttacher.Verify(a => a.AttachDebugger(It.Is(processId => processId == debuggeeProcessId), It.IsAny()), Times.Once); host.Close(); diff --git a/GoogleTestAdapter/VsPackage.Shared/Debugging/DebuggerAttacherService.cs b/GoogleTestAdapter/VsPackage.Shared/Debugging/DebuggerAttacherService.cs index 113783e80..247144175 100644 --- a/GoogleTestAdapter/VsPackage.Shared/Debugging/DebuggerAttacherService.cs +++ b/GoogleTestAdapter/VsPackage.Shared/Debugging/DebuggerAttacherService.cs @@ -2,9 +2,7 @@ using System; using GoogleTestAdapter.Common; -using GoogleTestAdapter.Framework; using System.ServiceModel; -using GoogleTestAdapter.ProcessExecution.Contracts; using GoogleTestAdapter.TestAdapter.ProcessExecution; namespace GoogleTestAdapter.VsPackage.Debugging @@ -24,12 +22,12 @@ public DebuggerAttacherService(IDebuggerAttacher debuggerAttacher, ILogger logge _logger = logger; } - public void AttachDebugger(int processId) + public void AttachDebugger(int processId, DebuggerEngine debuggerEngine) { bool success = false; try { - success = _debuggerAttacher.AttachDebugger(processId); + success = _debuggerAttacher.AttachDebugger(processId, debuggerEngine); } catch (Exception e) { @@ -43,6 +41,7 @@ public void AttachDebugger(int processId) private void ThrowFaultException(string message) { + _logger.LogError(message); throw new FaultException(new DebuggerAttacherServiceFault(message)); } } diff --git a/GoogleTestAdapter/VsPackage.Shared/Debugging/VsDebuggerAttacher.cs b/GoogleTestAdapter/VsPackage.Shared/Debugging/VsDebuggerAttacher.cs index ec2166028..4f05c5bbb 100644 --- a/GoogleTestAdapter/VsPackage.Shared/Debugging/VsDebuggerAttacher.cs +++ b/GoogleTestAdapter/VsPackage.Shared/Debugging/VsDebuggerAttacher.cs @@ -1,8 +1,7 @@ using System; using System.Reflection; using System.Runtime.InteropServices; -using GoogleTestAdapter.Framework; -using GoogleTestAdapter.ProcessExecution.Contracts; +using GoogleTestAdapter.Common; using GoogleTestAdapter.TestAdapter.ProcessExecution; using Microsoft.VisualStudio; using Microsoft.VisualStudio.Shell.Interop; @@ -27,12 +26,15 @@ internal VsDebuggerAttacher(IServiceProvider serviceProvider) _serviceProvider = serviceProvider; } - public bool AttachDebugger(int processId) + public bool AttachDebugger(int processId, DebuggerEngine debuggerEngine) { IntPtr pDebugEngine = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(Guid))); try { - Marshal.StructureToPtr(VSConstants.DebugEnginesGuids.NativeOnly_guid, pDebugEngine, false); + Guid debuggerEngineGuid = debuggerEngine == DebuggerEngine.Native + ? VSConstants.DebugEnginesGuids.NativeOnly_guid + : VSConstants.DebugEnginesGuids.ManagedAndNative; + Marshal.StructureToPtr(debuggerEngineGuid, pDebugEngine, false); var debugTarget = new VsDebugTargetInfo4 { From edfd26a1aac529fc33d13819e23adb8a05683a11 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sat, 6 Apr 2019 15:08:26 +0200 Subject: [PATCH 63/81] introduced new option for debugger kind, deprecated old option --- .../Core.Tests/GoogleTestDiscovererTests.cs | 2 +- .../GoogleTestDiscovererTraitTestsBase.cs | 4 ++-- .../Core.Tests/Settings/SettingsWrapperTests.cs | 2 +- .../Core.Tests/TestCases/TestCaseFactoryTests.cs | 5 +++-- .../TestResults/ExitCodeTestsReporterTests.cs | 8 ++++---- .../Core/Runners/SequentialTestRunner.cs | 10 +++++----- .../Core/Settings/IGoogleTestAdapterSettings.cs | 3 +++ GoogleTestAdapter/Core/Settings/RunSettings.cs | 3 +++ .../Core/Settings/SettingsWrapper.cs | 14 ++++++++------ .../Core/TestResults/ExitCodeTestsReporter.cs | 4 ++-- .../Core/TestResults/XmlTestResultParser.cs | 2 +- .../TestAdapter.Tests/CommonFunctionsTests.cs | 11 +++++++++++ ...tExecutorSequentialTests_FrameworkDebugging.cs | 5 +++-- ...TestExecutorSequentialTests_NativeDebugging.cs | 3 ++- .../TestAdapter.Tests/TestExecutorTestsBase.cs | 12 ++++++------ GoogleTestAdapter/TestAdapter/CommonFunctions.cs | 14 +++++++++++--- .../TestAdapter/GoogleTestAdapterSettings.xsd | 15 ++++++++++++--- .../FrameworkDebuggedProcessExecutor.cs | 4 ++-- .../NativeDebuggedProcessExecutor.cs | 2 +- GoogleTestAdapter/Tests.Common/TestsBase.cs | 2 +- .../Debugging/DebuggerAttacherService.cs | 1 - .../GoogleTestExtensionOptionsPage.cs | 2 +- .../OptionsPages/OptionsUpdater.cs | 2 +- .../TestExecutionOptionsDialogPage.cs | 12 ++++++------ 24 files changed, 90 insertions(+), 52 deletions(-) diff --git a/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTests.cs b/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTests.cs index b04fcc68e..75a978889 100644 --- a/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTests.cs +++ b/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTests.cs @@ -413,7 +413,7 @@ public void GetTestsFromExecutable_OldExecutionEnvironment_LoadTests_AreFoundInR Assert.Inconclusive("Skipping test since it is unstable on the build server"); } - MockOptions.Setup(o => o.UseNewTestExecutionFramework).Returns(false); + MockOptions.Setup(o => o.DebuggerKind).Returns(DebuggerKind.VsTestFramework); var stopwatch = Stopwatch.StartNew(); var discoverer = new GoogleTestDiscoverer(TestEnvironment.Logger, TestEnvironment.Options); diff --git a/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTraitTestsBase.cs b/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTraitTestsBase.cs index dd0e1a114..343b474cf 100644 --- a/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTraitTestsBase.cs +++ b/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTraitTestsBase.cs @@ -344,7 +344,7 @@ public virtual void GetTestsFromExecutable_RegexButNoSourceLocation_TraitsAreAdd [TestCategory(Integration)] public virtual void GetTestsFromExecutable_NewExecutionEnvironmentAndFailUserParamIsSet_NoTestsAreFound() { - MockOptions.Setup(o => o.UseNewTestExecutionFramework).Returns(true); + MockOptions.Setup(o => o.DebuggerKind).Returns(DebuggerKind.Native); CheckEffectOfDiscoveryParam(); } @@ -353,7 +353,7 @@ public virtual void GetTestsFromExecutable_NewExecutionEnvironmentAndFailUserPar [TestCategory(Integration)] public virtual void GetTestsFromExecutable_OldExecutionEnvironmentAndFailUserParamIsSet_NoTestsAreFound() { - MockOptions.Setup(o => o.UseNewTestExecutionFramework).Returns(false); + MockOptions.Setup(o => o.DebuggerKind).Returns(DebuggerKind.VsTestFramework); CheckEffectOfDiscoveryParam(); } diff --git a/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs b/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs index 5e30e477e..229f474c8 100644 --- a/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs +++ b/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs @@ -512,7 +512,7 @@ public void ToString_PrintsCorrectly() MockXmlOptions.Setup(s => s.MaxNrOfThreads).Returns(1); string optionsString = TheOptions.ToString(); - optionsString.Should().Contain("UseNewTestExecutionFramework: True"); + optionsString.Should().Contain("DebuggerKind: Native"); optionsString.Should().Contain("PrintTestOutput: False"); optionsString.Should().Contain("TestDiscoveryRegex: ''"); optionsString.Should().Contain("WorkingDir: '$(ExecutableDir)'"); diff --git a/GoogleTestAdapter/Core.Tests/TestCases/TestCaseFactoryTests.cs b/GoogleTestAdapter/Core.Tests/TestCases/TestCaseFactoryTests.cs index 876feb186..fa7eda842 100644 --- a/GoogleTestAdapter/Core.Tests/TestCases/TestCaseFactoryTests.cs +++ b/GoogleTestAdapter/Core.Tests/TestCases/TestCaseFactoryTests.cs @@ -8,6 +8,7 @@ using GoogleTestAdapter.Model; using GoogleTestAdapter.ProcessExecution; using GoogleTestAdapter.ProcessExecution.Contracts; +using GoogleTestAdapter.Settings; using GoogleTestAdapter.Tests.Common; using GoogleTestAdapter.Tests.Common.Assertions; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -47,7 +48,7 @@ public void CreateTestCases_DiscoveryTimeoutIsExceeded_DiscoveryIsCanceledAndCan [TestCategory(Unit)] public void CreateTestCases_OldExeDiscoveryTimeoutIsExceeded_DiscoveryIsCanceledAndCancellationIsLogged() { - MockOptions.Setup(o => o.UseNewTestExecutionFramework).Returns(false); + MockOptions.Setup(o => o.DebuggerKind).Returns(DebuggerKind.VsTestFramework); CreateTestCases_DiscoveryTimeoutIsExceeded_DiscoveryIsCanceledAndCancellationIsLogged(); } @@ -55,7 +56,7 @@ public void CreateTestCases_OldExeDiscoveryTimeoutIsExceeded_DiscoveryIsCanceled [TestCategory(Integration)] public void CreateTestCases_OldExeWithAdditionalPdb_TestCasesAreFound() { - MockOptions.Setup(o => o.UseNewTestExecutionFramework).Returns(false); + MockOptions.Setup(o => o.DebuggerKind).Returns(DebuggerKind.VsTestFramework); CheckIfSourceLocationsAreFound(); } diff --git a/GoogleTestAdapter/Core.Tests/TestResults/ExitCodeTestsReporterTests.cs b/GoogleTestAdapter/Core.Tests/TestResults/ExitCodeTestsReporterTests.cs index dd6f29e27..b40d0f19d 100644 --- a/GoogleTestAdapter/Core.Tests/TestResults/ExitCodeTestsReporterTests.cs +++ b/GoogleTestAdapter/Core.Tests/TestResults/ExitCodeTestsReporterTests.cs @@ -154,7 +154,7 @@ public void ReportExitCodeTestCases_FailAndSkip_CorrectResult() [TestCategory(Unit)] public void ReportExitCodeTestCases_PassButNoOutput_WarningIsLogged() { - MockOptions.Setup(o => o.UseNewTestExecutionFramework).Returns(false); + MockOptions.Setup(o => o.DebuggerKind).Returns(DebuggerKind.VsTestFramework); _mockAggregator.Setup(a => a.ComputeAggregatedResults(It.IsAny>())).Returns( new List { @@ -163,14 +163,14 @@ public void ReportExitCodeTestCases_PassButNoOutput_WarningIsLogged() _reporter.ReportExitCodeTestCases(null, true); - MockLogger.Verify(l => l.LogWarning(It.Is(msg => msg.Contains("collected") && msg.Contains(SettingsWrapper.OptionUseNewTestExecutionFramework))), Times.Once); + MockLogger.Verify(l => l.LogWarning(It.Is(msg => msg.Contains("collected") && msg.Contains(SettingsWrapper.OptionDebuggerKind))), Times.Once); } [TestMethod] [TestCategory(Unit)] public void ReportExitCodeTestCases_FailButNoOutput_WarningIsLogged() { - MockOptions.Setup(o => o.UseNewTestExecutionFramework).Returns(false); + MockOptions.Setup(o => o.DebuggerKind).Returns(DebuggerKind.VsTestFramework); _mockAggregator.Setup(a => a.ComputeAggregatedResults(It.IsAny>())).Returns( new List { @@ -179,7 +179,7 @@ public void ReportExitCodeTestCases_FailButNoOutput_WarningIsLogged() _reporter.ReportExitCodeTestCases(null, true); - MockLogger.Verify(l => l.LogWarning(It.Is(msg => msg.Contains("collected") && msg.Contains(SettingsWrapper.OptionUseNewTestExecutionFramework))), Times.Once); + MockLogger.Verify(l => l.LogWarning(It.Is(msg => msg.Contains("collected") && msg.Contains(SettingsWrapper.OptionDebuggerKind))), Times.Once); } private static bool CheckResult(TestResult result, string executable, TestOutcome outcome, params string[] errorMessageParts) diff --git a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs index d30fbd8c4..4c9c1a97f 100644 --- a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs @@ -171,7 +171,7 @@ private List RunTestExecutable(string executable, string workingDir, Com StreamingStandardOutputTestResultParser streamingParser) { string pathExtension = _settings.GetPathExtension(executable); - bool isTestOutputAvailable = !isBeingDebugged || _settings.UseNewTestExecutionFramework; + bool isTestOutputAvailable = !isBeingDebugged || _settings.DebuggerKind > DebuggerKind.VsTestFramework; bool printTestOutput = _settings.PrintTestOutput && !_settings.ParallelTestExecution && isTestOutputAvailable; @@ -190,11 +190,11 @@ void OnNewOutputLine(string line) } _processExecutor = isBeingDebugged - ? _settings.UseNewTestExecutionFramework - ? processExecutorFactory.CreateNativeDebuggingExecutor( - DebuggerEngine.Native, + ? _settings.DebuggerKind == DebuggerKind.VsTestFramework + ? processExecutorFactory.CreateFrameworkDebuggingExecutor(printTestOutput, _logger) + : processExecutorFactory.CreateNativeDebuggingExecutor( + _settings.DebuggerKind == DebuggerKind.Native ? DebuggerEngine.Native : DebuggerEngine.ManagedAndNative, printTestOutput, _logger) - : processExecutorFactory.CreateFrameworkDebuggingExecutor(printTestOutput, _logger) : processExecutorFactory.CreateExecutor(printTestOutput, _logger); int exitCode = _processExecutor.ExecuteCommandBlocking( executable, arguments.CommandLine, workingDir, pathExtension, diff --git a/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs b/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs index 5bdfcbe03..93123d307 100644 --- a/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs +++ b/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs @@ -4,6 +4,7 @@ namespace GoogleTestAdapter.Settings { + public enum DebuggerKind { VsTestFramework, Native, ManagedAndNative } /* To add a new option, make the following changes: @@ -51,6 +52,7 @@ public interface IGoogleTestAdapterSettings string ExitCodeTestCase { get; set; } bool? UseNewTestExecutionFramework { get; set; } + DebuggerKind? DebuggerKind { get; set; } // internal string DebuggingNamedPipeId { get; set; } @@ -93,6 +95,7 @@ public static void GetUnsetValuesFrom(this IGoogleTestAdapterSettings self, IGoo self.ExitCodeTestCase = self.ExitCodeTestCase ?? other.ExitCodeTestCase; self.UseNewTestExecutionFramework = self.UseNewTestExecutionFramework ?? other.UseNewTestExecutionFramework; + self.DebuggerKind = self.DebuggerKind ?? other.DebuggerKind; self.DebuggingNamedPipeId = self.DebuggingNamedPipeId ?? other.DebuggingNamedPipeId; self.SolutionDir = self.SolutionDir ?? other.SolutionDir; diff --git a/GoogleTestAdapter/Core/Settings/RunSettings.cs b/GoogleTestAdapter/Core/Settings/RunSettings.cs index 294295f85..3403553d2 100644 --- a/GoogleTestAdapter/Core/Settings/RunSettings.cs +++ b/GoogleTestAdapter/Core/Settings/RunSettings.cs @@ -106,6 +106,9 @@ public RunSettings(string projectRegex) public virtual bool? UseNewTestExecutionFramework { get; set; } public bool ShouldSerializeUseNewTestExecutionFramework() { return UseNewTestExecutionFramework != null; } + public virtual DebuggerKind? DebuggerKind { get; set; } + public bool ShouldSerializeDebuggerKind() { return DebuggerKind != null; } + // internal public virtual string DebuggingNamedPipeId { get; set; } diff --git a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs index 0940e5c09..f6312bb5d 100644 --- a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs +++ b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs @@ -271,12 +271,14 @@ public virtual int ShuffleTestsSeed #region TestExecutionOptionsPage - public const string OptionUseNewTestExecutionFramework = "Use native debugging"; - public const string OptionUseNewTestExecutionFrameworkDescription = - "Make use of native debugging (in contrast to debugging provided by the VsTest framework). Advantages: test crash detection and test output printing also work in debug mode."; - public const bool OptionUseNewTestExecutionFrameworkDefaultValue = true; - - public virtual bool UseNewTestExecutionFramework => _currentSettings.UseNewTestExecutionFramework ?? OptionUseNewTestExecutionFrameworkDefaultValue; + public const string OptionDebuggerKind = "Debugger engine"; + public const string OptionDebuggerKindDescription = + "Framework: Debugger engine as provided by VsTest framework; no test crash detection, no test output printing, less interactive UI\n" + + "Native: Debugger engine as provided by VS native API; no restrictions (default)\n" + + "ManagedAndNative: Same as Native, but allows to also debug into managed code"; + public const DebuggerKind OptionDebuggerKindDefaultValue = DebuggerKind.Native; + + public virtual DebuggerKind DebuggerKind => _currentSettings.DebuggerKind ?? OptionDebuggerKindDefaultValue; public const string OptionAdditionalPdbs = "Additional PDBs"; diff --git a/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs b/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs index e356826a7..25af220b4 100644 --- a/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs +++ b/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs @@ -50,7 +50,7 @@ public void ReportExitCodeTestCases(IEnumerable allResults, bo if (!string.IsNullOrWhiteSpace(_settings.ExitCodeTestCase)) { var testResult = ReportExitCodeTestResult(executableResult); - printWarning |= isBeingDebugged && !_settings.UseNewTestExecutionFramework; + printWarning |= isBeingDebugged && _settings.DebuggerKind == DebuggerKind.VsTestFramework; _logger.DebugInfo($"Reported exit code test {testResult.DisplayName} for executable {executableResult.Executable}"); } }); @@ -59,7 +59,7 @@ public void ReportExitCodeTestCases(IEnumerable allResults, bo if (printWarning) { _logger.LogWarning( - $"Result code output can not be collected while debugging if option '{SettingsWrapper.OptionUseNewTestExecutionFramework}' is false"); + $"Result code output can not be collected while debugging if option '{SettingsWrapper.OptionDebuggerKind}' is {DebuggerKind.VsTestFramework}"); } } diff --git a/GoogleTestAdapter/Core/TestResults/XmlTestResultParser.cs b/GoogleTestAdapter/Core/TestResults/XmlTestResultParser.cs index fc5c150b1..638f50afe 100644 --- a/GoogleTestAdapter/Core/TestResults/XmlTestResultParser.cs +++ b/GoogleTestAdapter/Core/TestResults/XmlTestResultParser.cs @@ -71,7 +71,7 @@ private IDictionary CreateWorkaroundMap() string message = $"Executable {_testExecutable} has test names containing characters which happen to not end up in the XML file produced by Google Test. " + "This has caused ambiguities while resolving the according test results, which are thus not available. " + - $"Note that this problem does not occur if GTA option '{SettingsWrapper.OptionUseNewTestExecutionFramework}' is enabled." + + $"Note that this problem can only occur if GTA option '{SettingsWrapper.OptionDebuggerKind}' is {DebuggerKind.VsTestFramework}." + $"\nThe following tests are affected: {string.Join(", ", duplicateTestCases.Select(tc => tc.FullyQualifiedName).OrderBy(n => n))}"; _logger.LogWarning(message); } diff --git a/GoogleTestAdapter/TestAdapter.Tests/CommonFunctionsTests.cs b/GoogleTestAdapter/TestAdapter.Tests/CommonFunctionsTests.cs index f5d33e491..2732d4597 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/CommonFunctionsTests.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/CommonFunctionsTests.cs @@ -166,6 +166,17 @@ public void CreateEnvironment_DeprecatedSettingDebugMode_WarningIsLogged() It.Is(s => s.Contains(nameof(RunSettings.DebugMode)))))); } + [TestMethod] + [TestCategory(Unit)] + public void CreateEnvironment_DeprecatedSettingUseNewTestExecutionFramework_WarningIsLogged() + { + SetupRunSettingsAndCheckAssertions( + mockRunSettings => mockRunSettings.Setup(s => s.UseNewTestExecutionFramework).Returns(true), + () => _mockMessageLogger.Verify(l => l.SendMessage( + It.Is(level => level == TestMessageLevel.Warning), + It.Is(s => s.Contains(nameof(RunSettings.UseNewTestExecutionFramework)))))); + } + [TestMethod] [TestCategory(Unit)] public void CreateEnvironment_DeprecatedSettingShowReleaseNotes_WarningIsLogged() diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs index 191098098..b101387a0 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Diagnostics; using GoogleTestAdapter.Helpers; +using GoogleTestAdapter.Settings; using GoogleTestAdapter.Tests.Common; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -17,7 +18,7 @@ public class TestExecutorSequentialTests_FrameworkDebugging : TestExecutorSequen public override void SetUp() { base.SetUp(); - MockOptions.Setup(o => o.UseNewTestExecutionFramework).Returns(false); + MockOptions.Setup(o => o.DebuggerKind).Returns(DebuggerKind.VsTestFramework); MockRunContext.Setup(c => c.IsBeingDebugged).Returns(true); SetUpMockFrameworkHandle(); @@ -210,7 +211,7 @@ public override void RunTests_ExitCodeTest_FailingTestResultIsProduced() [TestCategory(Integration)] public override void MemoryLeakTests_FailingWithLeaks_CorrectResult() { - bool outputAvailable = MockOptions.Object.UseNewTestExecutionFramework || + bool outputAvailable = MockOptions.Object.DebuggerKind > DebuggerKind.VsTestFramework || !MockRunContext.Object.IsBeingDebugged; RunMemoryLeakTest(TestResources.LeakCheckTests_DebugX86, "memory_leaks.failing_and_leaking", VsTestOutcome.Failed, VsTestOutcome.Failed, msg => msg.Contains("Exit code: 1") diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_NativeDebugging.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_NativeDebugging.cs index 0f5bd8330..023d95e6c 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_NativeDebugging.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_NativeDebugging.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Diagnostics; using GoogleTestAdapter.Helpers; +using GoogleTestAdapter.Settings; using GoogleTestAdapter.Tests.Common; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -15,7 +16,7 @@ public class TestExecutorSequentialTests_NativeDebugging : TestExecutorSequentia public override void SetUp() { base.SetUp(); - MockOptions.Setup(o => o.UseNewTestExecutionFramework).Returns(true); + MockOptions.Setup(o => o.DebuggerKind).Returns(DebuggerKind.Native); MockRunContext.Setup(c => c.IsBeingDebugged).Returns(true); SetUpMockFrameworkHandle(); diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs index b366747e3..61779946b 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs @@ -172,7 +172,7 @@ public virtual void RunTests_StaticallyLinkedX64Tests_OutputIsPrintedAtMostOnce( bool isTestOutputAvailable = !MockOptions.Object.ParallelTestExecution && - (MockOptions.Object.UseNewTestExecutionFramework || !MockRunContext.Object.IsBeingDebugged); + (MockOptions.Object.DebuggerKind > DebuggerKind.VsTestFramework || !MockRunContext.Object.IsBeingDebugged); int nrOfExpectedLines = isTestOutputAvailable ? 1 : 0; MockLogger.Verify(l => l.LogInfo(It.Is(line => line == "[----------] Global test environment set-up.")), Times.Exactly(nrOfExpectedLines)); @@ -326,7 +326,7 @@ protected void RunAndVerifyTests(string executable, int nrOfPassedTests, int nrO [TestCategory(Integration)] public virtual void MemoryLeakTests_PassingWithLeaks_CorrectResult() { - bool outputAvailable = MockOptions.Object.UseNewTestExecutionFramework || + bool outputAvailable = MockOptions.Object.DebuggerKind > DebuggerKind.VsTestFramework || !MockRunContext.Object.IsBeingDebugged; RunMemoryLeakTest(TestResources.LeakCheckTests_DebugX86, "memory_leaks.passing_and_leaking", VsTestOutcome.Passed, VsTestOutcome.Failed, msg => msg.Contains("Exit code: 1") @@ -337,7 +337,7 @@ public virtual void MemoryLeakTests_PassingWithLeaks_CorrectResult() [TestCategory(Integration)] public virtual void MemoryLeakTests_FailingWithLeaks_CorrectResult() { - bool outputAvailable = MockOptions.Object.UseNewTestExecutionFramework || + bool outputAvailable = MockOptions.Object.DebuggerKind > DebuggerKind.VsTestFramework || !MockRunContext.Object.IsBeingDebugged; RunMemoryLeakTest(TestResources.LeakCheckTests_DebugX86, "memory_leaks.failing_and_leaking", VsTestOutcome.Failed, VsTestOutcome.Skipped, msg => msg.Contains("Exit code: 1") @@ -398,7 +398,7 @@ public virtual void MemoryLeakTests_FailingWithoutLeaks_CorrectResult() [TestCategory(Integration)] public virtual void MemoryLeakTests_PassingWithoutLeaksRelease_CorrectResult() { - bool outputAvailable = MockOptions.Object.UseNewTestExecutionFramework || + bool outputAvailable = MockOptions.Object.DebuggerKind > DebuggerKind.VsTestFramework || !MockRunContext.Object.IsBeingDebugged; RunMemoryLeakTest(TestResources.LeakCheckTests_ReleaseX86, "memory_leaks.passing_and_leaking", VsTestOutcome.Passed, outputAvailable ? VsTestOutcome.Skipped : VsTestOutcome.Passed, @@ -460,7 +460,7 @@ private void RunExitCodeTest(string testCaseName, VsTestOutcome outcome) // ReSharper disable once PossibleNullReferenceException string finalName = exitCodeTestName + "." + Path.GetFileName(testCase.Source).Replace(".", "_"); - bool outputAvailable = MockOptions.Object.UseNewTestExecutionFramework || + bool outputAvailable = MockOptions.Object.DebuggerKind > DebuggerKind.VsTestFramework || !MockRunContext.Object.IsBeingDebugged; Func errorMessagePredicate = outcome == VsTestOutcome.Failed ? result => result.ErrorMessage.Contains("Exit code: 1") @@ -481,7 +481,7 @@ private void RunExitCodeTest(string testCaseName, VsTestOutcome outcome) if (!outputAvailable && outcome == VsTestOutcome.Failed) { MockLogger.Verify(l => l.LogWarning(It.Is(msg => msg.Contains("Result code") - && msg.Contains(SettingsWrapper.OptionUseNewTestExecutionFramework))), Times.Once); + && msg.Contains(SettingsWrapper.OptionDebuggerKind))), Times.Once); } MockLogger.Verify(l => l.DebugWarning(It.Is(msg => msg.Contains("main method") && msg.Contains("exit code"))), Times.Never); diff --git a/GoogleTestAdapter/TestAdapter/CommonFunctions.cs b/GoogleTestAdapter/TestAdapter/CommonFunctions.cs index 4cbef3c50..59eb1df62 100644 --- a/GoogleTestAdapter/TestAdapter/CommonFunctions.cs +++ b/GoogleTestAdapter/TestAdapter/CommonFunctions.cs @@ -156,9 +156,17 @@ private static void LogWarningsForDeprecatedSettings(RunSettingsContainer runSet var debugModeProperty = typeof(RunSettings).GetProperty(nameof(RunSettings.DebugMode)); if (HasSetting(runSettingsContainer, debugModeProperty)) { - logger.LogWarning($"GTA option '{nameof(IGoogleTestAdapterSettings.DebugMode)}' is deprecated and will be ignored - check your settings files and replace any occurence with new option '{nameof(IGoogleTestAdapterSettings.OutputMode)}' as follows:"); - logger.LogWarning("False => Info"); - logger.LogWarning("True => Verbose (consider using Debug)"); + logger.LogWarning($"GTA option '{nameof(IGoogleTestAdapterSettings.DebugMode)}' does not have any effect any more - check your settings files and replace any occurence with new option '{nameof(IGoogleTestAdapterSettings.OutputMode)}' as follows:"); + logger.LogWarning($"False => {OutputMode.Info}"); + logger.LogWarning($"True => {OutputMode.Verbose} (consider using {OutputMode.Debug})"); + } + + var useNewTestExecutionEnvironmentProperty = typeof(RunSettings).GetProperty(nameof(RunSettings.UseNewTestExecutionFramework)); + if (HasSetting(runSettingsContainer, useNewTestExecutionEnvironmentProperty)) + { + logger.LogWarning($"GTA option '{nameof(IGoogleTestAdapterSettings.UseNewTestExecutionFramework)}' does not have any effect any more - check your settings files and replace any occurence with new option '{nameof(IGoogleTestAdapterSettings.DebuggerKind)}' as follows:"); + logger.LogWarning($"False => {DebuggerKind.VsTestFramework}"); + logger.LogWarning($"True => {DebuggerKind.Native}"); } var showReleaseNotesProperty = typeof(RunSettings).GetProperty(nameof(RunSettings.ShowReleaseNotes)); diff --git a/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd b/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd index 7f60f63c1..9f788952a 100644 --- a/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd +++ b/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd @@ -91,9 +91,18 @@ - - Corresponds to option 'Use native debugging' - + + Corresponds to option 'Use native debugging' + + + + + + + + + + diff --git a/GoogleTestAdapter/TestAdapter/ProcessExecution/FrameworkDebuggedProcessExecutor.cs b/GoogleTestAdapter/TestAdapter/ProcessExecution/FrameworkDebuggedProcessExecutor.cs index 0fee516bd..f744fe1bc 100644 --- a/GoogleTestAdapter/TestAdapter/ProcessExecution/FrameworkDebuggedProcessExecutor.cs +++ b/GoogleTestAdapter/TestAdapter/ProcessExecution/FrameworkDebuggedProcessExecutor.cs @@ -40,11 +40,11 @@ public int ExecuteCommandBlocking(string command, string parameters, string work if (!string.IsNullOrEmpty(pathExtension)) envVariables["PATH"] = Utils.GetExtendedPath(pathExtension); - _logger.DebugInfo($"Attaching debugger to '{command}' via VsTest framework API"); + _logger.DebugInfo($"Attaching debugger to '{command}' via {DebuggerKind.VsTestFramework} engine"); if (_printTestOutput) { _logger.DebugInfo( - $"Note that due to restrictions of the VsTest framework, the test executable's output can not be displayed in the test console when debugging tests. Use '{SettingsWrapper.OptionUseNewTestExecutionFramework}' option to overcome this problem.'"); + $"Note that due to restrictions of the VsTest framework, the test executable's output can not be displayed in the test console when debugging tests. Use '{SettingsWrapper.OptionDebuggerKind}' option to overcome this problem.'"); } _processId = _frameworkHandle.LaunchProcessWithDebuggerAttached(command, workingDir, parameters, envVariables); diff --git a/GoogleTestAdapter/TestAdapter/ProcessExecution/NativeDebuggedProcessExecutor.cs b/GoogleTestAdapter/TestAdapter/ProcessExecution/NativeDebuggedProcessExecutor.cs index 3a244ecc9..f02934834 100644 --- a/GoogleTestAdapter/TestAdapter/ProcessExecution/NativeDebuggedProcessExecutor.cs +++ b/GoogleTestAdapter/TestAdapter/ProcessExecution/NativeDebuggedProcessExecutor.cs @@ -120,7 +120,7 @@ internal static int ExecuteCommandBlocking( { pipeStream.ConnectedToChildProcess(); - logger.DebugInfo($"Attaching debugger to '{command}' via native implementation"); + logger.DebugInfo($"Attaching debugger to '{command}' via {debuggerEngine} engine"); if (!debuggerAttacher.AttachDebugger(processInfo.dwProcessId, debuggerEngine)) { logger.LogError($"Could not attach debugger to process {processInfo.dwProcessId}"); diff --git a/GoogleTestAdapter/Tests.Common/TestsBase.cs b/GoogleTestAdapter/Tests.Common/TestsBase.cs index 706e45bc5..d46914343 100644 --- a/GoogleTestAdapter/Tests.Common/TestsBase.cs +++ b/GoogleTestAdapter/Tests.Common/TestsBase.cs @@ -93,7 +93,7 @@ public static void SetupOptions(Mock mockOptions) mockOptions.Setup(o => o.SkipOriginCheck).Returns(SettingsWrapper.OptionSkipOriginCheckDefaultValue); mockOptions.Setup(o => o.ExitCodeTestCase).Returns(SettingsWrapper.OptionExitCodeTestCaseDefaultValue); - mockOptions.Setup(o => o.UseNewTestExecutionFramework).Returns(true); + mockOptions.Setup(o => o.DebuggerKind).Returns(DebuggerKind.Native); mockOptions.Setup(o => o.DebuggingNamedPipeId).Returns(Guid.NewGuid().ToString()); mockOptions.Setup(o => o.SolutionDir).CallBase(); diff --git a/GoogleTestAdapter/VsPackage.Shared/Debugging/DebuggerAttacherService.cs b/GoogleTestAdapter/VsPackage.Shared/Debugging/DebuggerAttacherService.cs index 247144175..c10e0be2d 100644 --- a/GoogleTestAdapter/VsPackage.Shared/Debugging/DebuggerAttacherService.cs +++ b/GoogleTestAdapter/VsPackage.Shared/Debugging/DebuggerAttacherService.cs @@ -41,7 +41,6 @@ public void AttachDebugger(int processId, DebuggerEngine debuggerEngine) private void ThrowFaultException(string message) { - _logger.LogError(message); throw new FaultException(new DebuggerAttacherServiceFault(message)); } } diff --git a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs index 8779aed74..3db20b822 100644 --- a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs @@ -274,7 +274,7 @@ private RunSettings GetRunSettingsFromOptionPages() ExitCodeTestCase = _testExecutionOptions.ExitCodeTestCase, ParallelTestExecution = _testExecutionOptions.EnableParallelTestExecution, MaxNrOfThreads = _testExecutionOptions.MaxNrOfThreads, - UseNewTestExecutionFramework = _testExecutionOptions.UseNewTestExecutionFramework2, + DebuggerKind = _testExecutionOptions.DebuggerKind, DebuggingNamedPipeId = _debuggingNamedPipeId, SolutionDir = solutionDir, diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs index dc0e1be65..a8cf69526 100644 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs @@ -86,9 +86,9 @@ private void UpdateSettings() if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestExecutionOptionsDialogPage.ExitCodeTestCase), s => s, out var exitCodeTestCase)) { _testExecutionOptions.ExitCodeTestCase = exitCodeTestCase; } if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestExecutionOptionsDialogPage.PathExtension), s => s, out var pathExtension)) { _testExecutionOptions.PathExtension = pathExtension; } if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestExecutionOptionsDialogPage.KillProcessesOnCancel), bool.Parse, out var killProcessesOnCancel)) { _testExecutionOptions.KillProcessesOnCancel = killProcessesOnCancel; } - if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestExecutionOptionsDialogPage.UseNewTestExecutionFramework2), bool.Parse, out var useNewTestExecutionFramework2)) { _testExecutionOptions.UseNewTestExecutionFramework2 = useNewTestExecutionFramework2; } if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestExecutionOptionsDialogPage.WorkingDir), s => s, out var workingDir)) { _testExecutionOptions.WorkingDir = workingDir; } + if (GetAndDeleteValue(GeneralOptionsPage, "UseNewTestExecutionFramework2", bool.Parse, out var useNewTestExecutionFramework2)) { _testExecutionOptions.DebuggerKind = useNewTestExecutionFramework2 ? DebuggerKind.Native : DebuggerKind.Platform; } if (GetAndDeleteValue(GeneralOptionsPage, nameof(IGoogleTestAdapterSettings.DebugMode), bool.Parse, out var debugMode)) { _generalOptions.OutputMode = debugMode ? OutputMode.Debug : OutputMode.Info; } GetAndDeleteValue(GeneralOptionsPage, nameof(IGoogleTestAdapterSettings.ShowReleaseNotes), bool.Parse, out _); } diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestExecutionOptionsDialogPage.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestExecutionOptionsDialogPage.cs index e0353eb50..d9de88539 100644 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestExecutionOptionsDialogPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestExecutionOptionsDialogPage.cs @@ -140,14 +140,14 @@ public bool KillProcessesOnCancel private bool _killProcessesOnCancel = SettingsWrapper.OptionKillProcessesOnCancelDefaultValue; [Category(SettingsWrapper.CategoryMiscName)] - [DisplayName(SettingsWrapper.OptionUseNewTestExecutionFramework)] - [Description(SettingsWrapper.OptionUseNewTestExecutionFrameworkDescription)] - public bool UseNewTestExecutionFramework2 + [DisplayName(SettingsWrapper.OptionDebuggerKind)] + [Description(SettingsWrapper.OptionDebuggerKindDescription)] + public DebuggerKind DebuggerKind { - get => _useNewTestExecutionFramework; - set => SetAndNotify(ref _useNewTestExecutionFramework, value); + get => _debuggerKind; + set => SetAndNotify(ref _debuggerKind, value); } - private bool _useNewTestExecutionFramework = SettingsWrapper.OptionUseNewTestExecutionFrameworkDefaultValue; + private DebuggerKind _debuggerKind = SettingsWrapper.OptionDebuggerKindDefaultValue; [Category(SettingsWrapper.CategoryMiscName)] [DisplayName(SettingsWrapper.OptionExitCodeTestCase)] From 3d509a99c83881c0aad01cbff21cf70450d8ff49 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sat, 6 Apr 2019 19:29:14 +0200 Subject: [PATCH 64/81] added DebuggerKind converter --- .../Core.Tests/Core.Tests.csproj | 1 + .../GoogleTestDiscovererTraitTestsBase.cs | 3 + .../Runners/DebuggerKindConverterTests.cs | 41 +++++++++++ .../TestCases/TestCaseFactoryTests.cs | 1 - .../TestResults/ExitCodeTestsReporterTests.cs | 1 + GoogleTestAdapter/Core/Core.csproj | 2 + .../Core/ProcessExecution/DebuggerKind.cs | 73 +++++++++++++++++++ .../Core/Runners/ExecutableResult.cs | 26 +++++++ GoogleTestAdapter/Core/Runners/ITestRunner.cs | 25 +------ .../Core/Runners/PreparingTestRunner.cs | 1 - .../Core/Runners/SequentialTestRunner.cs | 1 + .../Settings/IGoogleTestAdapterSettings.cs | 3 +- .../Core/Settings/RunSettings.cs | 1 + .../Core/Settings/SettingsWrapper.cs | 1 + .../Core/TestResults/ExitCodeTestsReporter.cs | 3 +- .../Core/TestResults/XmlTestResultParser.cs | 3 +- ...cutorSequentialTests_FrameworkDebugging.cs | 2 +- ...ExecutorSequentialTests_NativeDebugging.cs | 3 +- .../TestAdapter/CommonFunctions.cs | 1 + .../FrameworkDebuggedProcessExecutor.cs | 1 + .../OptionsPages/OptionsUpdater.cs | 3 +- .../TestExecutionOptionsDialogPage.cs | 4 + 22 files changed, 166 insertions(+), 34 deletions(-) create mode 100644 GoogleTestAdapter/Core.Tests/Runners/DebuggerKindConverterTests.cs create mode 100644 GoogleTestAdapter/Core/ProcessExecution/DebuggerKind.cs create mode 100644 GoogleTestAdapter/Core/Runners/ExecutableResult.cs diff --git a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj index ab66af659..aae82d5f4 100644 --- a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj +++ b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj @@ -96,6 +96,7 @@ + diff --git a/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTraitTestsBase.cs b/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTraitTestsBase.cs index 343b474cf..29e395258 100644 --- a/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTraitTestsBase.cs +++ b/GoogleTestAdapter/Core.Tests/GoogleTestDiscovererTraitTestsBase.cs @@ -1,10 +1,12 @@ using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Text.RegularExpressions; using FluentAssertions; using GoogleTestAdapter.Helpers; using GoogleTestAdapter.Model; +using GoogleTestAdapter.ProcessExecution; using GoogleTestAdapter.Settings; using GoogleTestAdapter.Tests.Common; using GoogleTestAdapter.Tests.Common.Assertions; @@ -316,6 +318,7 @@ public virtual void GetTestsFromExecutable_RegexAfterFromOptions_AddsTraitIfNotA [TestMethod] [TestCategory(Integration)] + [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")] public virtual void GetTestsFromExecutable_RegexButNoSourceLocation_TraitsAreAdded() { string pdb = Path.ChangeExtension(SampleTestToUse, "pdb"); diff --git a/GoogleTestAdapter/Core.Tests/Runners/DebuggerKindConverterTests.cs b/GoogleTestAdapter/Core.Tests/Runners/DebuggerKindConverterTests.cs new file mode 100644 index 000000000..0eecc57bb --- /dev/null +++ b/GoogleTestAdapter/Core.Tests/Runners/DebuggerKindConverterTests.cs @@ -0,0 +1,41 @@ +using System.ComponentModel; +using FluentAssertions; +using GoogleTestAdapter.ProcessExecution; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using static GoogleTestAdapter.Tests.Common.TestMetadata.TestCategories; + +namespace GoogleTestAdapter.Runners +{ + [TestClass] + public class DebuggerKindConverterTests + { + [TestMethod] + [TestCategory(Unit)] + public void TypeDescriptor_DeliversCorrectType() + { + var converter = TypeDescriptor.GetConverter(typeof(DebuggerKind)); + converter.Should().BeOfType(); + } + + [TestMethod] + [TestCategory(Unit)] + public void ToReadableString_ReturnsCorrectStrings() + { + DebuggerKind.VsTestFramework.ToReadableString().Should().Be("VsTest framework"); + DebuggerKind.Native.ToReadableString().Should().Be("Native"); + DebuggerKind.ManagedAndNative.ToReadableString().Should().Be("Managed and native"); + } + + [TestMethod] + [TestCategory(Unit)] + public void ConvertFrom_ReturnsCorrectLiterals() + { + new DebuggerKindConverter().ConvertFrom("VsTest framework").Should().Be(DebuggerKind.VsTestFramework); + new DebuggerKindConverter().ConvertFrom("VsTestFramework").Should().Be(DebuggerKind.VsTestFramework); + new DebuggerKindConverter().ConvertFrom("Native").Should().Be(DebuggerKind.Native); + new DebuggerKindConverter().ConvertFrom("Managed and native").Should().Be(DebuggerKind.ManagedAndNative); + new DebuggerKindConverter().ConvertFrom("ManagedAndNative").Should().Be(DebuggerKind.ManagedAndNative); + } + + } +} \ No newline at end of file diff --git a/GoogleTestAdapter/Core.Tests/TestCases/TestCaseFactoryTests.cs b/GoogleTestAdapter/Core.Tests/TestCases/TestCaseFactoryTests.cs index fa7eda842..0d299d433 100644 --- a/GoogleTestAdapter/Core.Tests/TestCases/TestCaseFactoryTests.cs +++ b/GoogleTestAdapter/Core.Tests/TestCases/TestCaseFactoryTests.cs @@ -8,7 +8,6 @@ using GoogleTestAdapter.Model; using GoogleTestAdapter.ProcessExecution; using GoogleTestAdapter.ProcessExecution.Contracts; -using GoogleTestAdapter.Settings; using GoogleTestAdapter.Tests.Common; using GoogleTestAdapter.Tests.Common.Assertions; using Microsoft.VisualStudio.TestTools.UnitTesting; diff --git a/GoogleTestAdapter/Core.Tests/TestResults/ExitCodeTestsReporterTests.cs b/GoogleTestAdapter/Core.Tests/TestResults/ExitCodeTestsReporterTests.cs index b40d0f19d..1be5849a1 100644 --- a/GoogleTestAdapter/Core.Tests/TestResults/ExitCodeTestsReporterTests.cs +++ b/GoogleTestAdapter/Core.Tests/TestResults/ExitCodeTestsReporterTests.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using GoogleTestAdapter.Model; +using GoogleTestAdapter.ProcessExecution; using GoogleTestAdapter.Runners; using GoogleTestAdapter.Settings; using GoogleTestAdapter.Tests.Common; diff --git a/GoogleTestAdapter/Core/Core.csproj b/GoogleTestAdapter/Core/Core.csproj index 9da1a1442..16fd3ec6c 100644 --- a/GoogleTestAdapter/Core/Core.csproj +++ b/GoogleTestAdapter/Core/Core.csproj @@ -70,6 +70,8 @@ + + diff --git a/GoogleTestAdapter/Core/ProcessExecution/DebuggerKind.cs b/GoogleTestAdapter/Core/ProcessExecution/DebuggerKind.cs new file mode 100644 index 000000000..5a1df384f --- /dev/null +++ b/GoogleTestAdapter/Core/ProcessExecution/DebuggerKind.cs @@ -0,0 +1,73 @@ +using System; +using System.ComponentModel; +using System.Globalization; + +namespace GoogleTestAdapter.ProcessExecution +{ + [TypeConverter(typeof(DebuggerKindConverter))] + public enum DebuggerKind { VsTestFramework, Native, ManagedAndNative } + + public static class DebuggerKindExtensions + { + public static string ToReadableString(this DebuggerKind debuggerKind) + { + return TypeDescriptor.GetConverter(typeof(DebuggerKind)).ConvertToString(debuggerKind); + } + } + + public class DebuggerKindConverter : EnumConverter + { + private const string VsTestFramework = "VsTest framework"; + private const string Native = "Native"; + private const string ManagedAndNative = "Managed and native"; + + + public DebuggerKindConverter(Type enumType) : base(enumType) {} + + public DebuggerKindConverter() : this(typeof(DebuggerKind)) {} + + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + { + return destinationType == typeof(string) || + base.CanConvertTo(context, destinationType); + } + + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + return sourceType == typeof(DebuggerKind) || + base.CanConvertFrom(context, sourceType); + } + + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + if (!(value is DebuggerKind debuggerKind) || destinationType != typeof(string)) + return base.ConvertTo(context, culture, value, destinationType); + + switch (debuggerKind) + { + case DebuggerKind.VsTestFramework: return VsTestFramework; + case DebuggerKind.Native: return Native; + case DebuggerKind.ManagedAndNative: return ManagedAndNative; + default: + return base.ConvertTo(context, culture, value, destinationType); + } + } + + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + if (!(value is string valueString)) + return base.ConvertFrom(context, culture, value); + + switch (valueString) + { + case VsTestFramework: return DebuggerKind.VsTestFramework; + case Native: return DebuggerKind.Native; + case ManagedAndNative: return DebuggerKind.ManagedAndNative; + default: + return base.ConvertFrom(context, culture, value); + } + } + + } + +} \ No newline at end of file diff --git a/GoogleTestAdapter/Core/Runners/ExecutableResult.cs b/GoogleTestAdapter/Core/Runners/ExecutableResult.cs new file mode 100644 index 000000000..86b99b082 --- /dev/null +++ b/GoogleTestAdapter/Core/Runners/ExecutableResult.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; + +namespace GoogleTestAdapter.Runners +{ + public class ExecutableResult + { + public string Executable { get; } + public int ExitCode { get; } + public IReadOnlyList ExitCodeOutput { get; } + public bool ExitCodeSkip { get; } + + public ExecutableResult(string executable, int exitCode = 0, IList exitCodeOutput = null, bool exitCodeSkip = false) + { + if (string.IsNullOrWhiteSpace(executable)) + { + throw new ArgumentException(nameof(executable)); + } + + Executable = executable; + ExitCode = exitCode; + ExitCodeOutput = (IReadOnlyList) (exitCodeOutput ?? new List()); + ExitCodeSkip = exitCodeSkip; + } + } +} \ No newline at end of file diff --git a/GoogleTestAdapter/Core/Runners/ITestRunner.cs b/GoogleTestAdapter/Core/Runners/ITestRunner.cs index 8d7275c18..7f5cda816 100644 --- a/GoogleTestAdapter/Core/Runners/ITestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/ITestRunner.cs @@ -1,32 +1,9 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using GoogleTestAdapter.Model; using GoogleTestAdapter.ProcessExecution.Contracts; namespace GoogleTestAdapter.Runners { - - public class ExecutableResult - { - public string Executable { get; } - public int ExitCode { get; } - public IReadOnlyList ExitCodeOutput { get; } - public bool ExitCodeSkip { get; } - - public ExecutableResult(string executable, int exitCode = 0, IList exitCodeOutput = null, bool exitCodeSkip = false) - { - if (string.IsNullOrWhiteSpace(executable)) - { - throw new ArgumentException(nameof(executable)); - } - - Executable = executable; - ExitCode = exitCode; - ExitCodeOutput = (IReadOnlyList) (exitCodeOutput ?? new List()); - ExitCodeSkip = exitCodeSkip; - } - } - public interface ITestRunner { void RunTests(IEnumerable testCasesToRun, bool isBeingDebugged, diff --git a/GoogleTestAdapter/Core/Runners/PreparingTestRunner.cs b/GoogleTestAdapter/Core/Runners/PreparingTestRunner.cs index 2e513e728..0844f81b1 100644 --- a/GoogleTestAdapter/Core/Runners/PreparingTestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/PreparingTestRunner.cs @@ -6,7 +6,6 @@ using GoogleTestAdapter.Helpers; using GoogleTestAdapter.Model; using GoogleTestAdapter.Framework; -using GoogleTestAdapter.ProcessExecution; using GoogleTestAdapter.ProcessExecution.Contracts; using GoogleTestAdapter.Scheduling; using GoogleTestAdapter.Settings; diff --git a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs index 4c9c1a97f..07047c2bd 100644 --- a/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs +++ b/GoogleTestAdapter/Core/Runners/SequentialTestRunner.cs @@ -11,6 +11,7 @@ using GoogleTestAdapter.TestResults; using GoogleTestAdapter.Model; using GoogleTestAdapter.Framework; +using GoogleTestAdapter.ProcessExecution; using GoogleTestAdapter.ProcessExecution.Contracts; using GoogleTestAdapter.Settings; diff --git a/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs b/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs index 93123d307..21220fa0f 100644 --- a/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs +++ b/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs @@ -1,11 +1,10 @@ // This file has been modified by Microsoft on 6/2017. using GoogleTestAdapter.Common; +using GoogleTestAdapter.ProcessExecution; namespace GoogleTestAdapter.Settings { - public enum DebuggerKind { VsTestFramework, Native, ManagedAndNative } - /* To add a new option, make the following changes: - add (nullable!) property to GoogleTestAdapter.Settings.IGoogleTestAdapterSettings diff --git a/GoogleTestAdapter/Core/Settings/RunSettings.cs b/GoogleTestAdapter/Core/Settings/RunSettings.cs index 3403553d2..76f098281 100644 --- a/GoogleTestAdapter/Core/Settings/RunSettings.cs +++ b/GoogleTestAdapter/Core/Settings/RunSettings.cs @@ -2,6 +2,7 @@ using System.Xml.Serialization; using GoogleTestAdapter.Common; +using GoogleTestAdapter.ProcessExecution; namespace GoogleTestAdapter.Settings { diff --git a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs index f6312bb5d..a848e4a77 100644 --- a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs +++ b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs @@ -6,6 +6,7 @@ using System.Threading; using GoogleTestAdapter.Common; using GoogleTestAdapter.Helpers; +using GoogleTestAdapter.ProcessExecution; namespace GoogleTestAdapter.Settings { diff --git a/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs b/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs index 25af220b4..1f8e88ecf 100644 --- a/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs +++ b/GoogleTestAdapter/Core/TestResults/ExitCodeTestsReporter.cs @@ -6,6 +6,7 @@ using GoogleTestAdapter.Framework; using GoogleTestAdapter.Helpers; using GoogleTestAdapter.Model; +using GoogleTestAdapter.ProcessExecution; using GoogleTestAdapter.Runners; using GoogleTestAdapter.Settings; using GoogleTestAdapter.TestCases; @@ -59,7 +60,7 @@ public void ReportExitCodeTestCases(IEnumerable allResults, bo if (printWarning) { _logger.LogWarning( - $"Result code output can not be collected while debugging if option '{SettingsWrapper.OptionDebuggerKind}' is {DebuggerKind.VsTestFramework}"); + $"Result code output can not be collected while debugging if option '{SettingsWrapper.OptionDebuggerKind}' is '{DebuggerKind.VsTestFramework.ToReadableString()}'"); } } diff --git a/GoogleTestAdapter/Core/TestResults/XmlTestResultParser.cs b/GoogleTestAdapter/Core/TestResults/XmlTestResultParser.cs index 638f50afe..eaae35122 100644 --- a/GoogleTestAdapter/Core/TestResults/XmlTestResultParser.cs +++ b/GoogleTestAdapter/Core/TestResults/XmlTestResultParser.cs @@ -10,6 +10,7 @@ using System.Xml; using GoogleTestAdapter.Common; using GoogleTestAdapter.Model; +using GoogleTestAdapter.ProcessExecution; using GoogleTestAdapter.Settings; namespace GoogleTestAdapter.TestResults @@ -71,7 +72,7 @@ private IDictionary CreateWorkaroundMap() string message = $"Executable {_testExecutable} has test names containing characters which happen to not end up in the XML file produced by Google Test. " + "This has caused ambiguities while resolving the according test results, which are thus not available. " + - $"Note that this problem can only occur if GTA option '{SettingsWrapper.OptionDebuggerKind}' is {DebuggerKind.VsTestFramework}." + + $"Note that this problem can only occur if GTA option '{SettingsWrapper.OptionDebuggerKind}' is '{DebuggerKind.VsTestFramework.ToReadableString()}'." + $"\nThe following tests are affected: {string.Join(", ", duplicateTestCases.Select(tc => tc.FullyQualifiedName).OrderBy(n => n))}"; _logger.LogWarning(message); } diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs index b101387a0..c2cb1910d 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_FrameworkDebugging.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Diagnostics; using GoogleTestAdapter.Helpers; -using GoogleTestAdapter.Settings; +using GoogleTestAdapter.ProcessExecution; using GoogleTestAdapter.Tests.Common; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_NativeDebugging.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_NativeDebugging.cs index 023d95e6c..7f31e85c6 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_NativeDebugging.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorSequentialTests_NativeDebugging.cs @@ -1,8 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using GoogleTestAdapter.Helpers; -using GoogleTestAdapter.Settings; +using GoogleTestAdapter.ProcessExecution; using GoogleTestAdapter.Tests.Common; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; diff --git a/GoogleTestAdapter/TestAdapter/CommonFunctions.cs b/GoogleTestAdapter/TestAdapter/CommonFunctions.cs index 59eb1df62..52c67e897 100644 --- a/GoogleTestAdapter/TestAdapter/CommonFunctions.cs +++ b/GoogleTestAdapter/TestAdapter/CommonFunctions.cs @@ -5,6 +5,7 @@ using System.Reflection; using GoogleTestAdapter.Common; using GoogleTestAdapter.Helpers; +using GoogleTestAdapter.ProcessExecution; using GoogleTestAdapter.Settings; using GoogleTestAdapter.TestAdapter.Framework; using GoogleTestAdapter.TestAdapter.Settings; diff --git a/GoogleTestAdapter/TestAdapter/ProcessExecution/FrameworkDebuggedProcessExecutor.cs b/GoogleTestAdapter/TestAdapter/ProcessExecution/FrameworkDebuggedProcessExecutor.cs index f744fe1bc..348f5ef6b 100644 --- a/GoogleTestAdapter/TestAdapter/ProcessExecution/FrameworkDebuggedProcessExecutor.cs +++ b/GoogleTestAdapter/TestAdapter/ProcessExecution/FrameworkDebuggedProcessExecutor.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using GoogleTestAdapter.Common; using GoogleTestAdapter.Helpers; +using GoogleTestAdapter.ProcessExecution; using GoogleTestAdapter.ProcessExecution.Contracts; using GoogleTestAdapter.Settings; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter; diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs index a8cf69526..9470e85be 100644 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using GoogleTestAdapter.Common; +using GoogleTestAdapter.ProcessExecution; using GoogleTestAdapter.Settings; using GoogleTestAdapter.TestAdapter.Framework; using GoogleTestAdapter.VsPackage.GTA.Helpers; @@ -88,7 +89,7 @@ private void UpdateSettings() if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestExecutionOptionsDialogPage.KillProcessesOnCancel), bool.Parse, out var killProcessesOnCancel)) { _testExecutionOptions.KillProcessesOnCancel = killProcessesOnCancel; } if (GetAndDeleteValue(GeneralOptionsPage, nameof(TestExecutionOptionsDialogPage.WorkingDir), s => s, out var workingDir)) { _testExecutionOptions.WorkingDir = workingDir; } - if (GetAndDeleteValue(GeneralOptionsPage, "UseNewTestExecutionFramework2", bool.Parse, out var useNewTestExecutionFramework2)) { _testExecutionOptions.DebuggerKind = useNewTestExecutionFramework2 ? DebuggerKind.Native : DebuggerKind.Platform; } + if (GetAndDeleteValue(GeneralOptionsPage, "UseNewTestExecutionFramework2", bool.Parse, out var useNewTestExecutionFramework2)) { _testExecutionOptions.DebuggerKind = useNewTestExecutionFramework2 ? DebuggerKind.Native : DebuggerKind.VsTestFramework; } if (GetAndDeleteValue(GeneralOptionsPage, nameof(IGoogleTestAdapterSettings.DebugMode), bool.Parse, out var debugMode)) { _generalOptions.OutputMode = debugMode ? OutputMode.Debug : OutputMode.Info; } GetAndDeleteValue(GeneralOptionsPage, nameof(IGoogleTestAdapterSettings.ShowReleaseNotes), bool.Parse, out _); } diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestExecutionOptionsDialogPage.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestExecutionOptionsDialogPage.cs index d9de88539..f233bb889 100644 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestExecutionOptionsDialogPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/TestExecutionOptionsDialogPage.cs @@ -6,6 +6,9 @@ using System.ComponentModel; using System.Linq; using GoogleTestAdapter.Helpers; +using GoogleTestAdapter.ProcessExecution; +using Microsoft.VisualStudio.Shell; + // ReSharper disable LocalizableElement namespace GoogleTestAdapter.VsPackage.OptionsPages @@ -142,6 +145,7 @@ public bool KillProcessesOnCancel [Category(SettingsWrapper.CategoryMiscName)] [DisplayName(SettingsWrapper.OptionDebuggerKind)] [Description(SettingsWrapper.OptionDebuggerKindDescription)] + [PropertyPageTypeConverter(typeof(DebuggerKindConverter))] public DebuggerKind DebuggerKind { get => _debuggerKind; From 0ddc4c84d6f8c1edfaf592a5d2cf3c84b86d6231 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Tue, 12 Mar 2019 07:57:56 +0100 Subject: [PATCH 65/81] added readme section, removed uncommented code --- GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md | 1 + 1 file changed, 1 insertion(+) diff --git a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md index 55460be96..d5588a0c9 100644 --- a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md +++ b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md @@ -1,4 +1,5 @@ * enhancement: setting the new option [*Exit code test name*](https://github.com/csoltenborn/GoogleTestAdapter#evaluating_exit_code) results in an additional test per test executable that passes if the executable's exit code is 0, and fails otherwise. Additionally, GTA parses the test executable's output for certain [tokens](https://github.com/csoltenborn/GoogleTestAdapter#evaluating_exit_code_tokens) which allow to influence the test's outcome and message. One interesting use case for this is memory leak detection; a complete, reusable [example](https://github.com/csoltenborn/GoogleTestAdapter#evaluating_exit_code_leak_example) is provided as part of GTA's [SampleTests solution](https://github.com/csoltenborn/GoogleTestAdapter/tree/master/SampleTests) ([#266](https://github.com/csoltenborn/GoogleTestAdapter/issues/266), thanks to [alfredskpoon](https://github.com/alfredskpoon) for report, example code, and testing) +* usability: reorganized options ([#271](https://github.com/csoltenborn/GoogleTestAdapter/issues/271)) * enhancement: the GTA extension is now loaded asynchronically by Visual Studio; the drawback is that support for Visual Studio 2012 had to be dropped ([#243](https://github.com/csoltenborn/GoogleTestAdapter/issues/243)) * enhancement: the *Show release notes* option has been removed, and this release notes dialog has been slightly changed and now has very funny buttons ([#270](https://github.com/csoltenborn/GoogleTestAdapter/issues/270)) * maintenance: reduced code duplication of streaming and batch output parsers ([#263](https://github.com/csoltenborn/GoogleTestAdapter/issues/263)) From 0e3c0e40dd5fca0a6733bd97b6f97b6e5f54c5ba Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sun, 31 Mar 2019 18:15:39 +0200 Subject: [PATCH 66/81] added initial support for placeholders from helper files --- .../Runners/SequentialTestRunnerTests.cs | 3 +- .../Settings/SettingsWrapperTests.cs | 3 +- GoogleTestAdapter/Core/Core.csproj | 1 + .../Core/Settings/HelperFilesCache.cs | 73 +++++++++++++ .../Core/Settings/PlaceholderReplacer.cs | 102 ++++++++++-------- .../Core/Settings/SettingsWrapper.cs | 32 ++++-- .../TestAdapter/CommonFunctions.cs | 4 +- GoogleTestAdapter/Tests.Common/TestsBase.cs | 7 +- 8 files changed, 166 insertions(+), 59 deletions(-) create mode 100644 GoogleTestAdapter/Core/Settings/HelperFilesCache.cs diff --git a/GoogleTestAdapter/Core.Tests/Runners/SequentialTestRunnerTests.cs b/GoogleTestAdapter/Core.Tests/Runners/SequentialTestRunnerTests.cs index 95a842cce..db4bd4e2f 100644 --- a/GoogleTestAdapter/Core.Tests/Runners/SequentialTestRunnerTests.cs +++ b/GoogleTestAdapter/Core.Tests/Runners/SequentialTestRunnerTests.cs @@ -123,7 +123,8 @@ private SettingsWrapper CreateSettings(string solutionWorkingDir, string project return new SettingsWrapper(mockContainer.Object, TestResources.SampleTestsSolutionDir) { - RegexTraitParser = new RegexTraitParser(MockLogger.Object) + RegexTraitParser = new RegexTraitParser(MockLogger.Object), + HelperFilesCache = new HelperFilesCache(MockLogger.Object) }; } diff --git a/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs b/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs index 5e30e477e..07a126086 100644 --- a/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs +++ b/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs @@ -32,7 +32,8 @@ public override void SetUp() containerMock.Setup(c => c.GetSettingsForExecutable(It.IsAny())).Returns(MockXmlOptions.Object); TheOptions = new SettingsWrapper(containerMock.Object) { - RegexTraitParser = new RegexTraitParser(TestEnvironment.Logger) + RegexTraitParser = new RegexTraitParser(TestEnvironment.Logger), + HelperFilesCache = new HelperFilesCache(TestEnvironment.Logger) }; } diff --git a/GoogleTestAdapter/Core/Core.csproj b/GoogleTestAdapter/Core/Core.csproj index 9da1a1442..e629b1838 100644 --- a/GoogleTestAdapter/Core/Core.csproj +++ b/GoogleTestAdapter/Core/Core.csproj @@ -72,6 +72,7 @@ + diff --git a/GoogleTestAdapter/Core/Settings/HelperFilesCache.cs b/GoogleTestAdapter/Core/Settings/HelperFilesCache.cs new file mode 100644 index 000000000..17b35b5f8 --- /dev/null +++ b/GoogleTestAdapter/Core/Settings/HelperFilesCache.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.IO; +using GoogleTestAdapter.Common; + +namespace GoogleTestAdapter.Settings +{ + public class HelperFilesCache + { + public const string HelperFileEnding = ".gta_settings_helper"; + public const string SettingsSeparator = ":::"; + + private readonly ILogger _logger; + private readonly IDictionary> _files2ReplacementMap = new Dictionary>(); + + public HelperFilesCache(ILogger logger) + { + _logger = logger; + } + + // virtual for mocking + public virtual IDictionary GetReplacementsMap(string executable) + { + lock (this) + { + if (!_files2ReplacementMap.TryGetValue(executable, out IDictionary replacementMap)) + { + replacementMap = LoadReplacementsMap(executable); + _files2ReplacementMap[executable] = replacementMap; + } + return replacementMap; + } + } + + private IDictionary LoadReplacementsMap(string executable) + { + string helperFile = GetHelperFile(executable); + try + { + if (!File.Exists(helperFile)) + return new Dictionary(); + + return ParseHelperFile(File.ReadAllText(helperFile)); + } + catch (Exception e) + { + _logger.LogWarning($"Exception while loading settings from file '{helperFile}': {e}"); + return new Dictionary(); + } + } + + private IDictionary ParseHelperFile(string content) + { + var replacementMap = new Dictionary(); + foreach (string setting in content.Split(new []{ SettingsSeparator }, StringSplitOptions.RemoveEmptyEntries)) + { + int index = setting.IndexOf('='); + if (index > 0) + { + string name = setting.Substring(0, index); + string value = setting.Substring(index + 1, setting.Length - index); + replacementMap.Add(name, value); + } + } + return replacementMap; + } + + private string GetHelperFile(string executable) + { + return $"{executable}{HelperFileEnding}"; + } + } +} \ No newline at end of file diff --git a/GoogleTestAdapter/Core/Settings/PlaceholderReplacer.cs b/GoogleTestAdapter/Core/Settings/PlaceholderReplacer.cs index ab9f43ec7..aaf12767b 100644 --- a/GoogleTestAdapter/Core/Settings/PlaceholderReplacer.cs +++ b/GoogleTestAdapter/Core/Settings/PlaceholderReplacer.cs @@ -34,14 +34,16 @@ public class PlaceholderReplacer private readonly Func _getSolutionDir; private readonly Func _getSettings; + private readonly HelperFilesCache _helperFilesCache; private string SolutionDir => _getSolutionDir(); private IGoogleTestAdapterSettings Settings => _getSettings(); - public PlaceholderReplacer(Func getSolutionDir, Func getSettings) + public PlaceholderReplacer(Func getSolutionDir, Func getSettings, HelperFilesCache helperFilesCache) { _getSolutionDir = getSolutionDir; _getSettings = getSettings; + _helperFilesCache = helperFilesCache; } @@ -55,10 +57,12 @@ public PlaceholderReplacer(Func getSolutionDir, Func SolutionDir, () => _currentSettings, HelperFilesCache); + } + } + + private PlaceholderReplacer _placeholderReplacer; + private int _nrOfRunningExecutions; private string _currentExecutable; private Thread _currentThread; @@ -33,13 +46,16 @@ public SettingsWrapper(IGoogleTestAdapterSettingsContainer settingsContainer, st _settingsContainer = settingsContainer; _solutionDir = solutionDir; _currentSettings = _settingsContainer.SolutionSettings; - _placeholderReplacer = new PlaceholderReplacer(() => SolutionDir, () => _currentSettings); _settingsPrinter = new SettingsPrinter(this); } public virtual SettingsWrapper Clone() { - return new SettingsWrapper(_settingsContainer, _solutionDir) { RegexTraitParser = RegexTraitParser }; + return new SettingsWrapper(_settingsContainer, _solutionDir) + { + RegexTraitParser = RegexTraitParser, + HelperFilesCache = HelperFilesCache + }; } public override string ToString() @@ -302,12 +318,12 @@ public IEnumerable GetAdditionalPdbs(string executable) public string GetWorkingDirForExecution(string executable, string testDirectory, int threadId) { - return _placeholderReplacer.ReplaceWorkingDirPlaceholdersForExecution(executable, WorkingDir, testDirectory, threadId); + return _placeholderReplacer.ReplaceWorkingDirPlaceholdersForExecution(WorkingDir, executable, testDirectory, threadId); } public string GetWorkingDirForDiscovery(string executable) { - return _placeholderReplacer.ReplaceWorkingDirPlaceholdersForDiscovery(executable, WorkingDir); + return _placeholderReplacer.ReplaceWorkingDirPlaceholdersForDiscovery(WorkingDir, executable); } public const string OptionPathExtension = "PATH extension"; @@ -346,7 +362,7 @@ public string GetUserParametersForDiscovery(string executable) public virtual string BatchForTestSetup => _currentSettings.BatchForTestSetup ?? OptionBatchForTestSetupDefaultValue; public string GetBatchForTestSetup(string testDirectory, int threadId) - => _placeholderReplacer.ReplaceBatchForTestSetupPlaceholders(BatchForTestSetup, testDirectory, threadId); + => _placeholderReplacer.ReplaceBatchPlaceholders(BatchForTestSetup, testDirectory, threadId); public const string OptionBatchForTestTeardown = "Test teardown batch file"; @@ -357,7 +373,7 @@ public string GetBatchForTestSetup(string testDirectory, int threadId) public virtual string BatchForTestTeardown => _currentSettings.BatchForTestTeardown ?? OptionBatchForTestTeardownDefaultValue; public string GetBatchForTestTeardown(string testDirectory, int threadId) - => _placeholderReplacer.ReplaceBatchForTestTeardownPlaceholders(BatchForTestTeardown, testDirectory, + => _placeholderReplacer.ReplaceBatchPlaceholders(BatchForTestTeardown, testDirectory, threadId); diff --git a/GoogleTestAdapter/TestAdapter/CommonFunctions.cs b/GoogleTestAdapter/TestAdapter/CommonFunctions.cs index 4cbef3c50..8e2b34326 100644 --- a/GoogleTestAdapter/TestAdapter/CommonFunctions.cs +++ b/GoogleTestAdapter/TestAdapter/CommonFunctions.cs @@ -57,8 +57,8 @@ public static void CreateEnvironment(IRunSettings runSettings, IMessageLogger me var settingsWrapper = new SettingsWrapper(ourRunSettings, solutionDir); var loggerAdapter = new VsTestFrameworkLogger(messageLogger, () => settingsWrapper.OutputMode, () => settingsWrapper.TimestampOutput); - var regexParser = new RegexTraitParser(loggerAdapter); - settingsWrapper.RegexTraitParser = regexParser; + settingsWrapper.RegexTraitParser = new RegexTraitParser(loggerAdapter); + settingsWrapper.HelperFilesCache = new HelperFilesCache(loggerAdapter); LogWarningsForDeprecatedSettings(ourRunSettings, loggerAdapter); diff --git a/GoogleTestAdapter/Tests.Common/TestsBase.cs b/GoogleTestAdapter/Tests.Common/TestsBase.cs index a6cf46d79..a2736e578 100644 --- a/GoogleTestAdapter/Tests.Common/TestsBase.cs +++ b/GoogleTestAdapter/Tests.Common/TestsBase.cs @@ -46,6 +46,7 @@ protected TestsBase() var mockRunSettings = new Mock(); mockSettingsContainer.Setup(c => c.SolutionSettings).Returns(mockRunSettings.Object); MockOptions = new Mock(mockSettingsContainer.Object, Path.GetFullPath(TestResources.SampleTestsSolutionDir)); + MockFrameworkReporter = new Mock(); TestEnvironment = new TestEnvironment(MockOptions.Object, MockLogger.Object); @@ -56,11 +57,13 @@ protected TestsBase() [TestInitialize] public virtual void SetUp() { - SetupOptions(MockOptions); + SetupOptions(MockOptions, MockLogger.Object); } - public static void SetupOptions(Mock mockOptions) + public static void SetupOptions(Mock mockOptions, ILogger logger) { + mockOptions.Object.HelperFilesCache = new HelperFilesCache(logger); + mockOptions.Setup(o => o.CheckCorrectUsage(It.IsAny())).Callback(() => { }); mockOptions.Setup(o => o.Clone()).Returns(mockOptions.Object); From 18469fe84be5fda597d41dcbe34a11dbc806226c Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sun, 31 Mar 2019 19:40:09 +0200 Subject: [PATCH 67/81] SolutionDir, ConfigurationName and PlatformName can be consumed from helper files --- .../Core/Settings/HelperFilesCache.cs | 14 +-- .../Core/Settings/PlaceholderReplacer.cs | 104 +++++++++--------- 2 files changed, 57 insertions(+), 61 deletions(-) diff --git a/GoogleTestAdapter/Core/Settings/HelperFilesCache.cs b/GoogleTestAdapter/Core/Settings/HelperFilesCache.cs index 17b35b5f8..a330a663c 100644 --- a/GoogleTestAdapter/Core/Settings/HelperFilesCache.cs +++ b/GoogleTestAdapter/Core/Settings/HelperFilesCache.cs @@ -32,6 +32,11 @@ public virtual IDictionary GetReplacementsMap(string executable) } } + private string GetHelperFile(string executable) + { + return $"{executable}{HelperFileEnding}"; + } + private IDictionary LoadReplacementsMap(string executable) { string helperFile = GetHelperFile(executable); @@ -57,17 +62,12 @@ private IDictionary ParseHelperFile(string content) int index = setting.IndexOf('='); if (index > 0) { - string name = setting.Substring(0, index); + string placeholder = setting.Substring(0, index); string value = setting.Substring(index + 1, setting.Length - index); - replacementMap.Add(name, value); + replacementMap.Add(placeholder, value); } } return replacementMap; } - - private string GetHelperFile(string executable) - { - return $"{executable}{HelperFileEnding}"; - } } } \ No newline at end of file diff --git a/GoogleTestAdapter/Core/Settings/PlaceholderReplacer.cs b/GoogleTestAdapter/Core/Settings/PlaceholderReplacer.cs index aaf12767b..14e0aaf96 100644 --- a/GoogleTestAdapter/Core/Settings/PlaceholderReplacer.cs +++ b/GoogleTestAdapter/Core/Settings/PlaceholderReplacer.cs @@ -58,8 +58,8 @@ public PlaceholderReplacer(Func getSolutionDir, Func Date: Tue, 2 Apr 2019 06:06:58 +0200 Subject: [PATCH 68/81] added unit tests --- .../Core.Tests/Core.Tests.csproj | 2 + .../Settings/HelperFilesCacheTests.cs | 132 +++++++++++++++++ .../Settings/PlaceholderReplacerTests.cs | 140 ++++++++++++++++++ GoogleTestAdapter/Core.Tests/packages.config | 2 + .../Core/Settings/HelperFilesCache.cs | 6 +- .../Core/Settings/PlaceholderReplacer.cs | 2 +- .../Core/Settings/SettingsWrapper.cs | 2 +- 7 files changed, 283 insertions(+), 3 deletions(-) create mode 100644 GoogleTestAdapter/Core.Tests/Settings/HelperFilesCacheTests.cs create mode 100644 GoogleTestAdapter/Core.Tests/Settings/PlaceholderReplacerTests.cs diff --git a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj index ab66af659..5cc726aca 100644 --- a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj +++ b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj @@ -97,6 +97,8 @@ + + diff --git a/GoogleTestAdapter/Core.Tests/Settings/HelperFilesCacheTests.cs b/GoogleTestAdapter/Core.Tests/Settings/HelperFilesCacheTests.cs new file mode 100644 index 000000000..45cd3d1fa --- /dev/null +++ b/GoogleTestAdapter/Core.Tests/Settings/HelperFilesCacheTests.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.IO; +using FluentAssertions; +using GoogleTestAdapter.Tests.Common; +using GoogleTestAdapter.Tests.Common.Assertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using static GoogleTestAdapter.Tests.Common.TestMetadata.TestCategories; + +namespace GoogleTestAdapter.Settings +{ + [TestClass] + public class HelperFilesCacheTests : TestsBase + { + [TestMethod] + [TestCategory(Unit)] + public void GetReplacementsMap_NoFile_EmptyDictionary() + { + string executable = TestResources.Tests_DebugX86; + var extraSettings = $"{executable}{HelperFilesCache.HelperFileEnding}"; + extraSettings.AsFileInfo().Should().NotExist(); + + var cache = new HelperFilesCache(MockLogger.Object); + var map = cache.GetReplacementsMap(executable); + + map.Should().BeEmpty(); + } + + [TestMethod] + [TestCategory(Unit)] + public void GetReplacementsMap_EmptyString_EmptyDictionary() + { + DoTest("", map => + { + map.Should().BeEmpty(); + }); + } + + [TestMethod] + [TestCategory(Unit)] + public void GetReplacementsMap_InvalidString_EmptyDictionary() + { + DoTest("Foo", map => + { + map.Should().BeEmpty(); + }); + } + + [TestMethod] + [TestCategory(Unit)] + public void GetReplacementsMap_SingleValue_ProperDictionary() + { + DoTest("Foo=Bar", map => + { + map.Should().HaveCount(1); + map.Should().Contain(new KeyValuePair("Foo", "Bar")); + }); + } + + [TestMethod] + [TestCategory(Unit)] + public void GetReplacementsMap_TwoValues_ProperDictionary() + { + DoTest($"Placeholder1=value1{HelperFilesCache.SettingsSeparator}Placeholder2=value2", map => + { + map.Should().HaveCount(2); + map.Should().Contain(new KeyValuePair("Placeholder1", "value1")); + map.Should().Contain(new KeyValuePair("Placeholder2", "value2")); + }); + } + + [TestMethod] + [TestCategory(Unit)] + public void GetReplacementsMap_SingleWithEmptyValue_ProperDictionary() + { + DoTest("Placeholder1=", map => + { + map.Should().HaveCount(1); + map.Should().Contain(new KeyValuePair("Placeholder1", "")); + }); + } + + [TestMethod] + [TestCategory(Unit)] + public void GetReplacementsMap_SingleWithTrailingSeparator_ProperDictionary() + { + DoTest($"Ph=V{HelperFilesCache.SettingsSeparator}", map => + { + map.Should().HaveCount(1); + map.Should().Contain(new KeyValuePair("Ph", "V")); + }); + } + + [TestMethod] + [TestCategory(Unit)] + public void GetReplacementsMap_OnlySeparator_ProperDictionary() + { + DoTest($"{HelperFilesCache.SettingsSeparator}", map => + { + map.Should().BeEmpty(); + }); + } + + [TestMethod] + [TestCategory(Unit)] + public void GetReplacementsMap_OnlyTwoSeparators_ProperDictionary() + { + DoTest($"{HelperFilesCache.SettingsSeparator}{HelperFilesCache.SettingsSeparator}", map => + { + map.Should().BeEmpty(); + }); + } + + private void DoTest(string content, Action> assertions, string executable = TestResources.Tests_DebugX86) + { + var extraSettings = $"{executable}{HelperFilesCache.HelperFileEnding}"; + try + { + extraSettings.AsFileInfo().Should().NotExist(); + File.WriteAllText(extraSettings, content); + + var cache = new HelperFilesCache(MockLogger.Object); + var map = cache.GetReplacementsMap(executable); + assertions(map); + } + finally + { + File.Delete(extraSettings); + } + } + } +} \ No newline at end of file diff --git a/GoogleTestAdapter/Core.Tests/Settings/PlaceholderReplacerTests.cs b/GoogleTestAdapter/Core.Tests/Settings/PlaceholderReplacerTests.cs new file mode 100644 index 000000000..9acf30e6b --- /dev/null +++ b/GoogleTestAdapter/Core.Tests/Settings/PlaceholderReplacerTests.cs @@ -0,0 +1,140 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using FluentAssertions; +using GoogleTestAdapter.Tests.Common; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using static GoogleTestAdapter.Tests.Common.TestMetadata.TestCategories; + +namespace GoogleTestAdapter.Settings +{ + [TestClass] + public class PlaceholderReplacerTests + { + private class PlaceholderAndValue + { + public string Placeholder { get; } + public object Value { get; } + + public PlaceholderAndValue(string placeholder, object value) + { + Placeholder = placeholder; + Value = value; + } + } + + private class MethodnameAndPlaceholder + { + public string MethodName { get; } + public string Placeholder { get; } + + public MethodnameAndPlaceholder(string methodName, string placeholder) + { + MethodName = methodName; + Placeholder = placeholder; + } + } + + private static readonly string[] MethodNames = { + nameof(PlaceholderReplacer.ReplaceAdditionalPdbsPlaceholders), + nameof(PlaceholderReplacer.ReplaceAdditionalTestExecutionParamPlaceholdersForDiscovery), + nameof(PlaceholderReplacer.ReplaceAdditionalTestExecutionParamPlaceholdersForExecution), + nameof(PlaceholderReplacer.ReplaceBatchPlaceholders), + nameof(PlaceholderReplacer.ReplacePathExtensionPlaceholders), + nameof(PlaceholderReplacer.ReplaceWorkingDirPlaceholdersForDiscovery), + nameof(PlaceholderReplacer.ReplaceWorkingDirPlaceholdersForExecution) + }; + + private static readonly List PlaceholdersAndExpectedValues = new List + { + new PlaceholderAndValue(PlaceholderReplacer.SolutionDirPlaceholder, TestResources.SampleTestsSolutionDir), + new PlaceholderAndValue(PlaceholderReplacer.PlatformNamePlaceholder, "Win33"), + new PlaceholderAndValue(PlaceholderReplacer.ConfigurationNamePlaceholder, "MyDebug"), + // ReSharper disable once AssignNullToNotNullAttribute + new PlaceholderAndValue(PlaceholderReplacer.ExecutableDirPlaceholder, Path.GetFullPath(Path.GetDirectoryName(TestResources.Tests_DebugX86))), + new PlaceholderAndValue(PlaceholderReplacer.ExecutablePlaceholder, TestResources.Tests_DebugX86), + new PlaceholderAndValue(PlaceholderReplacer.TestDirPlaceholder, "testDirectory"), + new PlaceholderAndValue(PlaceholderReplacer.ThreadIdPlaceholder, 42) + }; + + private static readonly List UnsupportedCombinations = new List + { + new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplaceAdditionalPdbsPlaceholders), PlaceholderReplacer.TestDirPlaceholder), + new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplaceAdditionalTestExecutionParamPlaceholdersForDiscovery), PlaceholderReplacer.TestDirPlaceholder), + new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplacePathExtensionPlaceholders), PlaceholderReplacer.TestDirPlaceholder), + new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplaceWorkingDirPlaceholdersForDiscovery), PlaceholderReplacer.TestDirPlaceholder), + + new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplaceAdditionalPdbsPlaceholders), PlaceholderReplacer.ThreadIdPlaceholder), + new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplaceAdditionalTestExecutionParamPlaceholdersForDiscovery), PlaceholderReplacer.ThreadIdPlaceholder), + new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplacePathExtensionPlaceholders), PlaceholderReplacer.ThreadIdPlaceholder), + new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplaceWorkingDirPlaceholdersForDiscovery), PlaceholderReplacer.ThreadIdPlaceholder), + + new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplaceBatchPlaceholders), PlaceholderReplacer.ExecutablePlaceholder), + new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplaceBatchPlaceholders), PlaceholderReplacer.ExecutableDirPlaceholder), + new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplaceBatchPlaceholders), PlaceholderReplacer.ConfigurationNamePlaceholder), + new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplaceBatchPlaceholders), PlaceholderReplacer.PlatformNamePlaceholder), + }; + + + [TestMethod] + [TestCategory(Unit)] + public void AllReplacementsTest() + { + Mock mockHelperFilesCache = new Mock(); + mockHelperFilesCache.Setup(c => c.GetReplacementsMap(It.IsAny())).Returns( + new Dictionary + { + {nameof(IGoogleTestAdapterSettings.ConfigurationName), "MyDebug"}, + {nameof(IGoogleTestAdapterSettings.PlatformName), "Win33"} + }); + Mock mockOptions = new Mock(); + var placeholderReplacer = new PlaceholderReplacer( + () => TestResources.SampleTestsSolutionDir, + () => mockOptions.Object, + mockHelperFilesCache.Object); + + foreach (string methodName in MethodNames) + { + foreach (PlaceholderAndValue placeholder in PlaceholdersAndExpectedValues) + { + if (!UnsupportedCombinations.Any(combination => + combination.MethodName == methodName && combination.Placeholder == placeholder.Placeholder)) + { + GenericReplacementTest(placeholderReplacer, methodName, placeholder.Placeholder, placeholder.Value.ToString()); + } + } + } + } + + private void GenericReplacementTest(PlaceholderReplacer placeholderReplacer, + string methodName, string input, object expected) + { + var method = typeof(PlaceholderReplacer).GetMethod(methodName); + // ReSharper disable once PossibleNullReferenceException + var parameters = method.GetParameters(); + + var parameterValues = new List { input }; + for (int i = 1; i < parameters.Length; i++) + { + parameterValues.Add(GetValue(parameters[i])); + } + + string result = (string) method.Invoke(placeholderReplacer, parameterValues.ToArray()); + + result.Should().Be(expected.ToString(), $"{methodName} should replace {input} with {expected}"); + } + + private object GetValue(ParameterInfo parameter) + { + switch (parameter.Name) + { + case "executable": return TestResources.Tests_DebugX86; + case "threadId": return 42; + default: return parameter.Name; + } + } + + } +} \ No newline at end of file diff --git a/GoogleTestAdapter/Core.Tests/packages.config b/GoogleTestAdapter/Core.Tests/packages.config index 87cac3d92..31fd4c297 100644 --- a/GoogleTestAdapter/Core.Tests/packages.config +++ b/GoogleTestAdapter/Core.Tests/packages.config @@ -3,6 +3,8 @@ + + diff --git a/GoogleTestAdapter/Core/Settings/HelperFilesCache.cs b/GoogleTestAdapter/Core/Settings/HelperFilesCache.cs index a330a663c..0d206bd5a 100644 --- a/GoogleTestAdapter/Core/Settings/HelperFilesCache.cs +++ b/GoogleTestAdapter/Core/Settings/HelperFilesCache.cs @@ -13,6 +13,10 @@ public class HelperFilesCache private readonly ILogger _logger; private readonly IDictionary> _files2ReplacementMap = new Dictionary>(); + // public for mocking + // ReSharper disable once UnusedMember.Global + public HelperFilesCache() {} + public HelperFilesCache(ILogger logger) { _logger = logger; @@ -63,7 +67,7 @@ private IDictionary ParseHelperFile(string content) if (index > 0) { string placeholder = setting.Substring(0, index); - string value = setting.Substring(index + 1, setting.Length - index); + string value = setting.Substring(index + 1, setting.Length - index - 1); replacementMap.Add(placeholder, value); } } diff --git a/GoogleTestAdapter/Core/Settings/PlaceholderReplacer.cs b/GoogleTestAdapter/Core/Settings/PlaceholderReplacer.cs index 14e0aaf96..06433866e 100644 --- a/GoogleTestAdapter/Core/Settings/PlaceholderReplacer.cs +++ b/GoogleTestAdapter/Core/Settings/PlaceholderReplacer.cs @@ -55,7 +55,7 @@ public PlaceholderReplacer(Func getSolutionDir, Func _currentSettings.AdditionalPdbs ?? OptionAdditionalPdbsDefaultValue; public IEnumerable GetAdditionalPdbs(string executable) => Utils.SplitAdditionalPdbs(AdditionalPdbs) - .Select(p => _placeholderReplacer.ReplaceAdditionalPdbsPlaceholders(executable, p)); + .Select(p => _placeholderReplacer.ReplaceAdditionalPdbsPlaceholders(p, executable)); public const string OptionWorkingDir = "Working directory"; From 6de7d99b668339fe31be1d6356e436c1dcb5d576 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sun, 14 Apr 2019 11:04:16 +0200 Subject: [PATCH 69/81] added example project; warnings are printed for unknown placeholders; changed seperator and removed prefix --- .../Settings/PlaceholderReplacerTests.cs | 57 +++-- .../Settings/SettingsWrapperTests.cs | 3 +- .../Core/Settings/HelperFilesCache.cs | 6 +- .../Core/Settings/PlaceholderReplacer.cs | 71 +++++- .../Core/Settings/SettingsWrapper.cs | 8 +- .../DiaResolver.Tests/DiaResolverTests.cs | 2 +- GoogleTestAdapter/GoogleTestAdapter.sln | 13 ++ .../Settings/HelperFileTests.cs | 61 +++++ .../TestAdapter.Tests.csproj | 1 + .../TestExecutorTestsBase.cs | 1 - .../Tests.Common/TestResources.cs | 3 + README.md | 5 + .../HelperFileTests/HelperFileTests.cpp | 8 + .../HelperFileTests/HelperFileTests.vcxproj | 214 ++++++++++++++++++ .../HelperFileTests.vcxproj.filters | 28 +++ SampleTests/HelperFileTests/Main.cpp | 22 ++ .../LeakCheckTests/LeakCheckTests.vcxproj | 12 +- SampleTests/SampleTests.gta.runsettings | 47 ++-- SampleTests/SampleTests.sln | 12 + 19 files changed, 520 insertions(+), 54 deletions(-) create mode 100644 GoogleTestAdapter/TestAdapter.Tests/Settings/HelperFileTests.cs create mode 100644 SampleTests/HelperFileTests/HelperFileTests.cpp create mode 100644 SampleTests/HelperFileTests/HelperFileTests.vcxproj create mode 100644 SampleTests/HelperFileTests/HelperFileTests.vcxproj.filters create mode 100644 SampleTests/HelperFileTests/Main.cpp diff --git a/GoogleTestAdapter/Core.Tests/Settings/PlaceholderReplacerTests.cs b/GoogleTestAdapter/Core.Tests/Settings/PlaceholderReplacerTests.cs index 9acf30e6b..ebd1d2e16 100644 --- a/GoogleTestAdapter/Core.Tests/Settings/PlaceholderReplacerTests.cs +++ b/GoogleTestAdapter/Core.Tests/Settings/PlaceholderReplacerTests.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Reflection; using FluentAssertions; +using GoogleTestAdapter.Common; using GoogleTestAdapter.Tests.Common; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -41,7 +42,8 @@ public MethodnameAndPlaceholder(string methodName, string placeholder) nameof(PlaceholderReplacer.ReplaceAdditionalPdbsPlaceholders), nameof(PlaceholderReplacer.ReplaceAdditionalTestExecutionParamPlaceholdersForDiscovery), nameof(PlaceholderReplacer.ReplaceAdditionalTestExecutionParamPlaceholdersForExecution), - nameof(PlaceholderReplacer.ReplaceBatchPlaceholders), + nameof(PlaceholderReplacer.ReplaceSetupBatchPlaceholders), + nameof(PlaceholderReplacer.ReplaceTeardownBatchPlaceholders), nameof(PlaceholderReplacer.ReplacePathExtensionPlaceholders), nameof(PlaceholderReplacer.ReplaceWorkingDirPlaceholdersForDiscovery), nameof(PlaceholderReplacer.ReplaceWorkingDirPlaceholdersForExecution) @@ -71,10 +73,15 @@ public MethodnameAndPlaceholder(string methodName, string placeholder) new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplacePathExtensionPlaceholders), PlaceholderReplacer.ThreadIdPlaceholder), new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplaceWorkingDirPlaceholdersForDiscovery), PlaceholderReplacer.ThreadIdPlaceholder), - new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplaceBatchPlaceholders), PlaceholderReplacer.ExecutablePlaceholder), - new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplaceBatchPlaceholders), PlaceholderReplacer.ExecutableDirPlaceholder), - new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplaceBatchPlaceholders), PlaceholderReplacer.ConfigurationNamePlaceholder), - new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplaceBatchPlaceholders), PlaceholderReplacer.PlatformNamePlaceholder), + new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplaceSetupBatchPlaceholders), PlaceholderReplacer.ExecutablePlaceholder), + new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplaceSetupBatchPlaceholders), PlaceholderReplacer.ExecutableDirPlaceholder), + new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplaceSetupBatchPlaceholders), PlaceholderReplacer.ConfigurationNamePlaceholder), + new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplaceSetupBatchPlaceholders), PlaceholderReplacer.PlatformNamePlaceholder), + + new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplaceTeardownBatchPlaceholders), PlaceholderReplacer.ExecutablePlaceholder), + new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplaceTeardownBatchPlaceholders), PlaceholderReplacer.ExecutableDirPlaceholder), + new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplaceTeardownBatchPlaceholders), PlaceholderReplacer.ConfigurationNamePlaceholder), + new MethodnameAndPlaceholder(nameof(PlaceholderReplacer.ReplaceTeardownBatchPlaceholders), PlaceholderReplacer.PlatformNamePlaceholder), }; @@ -90,10 +97,12 @@ public void AllReplacementsTest() {nameof(IGoogleTestAdapterSettings.PlatformName), "Win33"} }); Mock mockOptions = new Mock(); + Mock mockLogger = new Mock(); var placeholderReplacer = new PlaceholderReplacer( () => TestResources.SampleTestsSolutionDir, () => mockOptions.Object, - mockHelperFilesCache.Object); + mockHelperFilesCache.Object, + mockLogger.Object); foreach (string methodName in MethodNames) { @@ -102,28 +111,50 @@ public void AllReplacementsTest() if (!UnsupportedCombinations.Any(combination => combination.MethodName == methodName && combination.Placeholder == placeholder.Placeholder)) { - GenericReplacementTest(placeholderReplacer, methodName, placeholder.Placeholder, placeholder.Value.ToString()); + var result = InvokeMethodWithStandardParameters(placeholderReplacer, methodName, placeholder.Placeholder); + result.Should().Be(placeholder.Value.ToString(), $"{methodName} should replace {placeholder.Placeholder} with {(object) placeholder.Value.ToString()}"); + mockLogger.Verify(l => l.LogWarning(It.IsAny()), Times.Never); } } } } - private void GenericReplacementTest(PlaceholderReplacer placeholderReplacer, - string methodName, string input, object expected) + [TestMethod] + [TestCategory(Unit)] + public void AllReplacementMethods_UnknownPlaceholderResultsInWarning() + { + Mock mockHelperFilesCache = new Mock(); + mockHelperFilesCache.Setup(c => c.GetReplacementsMap(It.IsAny())) + .Returns(new Dictionary()); + Mock mockOptions = new Mock(); + Mock mockLogger = new Mock(); + var replacer = new PlaceholderReplacer(() => "solutiondir", () => mockOptions.Object, + mockHelperFilesCache.Object, mockLogger.Object); + + string placeholder = "$(UnknownPlaceholder)"; + foreach (string methodName in MethodNames) + { + mockLogger.Reset(); + string result = InvokeMethodWithStandardParameters(replacer, methodName, placeholder); + result.Should().Be(placeholder); + mockLogger.Verify(l => l.LogWarning(It.Is(msg => msg.Contains(placeholder))), Times.Once); + } + } + + private string InvokeMethodWithStandardParameters(PlaceholderReplacer placeholderReplacer, string methodName, + string input) { var method = typeof(PlaceholderReplacer).GetMethod(methodName); // ReSharper disable once PossibleNullReferenceException var parameters = method.GetParameters(); - var parameterValues = new List { input }; + var parameterValues = new List {input}; for (int i = 1; i < parameters.Length; i++) { parameterValues.Add(GetValue(parameters[i])); } - string result = (string) method.Invoke(placeholderReplacer, parameterValues.ToArray()); - - result.Should().Be(expected.ToString(), $"{methodName} should replace {input} with {expected}"); + return (string) method.Invoke(placeholderReplacer, parameterValues.ToArray()); } private object GetValue(ParameterInfo parameter) diff --git a/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs b/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs index 07a126086..1da28c8de 100644 --- a/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs +++ b/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs @@ -644,7 +644,8 @@ private SettingsWrapper CreateSettingsWrapper(string solutionWorkdir, params str return new SettingsWrapper(containerMock.Object) { - RegexTraitParser = new RegexTraitParser(MockLogger.Object) + RegexTraitParser = new RegexTraitParser(MockLogger.Object), + HelperFilesCache = new HelperFilesCache(MockLogger.Object) }; } diff --git a/GoogleTestAdapter/Core/Settings/HelperFilesCache.cs b/GoogleTestAdapter/Core/Settings/HelperFilesCache.cs index 0d206bd5a..499eb0800 100644 --- a/GoogleTestAdapter/Core/Settings/HelperFilesCache.cs +++ b/GoogleTestAdapter/Core/Settings/HelperFilesCache.cs @@ -8,7 +8,7 @@ namespace GoogleTestAdapter.Settings public class HelperFilesCache { public const string HelperFileEnding = ".gta_settings_helper"; - public const string SettingsSeparator = ":::"; + public const string SettingsSeparator = "::GTA::"; private readonly ILogger _logger; private readonly IDictionary> _files2ReplacementMap = new Dictionary>(); @@ -22,6 +22,8 @@ public HelperFilesCache(ILogger logger) _logger = logger; } + public ILogger Logger => _logger; + // virtual for mocking public virtual IDictionary GetReplacementsMap(string executable) { @@ -36,7 +38,7 @@ public virtual IDictionary GetReplacementsMap(string executable) } } - private string GetHelperFile(string executable) + public static string GetHelperFile(string executable) { return $"{executable}{HelperFileEnding}"; } diff --git a/GoogleTestAdapter/Core/Settings/PlaceholderReplacer.cs b/GoogleTestAdapter/Core/Settings/PlaceholderReplacer.cs index 06433866e..31a74c232 100644 --- a/GoogleTestAdapter/Core/Settings/PlaceholderReplacer.cs +++ b/GoogleTestAdapter/Core/Settings/PlaceholderReplacer.cs @@ -1,5 +1,8 @@ using System; using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using GoogleTestAdapter.Common; namespace GoogleTestAdapter.Settings { @@ -32,18 +35,22 @@ public class PlaceholderReplacer private const string DescriptionOfEnvVarPlaceholders = "Environment variables are also possible, e.g. %PATH%"; + private static readonly Regex PlaceholdersRegex = new Regex(@"\$\(\w+\)", RegexOptions.Compiled); + private readonly Func _getSolutionDir; private readonly Func _getSettings; private readonly HelperFilesCache _helperFilesCache; + private readonly ILogger _logger; private string SolutionDir => _getSolutionDir(); private IGoogleTestAdapterSettings Settings => _getSettings(); - public PlaceholderReplacer(Func getSolutionDir, Func getSettings, HelperFilesCache helperFilesCache) + public PlaceholderReplacer(Func getSolutionDir, Func getSettings, HelperFilesCache helperFilesCache, ILogger logger) { _getSolutionDir = getSolutionDir; _getSettings = getSettings; _helperFilesCache = helperFilesCache; + _logger = logger; } @@ -62,6 +69,9 @@ public string ReplaceAdditionalPdbsPlaceholders(string pdb, string executable) pdb = ReplaceSolutionDirPlaceholder(pdb, executable); pdb = ReplaceEnvironmentVariables(pdb); pdb = ReplaceHelperFileSettings(pdb, executable); + + CheckForRemainingPlaceholders(pdb, SettingsWrapper.OptionAdditionalPdbs); + return pdb; } @@ -84,6 +94,9 @@ public string ReplaceWorkingDirPlaceholdersForDiscovery(string workingDir, strin workingDir = ReplaceSolutionDirPlaceholder(workingDir, executable); workingDir = ReplaceEnvironmentVariables(workingDir); workingDir = ReplaceHelperFileSettings(workingDir, executable); + + CheckForRemainingPlaceholders(workingDir, SettingsWrapper.OptionWorkingDir); + return workingDir; } @@ -91,7 +104,14 @@ public string ReplaceWorkingDirPlaceholdersForExecution(string workingDir, strin string testDirectory, int threadId) { workingDir = ReplaceTestDirAndThreadIdPlaceholders(workingDir, testDirectory, threadId); - workingDir = ReplaceWorkingDirPlaceholdersForDiscovery(workingDir, executable); + workingDir = ReplaceExecutablePlaceholders(workingDir, executable); + workingDir = ReplacePlatformAndConfigurationPlaceholders(workingDir, executable); + workingDir = ReplaceSolutionDirPlaceholder(workingDir, executable); + workingDir = ReplaceEnvironmentVariables(workingDir); + workingDir = ReplaceHelperFileSettings(workingDir, executable); + + CheckForRemainingPlaceholders(workingDir, SettingsWrapper.OptionWorkingDir); + return workingDir; } @@ -111,6 +131,9 @@ public string ReplacePathExtensionPlaceholders(string pathExtension, string exec pathExtension = ReplaceSolutionDirPlaceholder(pathExtension, executable); pathExtension = ReplaceEnvironmentVariables(pathExtension); pathExtension = ReplaceHelperFileSettings(pathExtension, executable); + + CheckForRemainingPlaceholders(pathExtension, SettingsWrapper.OptionPathExtension); + return pathExtension; } @@ -133,6 +156,9 @@ public string ReplaceAdditionalTestExecutionParamPlaceholdersForDiscovery(string additionalTestExecutionParam = ReplaceSolutionDirPlaceholder(additionalTestExecutionParam, executable); additionalTestExecutionParam = ReplaceEnvironmentVariables(additionalTestExecutionParam); additionalTestExecutionParam = ReplaceHelperFileSettings(additionalTestExecutionParam, executable); + + CheckForRemainingPlaceholders(additionalTestExecutionParam, SettingsWrapper.OptionAdditionalTestExecutionParams); + return additionalTestExecutionParam; } @@ -140,8 +166,14 @@ public string ReplaceAdditionalTestExecutionParamPlaceholdersForExecution(string { additionalTestExecutionParam = ReplaceTestDirAndThreadIdPlaceholders(additionalTestExecutionParam, testDirectory, threadId); - additionalTestExecutionParam = - ReplaceAdditionalTestExecutionParamPlaceholdersForDiscovery(additionalTestExecutionParam, executable); + additionalTestExecutionParam = ReplaceExecutablePlaceholders(additionalTestExecutionParam, executable); + additionalTestExecutionParam = ReplacePlatformAndConfigurationPlaceholders(additionalTestExecutionParam, executable); + additionalTestExecutionParam = ReplaceSolutionDirPlaceholder(additionalTestExecutionParam, executable); + additionalTestExecutionParam = ReplaceEnvironmentVariables(additionalTestExecutionParam); + additionalTestExecutionParam = ReplaceHelperFileSettings(additionalTestExecutionParam, executable); + + CheckForRemainingPlaceholders(additionalTestExecutionParam, SettingsWrapper.OptionAdditionalTestExecutionParams); + return additionalTestExecutionParam; } @@ -154,7 +186,22 @@ public string ReplaceAdditionalTestExecutionParamPlaceholdersForExecution(string DescriptionOfThreadIdPlaceholder + "\n" + DescriptionOfEnvVarPlaceholders; - public string ReplaceBatchPlaceholders(string batch, string testDirectory, int threadId) + + public string ReplaceSetupBatchPlaceholders(string batch, string testDirectory, int threadId) + { + batch = ReplaceBatchPlaceholders(batch, testDirectory, threadId); + CheckForRemainingPlaceholders(batch, SettingsWrapper.OptionBatchForTestSetup); + return batch; + } + + public string ReplaceTeardownBatchPlaceholders(string batch, string testDirectory, int threadId) + { + batch = ReplaceBatchPlaceholders(batch, testDirectory, threadId); + CheckForRemainingPlaceholders(batch, SettingsWrapper.OptionBatchForTestTeardown); + return batch; + } + + private string ReplaceBatchPlaceholders(string batch, string testDirectory, int threadId) { batch = ReplaceTestDirAndThreadIdPlaceholders(batch, testDirectory, threadId); batch = ReplacePlatformAndConfigurationPlaceholders(batch); @@ -225,7 +272,7 @@ private string ReplaceHelperFileSettings(string theString, string executable) var replacementMap = _helperFilesCache.GetReplacementsMap(executable); foreach (var nameValuePair in replacementMap) { - theString = theString.Replace($"$(GTA:{nameValuePair.Key})", nameValuePair.Value); + theString = theString.Replace($"$({nameValuePair.Key})", nameValuePair.Value); } return theString; @@ -248,6 +295,18 @@ private string ReplaceValueWithHelperFile(string theString, string placeholder, : theString.Replace(placeholder, value); } + private void CheckForRemainingPlaceholders(string theString, string optionName) + { + var matches = PlaceholdersRegex.Matches(theString); + if (matches.Count > 0) + { + + var placeholders = matches.Cast().Select(m => m.Value).Distinct().OrderBy(s => s); + string message = $"Option '{optionName}': Apparently, the following placeholders could not be replaced. {string.Join(", ", placeholders)}"; + _logger.LogWarning(message); + } + } + } } \ No newline at end of file diff --git a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs index 9ae4255e0..3baf762f9 100644 --- a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs +++ b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs @@ -25,8 +25,8 @@ public HelperFilesCache HelperFilesCache private get { return _cache; } set { - _cache = value; - _placeholderReplacer = new PlaceholderReplacer(() => SolutionDir, () => _currentSettings, HelperFilesCache); + _cache = value ?? throw new ArgumentNullException(nameof(HelperFilesCache)); + _placeholderReplacer = new PlaceholderReplacer(() => SolutionDir, () => _currentSettings, HelperFilesCache, HelperFilesCache.Logger); } } @@ -362,7 +362,7 @@ public string GetUserParametersForDiscovery(string executable) public virtual string BatchForTestSetup => _currentSettings.BatchForTestSetup ?? OptionBatchForTestSetupDefaultValue; public string GetBatchForTestSetup(string testDirectory, int threadId) - => _placeholderReplacer.ReplaceBatchPlaceholders(BatchForTestSetup, testDirectory, threadId); + => _placeholderReplacer.ReplaceSetupBatchPlaceholders(BatchForTestSetup, testDirectory, threadId); public const string OptionBatchForTestTeardown = "Test teardown batch file"; @@ -373,7 +373,7 @@ public string GetBatchForTestSetup(string testDirectory, int threadId) public virtual string BatchForTestTeardown => _currentSettings.BatchForTestTeardown ?? OptionBatchForTestTeardownDefaultValue; public string GetBatchForTestTeardown(string testDirectory, int threadId) - => _placeholderReplacer.ReplaceBatchPlaceholders(BatchForTestTeardown, testDirectory, + => _placeholderReplacer.ReplaceTeardownBatchPlaceholders(BatchForTestTeardown, testDirectory, threadId); diff --git a/GoogleTestAdapter/DiaResolver.Tests/DiaResolverTests.cs b/GoogleTestAdapter/DiaResolver.Tests/DiaResolverTests.cs index 752cd4dd4..2b7889c35 100644 --- a/GoogleTestAdapter/DiaResolver.Tests/DiaResolverTests.cs +++ b/GoogleTestAdapter/DiaResolver.Tests/DiaResolverTests.cs @@ -114,7 +114,7 @@ private void DoResolveTest(string executable, string filter, int expectedLocatio } locations.Should().HaveCountGreaterOrEqualTo(expectedLocations); - fakeLogger.GetMessages(Severity.Warning, Severity.Error).Count.Should().BeGreaterOrEqualTo(expectedErrorMessages); + fakeLogger.GetMessages(Severity.Warning, Severity.Error).Should().HaveCountGreaterOrEqualTo(expectedErrorMessages); } } diff --git a/GoogleTestAdapter/GoogleTestAdapter.sln b/GoogleTestAdapter/GoogleTestAdapter.sln index dfee3be1c..1f80df367 100644 --- a/GoogleTestAdapter/GoogleTestAdapter.sln +++ b/GoogleTestAdapter/GoogleTestAdapter.sln @@ -155,6 +155,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Donations", "Donations", "{ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LeakCheckTests", "..\SampleTests\LeakCheckTests\LeakCheckTests.vcxproj", "{41791F46-44CF-459B-9F77-049CE1C9D203}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HelperFileTests", "..\SampleTests\HelperFileTests\HelperFileTests.vcxproj", "{034E4479-F9C0-435B-AE6C-96109DE161AB}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution VsPackage.Shared\VsPackage.Shared.projitems*{ac75f34e-190b-402a-8c46-91b0fa02450f}*SharedItemsImports = 13 @@ -539,6 +541,16 @@ Global {41791F46-44CF-459B-9F77-049CE1C9D203}.Release|x64.Build.0 = Release|x64 {41791F46-44CF-459B-9F77-049CE1C9D203}.Release|x86.ActiveCfg = Release|Win32 {41791F46-44CF-459B-9F77-049CE1C9D203}.Release|x86.Build.0 = Release|Win32 + {034E4479-F9C0-435B-AE6C-96109DE161AB}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {034E4479-F9C0-435B-AE6C-96109DE161AB}.Debug|x64.ActiveCfg = Debug|x64 + {034E4479-F9C0-435B-AE6C-96109DE161AB}.Debug|x64.Build.0 = Debug|x64 + {034E4479-F9C0-435B-AE6C-96109DE161AB}.Debug|x86.ActiveCfg = Debug|Win32 + {034E4479-F9C0-435B-AE6C-96109DE161AB}.Debug|x86.Build.0 = Debug|Win32 + {034E4479-F9C0-435B-AE6C-96109DE161AB}.Release|Any CPU.ActiveCfg = Release|Win32 + {034E4479-F9C0-435B-AE6C-96109DE161AB}.Release|x64.ActiveCfg = Release|x64 + {034E4479-F9C0-435B-AE6C-96109DE161AB}.Release|x64.Build.0 = Release|x64 + {034E4479-F9C0-435B-AE6C-96109DE161AB}.Release|x86.ActiveCfg = Release|Win32 + {034E4479-F9C0-435B-AE6C-96109DE161AB}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -576,6 +588,7 @@ Global {883EFE71-6B36-4813-B1DB-80D9B972B8D5} = {1F754A4D-BD42-4368-8B90-F3C03F24A2F3} {58B6EF41-D226-40A9-A959-0543270D572F} = {883EFE71-6B36-4813-B1DB-80D9B972B8D5} {41791F46-44CF-459B-9F77-049CE1C9D203} = {1FF56AF6-0ACE-4FE8-B802-4832703EC2DC} + {034E4479-F9C0-435B-AE6C-96109DE161AB} = {1FF56AF6-0ACE-4FE8-B802-4832703EC2DC} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C942DDD5-B04E-4D57-BA9F-A444392C9480} diff --git a/GoogleTestAdapter/TestAdapter.Tests/Settings/HelperFileTests.cs b/GoogleTestAdapter/TestAdapter.Tests/Settings/HelperFileTests.cs new file mode 100644 index 000000000..c14e86d88 --- /dev/null +++ b/GoogleTestAdapter/TestAdapter.Tests/Settings/HelperFileTests.cs @@ -0,0 +1,61 @@ +using System.Linq; +using GoogleTestAdapter.Helpers; +using GoogleTestAdapter.ProcessExecution; +using GoogleTestAdapter.TestAdapter.ProcessExecution; +using GoogleTestAdapter.Tests.Common; +using Microsoft.VisualStudio.TestPlatform.ObjectModel; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using static GoogleTestAdapter.Tests.Common.TestMetadata.TestCategories; + + +namespace GoogleTestAdapter.TestAdapter.Settings +{ + [TestClass] + public class HelperFileTests : TestAdapterTestsBase + { + private readonly Mock _mockDebuggerAttacher = new Mock(); + + [TestInitialize] + public override void SetUp() + { + base.SetUp(); + + _mockDebuggerAttacher.Reset(); + _mockDebuggerAttacher.Setup(a => a.AttachDebugger(It.IsAny())).Returns(true); + } + + [TestMethod] + [TestCategory(Integration)] + public void HelperFileTests_AdditionalParamsAreNotProvided_TestFails() + { + RunHelperFileTestsExecutable(); + + MockFrameworkHandle.Verify(h => h.RecordResult(It.Is(tr => + tr.DisplayName.Contains("HelperFileTests.ArchDirIsSet") && + tr.Outcome == TestOutcome.Failed)), Times.Once); + } + + [TestMethod] + [TestCategory(Integration)] + public void HelperFileTests_AdditionalParamsAreProvided_TestSucceeds() + { + MockOptions.Setup(o => o.AdditionalTestExecutionParam).Returns("$(LocalDebuggerCommandArguments)"); + + RunHelperFileTestsExecutable(); + + MockFrameworkHandle.Verify(h => h.RecordResult(It.Is(tr => + tr.DisplayName.Contains("HelperFileTests.ArchDirIsSet") && + tr.Outcome == TestOutcome.Passed)), Times.Once); + } + + private void RunHelperFileTestsExecutable() + { + var testCase = new GoogleTestDiscoverer(MockLogger.Object, TestEnvironment.Options, new ProcessExecutorFactory()) + .GetTestsFromExecutable(TestResources.HelperFilesTests_ReleaseX86).Single(); + var executor = + new TestExecutor(TestEnvironment.Logger, TestEnvironment.Options, _mockDebuggerAttacher.Object); + executor.RunTests(testCase.ToVsTestCase().Yield(), MockRunContext.Object, MockFrameworkHandle.Object); + } + } +} \ No newline at end of file diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj b/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj index 284b7640e..cd0415a01 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj +++ b/GoogleTestAdapter/TestAdapter.Tests/TestAdapter.Tests.csproj @@ -101,6 +101,7 @@ + diff --git a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs index 512a39daa..c00173543 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/TestExecutorTestsBase.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Configuration; using System.IO; using System.Linq; using FluentAssertions; diff --git a/GoogleTestAdapter/Tests.Common/TestResources.cs b/GoogleTestAdapter/Tests.Common/TestResources.cs index 2b844d6c0..22448dd70 100644 --- a/GoogleTestAdapter/Tests.Common/TestResources.cs +++ b/GoogleTestAdapter/Tests.Common/TestResources.cs @@ -64,6 +64,9 @@ public static class TestResources public const string LeakCheckTests_DebugX86 = SampleTestsBuildDir + @"Debug\LeakCheckTests_gta.exe"; public const string LeakCheckTests_ReleaseX86 = SampleTestsBuildDir + @"Release\LeakCheckTests_gta.exe"; + public const string HelperFileTests_DebugX86 = SampleTestsBuildDir + @"Debug\HelperFileTests_gta.exe"; + public const string HelperFilesTests_ReleaseX86 = SampleTestsBuildDir + @"Release\HelperFileTests_gta.exe"; + public const string SucceedingBatch = @"Tests\Returns0.bat"; public const string FailingBatch = @"Tests\Returns1.bat"; diff --git a/README.md b/README.md index cfdf8e75c..e6158d690 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,11 @@ Note that due to the overriding hierarchy described above, you probably want to For reference, see a settings file [AllTestSettings.gta.runsettings](https://raw.githubusercontent.com/csoltenborn/GoogleTestAdapter/master/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings) containing all available settings, a more realistic solution settings file [SampleTests.gta.runsettings](https://raw.githubusercontent.com/csoltenborn/GoogleTestAdapter/master/SampleTests/SampleTests.gta.runsettings) as delivered with the SampleTests solution, and a user settings file [NonDeterministic.runsettings](https://raw.githubusercontent.com/csoltenborn/GoogleTestAdapter/master/SampleTests/NonDeterministic.runsettings) as used by GTA's end-to-end tests. The syntax of the GTA settings files (excluding the `` node) is specified by [this schema](https://raw.githubusercontent.com/csoltenborn/GoogleTestAdapter/master/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd). +##### GTA helper files +GTA does not provide direct access to VS project settings such as *Project* > *Properties* > *Debugging* > *Environment*. Additionally, when run as NuGet dependency, GTA does not have access to information such as solution dir or Platform/Configuration a test executable has been build with. + +To overcome these problems, GTA supports so-called *helper files* which provide that information to GTA. + #### Assigning traits to tests diff --git a/SampleTests/HelperFileTests/HelperFileTests.cpp b/SampleTests/HelperFileTests/HelperFileTests.cpp new file mode 100644 index 000000000..662009e14 --- /dev/null +++ b/SampleTests/HelperFileTests/HelperFileTests.cpp @@ -0,0 +1,8 @@ +#include "gtest/gtest.h" + +extern std::string ARCH_DIR; + +TEST(HelperFileTests, ArchDirIsSet) +{ + ASSERT_STRNE("", ARCH_DIR.c_str()); +} \ No newline at end of file diff --git a/SampleTests/HelperFileTests/HelperFileTests.vcxproj b/SampleTests/HelperFileTests/HelperFileTests.vcxproj new file mode 100644 index 000000000..c05f1a962 --- /dev/null +++ b/SampleTests/HelperFileTests/HelperFileTests.vcxproj @@ -0,0 +1,214 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + 15.0 + {034E4479-F9C0-435B-AE6C-96109DE161AB} + Win32Proj + HelperFileTests + 8.1 + + + + + Application + true + v100 + v110 + v120 + v140 + v141 + v142 + Unicode + + + Application + false + v100 + v110 + v120 + v140 + v141 + v142 + true + Unicode + + + Application + true + v100 + v110 + v120 + v140 + v141 + v142 + Unicode + + + Application + false + v100 + v110 + v120 + v140 + v141 + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + $(ProjectName)_gta + $(EnlistmentRoot)out\binaries\$(SolutionName)\$(Configuration)$(PlatformSuffix)\ + $(EnlistmentRoot)out\intermediate\$(SolutionName)\$(Configuration)\$(MSBuildProjectName)\ + + + true + $(ProjectName)_gta + $(EnlistmentRoot)out\binaries\$(SolutionName)\$(Configuration)$(PlatformSuffix)\ + $(EnlistmentRoot)out\intermediate\$(SolutionName)\$(Configuration)\$(MSBuildProjectName)\ + + + false + $(ProjectName)_gta + $(EnlistmentRoot)out\binaries\$(SolutionName)\$(Configuration)$(PlatformSuffix)\ + $(EnlistmentRoot)out\intermediate\$(SolutionName)\$(Configuration)\$(MSBuildProjectName)\ + + + false + $(ProjectName)_gta + $(EnlistmentRoot)out\binaries\$(SolutionName)\$(Configuration)$(PlatformSuffix)\ + $(EnlistmentRoot)out\intermediate\$(SolutionName)\$(Configuration)\$(MSBuildProjectName)\ + + + + NotUsing + Level3 + Disabled + true + _VARIADIC_MAX=10;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + false + pch.h + $(ProjectDir)..\3rdparty\gtest-1.8.1\fused-src;%(AdditionalIncludeDirectories) + + + Console + DebugFull + true + + + echo SolutionPath=$(SolutionPath)::GTA::SolutionDir=$(SolutionDir)::GTA::PlatformName=$(PlatformName)::GTA::ConfigurationName=$(ConfigurationName)::GTA::LocalDebuggerCommandArguments=$(LocalDebuggerCommandArguments) > $(TargetPath).gta_settings_helper + + + + + NotUsing + Level3 + Disabled + true + _VARIADIC_MAX=10;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + false + pch.h + $(ProjectDir)..\3rdparty\gtest-1.8.1\fused-src;%(AdditionalIncludeDirectories) + + + Console + DebugFull + true + + + echo SolutionPath=$(SolutionPath)::GTA::SolutionDir=$(SolutionDir)::GTA::PlatformName=$(PlatformName)::GTA::ConfigurationName=$(ConfigurationName)::GTA::LocalDebuggerCommandArguments=$(LocalDebuggerCommandArguments) > $(TargetPath).gta_settings_helper + + + + + NotUsing + Level3 + MaxSpeed + true + true + true + _VARIADIC_MAX=10;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + false + pch.h + $(ProjectDir)..\3rdparty\gtest-1.8.1\fused-src;%(AdditionalIncludeDirectories) + + + Console + true + true + DebugFull + true + + + echo SolutionPath=$(SolutionPath)::GTA::SolutionDir=$(SolutionDir)::GTA::PlatformName=$(PlatformName)::GTA::ConfigurationName=$(ConfigurationName)::GTA::LocalDebuggerCommandArguments=$(LocalDebuggerCommandArguments) > $(TargetPath).gta_settings_helper + + + + + NotUsing + Level3 + MaxSpeed + true + true + true + _VARIADIC_MAX=10;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + false + pch.h + $(ProjectDir)..\3rdparty\gtest-1.8.1\fused-src;%(AdditionalIncludeDirectories) + + + Console + true + true + DebugFull + true + + + echo SolutionPath=$(SolutionPath)::GTA::SolutionDir=$(SolutionDir)::GTA::PlatformName=$(PlatformName)::GTA::ConfigurationName=$(ConfigurationName)::GTA::LocalDebuggerCommandArguments=$(LocalDebuggerCommandArguments) > $(TargetPath).gta_settings_helper + + + + + + \ No newline at end of file diff --git a/SampleTests/HelperFileTests/HelperFileTests.vcxproj.filters b/SampleTests/HelperFileTests/HelperFileTests.vcxproj.filters new file mode 100644 index 000000000..3874ce680 --- /dev/null +++ b/SampleTests/HelperFileTests/HelperFileTests.vcxproj.filters @@ -0,0 +1,28 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Quelldateien + + + Quelldateien + + + Quelldateien + + + \ No newline at end of file diff --git a/SampleTests/HelperFileTests/Main.cpp b/SampleTests/HelperFileTests/Main.cpp new file mode 100644 index 000000000..56c205059 --- /dev/null +++ b/SampleTests/HelperFileTests/Main.cpp @@ -0,0 +1,22 @@ +#include "string.h" +#include "gtest/gtest.h" + +std::string ARCH_DIR; + +int main(int argc, char ** argv) +{ + std::string prefix_arch_dir("-arch_dir="); + + for (int i = 0; i < argc; i++) + { + if (strncmp(argv[i], prefix_arch_dir.c_str(), strlen(prefix_arch_dir.c_str())) == 0) + { + std::string arch_dir(argv[i]); + arch_dir.erase(0, strlen(prefix_arch_dir.c_str())); + ARCH_DIR = arch_dir; + } + } + + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/SampleTests/LeakCheckTests/LeakCheckTests.vcxproj b/SampleTests/LeakCheckTests/LeakCheckTests.vcxproj index cf7bfb250..ba4065f17 100644 --- a/SampleTests/LeakCheckTests/LeakCheckTests.vcxproj +++ b/SampleTests/LeakCheckTests/LeakCheckTests.vcxproj @@ -30,26 +30,30 @@ Application true - v141 + v141 + v142 Unicode Application false - v141 + v141 + v142 true Unicode Application true - v141 + v141 + v142 Unicode Application false - v141 + v141 + v142 true Unicode diff --git a/SampleTests/SampleTests.gta.runsettings b/SampleTests/SampleTests.gta.runsettings index c17fd267d..c72947290 100644 --- a/SampleTests/SampleTests.gta.runsettings +++ b/SampleTests/SampleTests.gta.runsettings @@ -1,25 +1,28 @@ - - - - -testdirectory=$(TestDir) - $(SolutionDir)Tests\Returns0.bat - $(SolutionDir)Tests\Returns1.bat - $(SolutionDir) - - - - - .*Tests.*_gta.exe - - - 60 - - - MemoryLeakTest - -is_run_by_gta - - - + + + + -testdirectory=$(TestDir) + $(SolutionDir)Tests\Returns0.bat + $(SolutionDir)Tests\Returns1.bat + $(SolutionDir) + + + + + .*Tests.*_gta.exe + + + 60 + + + MemoryLeakTest + -is_run_by_gta + + + $(LocalDebuggerCommandArguments) + + + \ No newline at end of file diff --git a/SampleTests/SampleTests.sln b/SampleTests/SampleTests.sln index 18b43f429..a6fc63617 100644 --- a/SampleTests/SampleTests.sln +++ b/SampleTests/SampleTests.sln @@ -33,6 +33,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DllProject", "DllProject\Dl EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LeakCheckTests", "LeakCheckTests\LeakCheckTests.vcxproj", "{41791F46-44CF-459B-9F77-049CE1C9D203}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HelperFileTests", "HelperFileTests\HelperFileTests.vcxproj", "{034E4479-F9C0-435B-AE6C-96109DE161AB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -133,6 +135,16 @@ Global {41791F46-44CF-459B-9F77-049CE1C9D203}.Release|Win32.Build.0 = Release|Win32 {41791F46-44CF-459B-9F77-049CE1C9D203}.Release|x64.ActiveCfg = Release|x64 {41791F46-44CF-459B-9F77-049CE1C9D203}.Release|x64.Build.0 = Release|x64 + {034E4479-F9C0-435B-AE6C-96109DE161AB}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {034E4479-F9C0-435B-AE6C-96109DE161AB}.Debug|Win32.ActiveCfg = Debug|Win32 + {034E4479-F9C0-435B-AE6C-96109DE161AB}.Debug|Win32.Build.0 = Debug|Win32 + {034E4479-F9C0-435B-AE6C-96109DE161AB}.Debug|x64.ActiveCfg = Debug|x64 + {034E4479-F9C0-435B-AE6C-96109DE161AB}.Debug|x64.Build.0 = Debug|x64 + {034E4479-F9C0-435B-AE6C-96109DE161AB}.Release|Any CPU.ActiveCfg = Release|Win32 + {034E4479-F9C0-435B-AE6C-96109DE161AB}.Release|Win32.ActiveCfg = Release|Win32 + {034E4479-F9C0-435B-AE6C-96109DE161AB}.Release|Win32.Build.0 = Release|Win32 + {034E4479-F9C0-435B-AE6C-96109DE161AB}.Release|x64.ActiveCfg = Release|x64 + {034E4479-F9C0-435B-AE6C-96109DE161AB}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 484e6a54363837e47fd57957a7937463ec669a5b Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Wed, 17 Apr 2019 07:14:01 +0200 Subject: [PATCH 70/81] debugging test fail --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 51bd6dfbe..adc1ceef9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,7 +12,7 @@ install: nuget install secure-file -ExcludeVersion NuGetPackages\secure-file\tools\secure-file -decrypt GoogleTestAdapter\Keys\Key_Release.snk.enc -secret $env:RELEASE_KEY_PASSWORD } else { - # $blockRdp = $true + $blockRdp = $true iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) } before_build: From 9d0f6a6a83d05b27d1e9111cc172e42511041efe Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Wed, 17 Apr 2019 07:51:34 +0200 Subject: [PATCH 71/81] fixed test for CI setting --- .../TestAdapter.Tests/Settings/HelperFileTests.cs | 6 +++--- SampleTests/HelperFileTests/HelperFileTests.cpp | 6 +++--- SampleTests/HelperFileTests/HelperFileTests.vcxproj | 8 ++++---- SampleTests/HelperFileTests/Main.cpp | 7 ++++--- SampleTests/SampleTests.gta.runsettings | 2 +- appveyor.yml | 2 +- 6 files changed, 16 insertions(+), 15 deletions(-) diff --git a/GoogleTestAdapter/TestAdapter.Tests/Settings/HelperFileTests.cs b/GoogleTestAdapter/TestAdapter.Tests/Settings/HelperFileTests.cs index c14e86d88..2bc61ee8c 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/Settings/HelperFileTests.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/Settings/HelperFileTests.cs @@ -32,7 +32,7 @@ public void HelperFileTests_AdditionalParamsAreNotProvided_TestFails() RunHelperFileTestsExecutable(); MockFrameworkHandle.Verify(h => h.RecordResult(It.Is(tr => - tr.DisplayName.Contains("HelperFileTests.ArchDirIsSet") && + tr.DisplayName.Contains("HelperFileTests.TheTargetIsSet") && tr.Outcome == TestOutcome.Failed)), Times.Once); } @@ -40,12 +40,12 @@ public void HelperFileTests_AdditionalParamsAreNotProvided_TestFails() [TestCategory(Integration)] public void HelperFileTests_AdditionalParamsAreProvided_TestSucceeds() { - MockOptions.Setup(o => o.AdditionalTestExecutionParam).Returns("$(LocalDebuggerCommandArguments)"); + MockOptions.Setup(o => o.AdditionalTestExecutionParam).Returns("-TheTarget=$(TheTarget)"); RunHelperFileTestsExecutable(); MockFrameworkHandle.Verify(h => h.RecordResult(It.Is(tr => - tr.DisplayName.Contains("HelperFileTests.ArchDirIsSet") && + tr.DisplayName.Contains("HelperFileTests.TheTargetIsSet") && tr.Outcome == TestOutcome.Passed)), Times.Once); } diff --git a/SampleTests/HelperFileTests/HelperFileTests.cpp b/SampleTests/HelperFileTests/HelperFileTests.cpp index 662009e14..2aa21c38a 100644 --- a/SampleTests/HelperFileTests/HelperFileTests.cpp +++ b/SampleTests/HelperFileTests/HelperFileTests.cpp @@ -1,8 +1,8 @@ #include "gtest/gtest.h" -extern std::string ARCH_DIR; +extern std::string THE_TARGET; -TEST(HelperFileTests, ArchDirIsSet) +TEST(HelperFileTests, TheTargetIsSet) { - ASSERT_STRNE("", ARCH_DIR.c_str()); + ASSERT_STREQ("HelperFileTests_gta.exe", THE_TARGET.c_str()); } \ No newline at end of file diff --git a/SampleTests/HelperFileTests/HelperFileTests.vcxproj b/SampleTests/HelperFileTests/HelperFileTests.vcxproj index c05f1a962..d1c529b87 100644 --- a/SampleTests/HelperFileTests/HelperFileTests.vcxproj +++ b/SampleTests/HelperFileTests/HelperFileTests.vcxproj @@ -137,7 +137,7 @@ true - echo SolutionPath=$(SolutionPath)::GTA::SolutionDir=$(SolutionDir)::GTA::PlatformName=$(PlatformName)::GTA::ConfigurationName=$(ConfigurationName)::GTA::LocalDebuggerCommandArguments=$(LocalDebuggerCommandArguments) > $(TargetPath).gta_settings_helper + echo SolutionPath=$(SolutionPath)::GTA::SolutionDir=$(SolutionDir)::GTA::PlatformName=$(PlatformName)::GTA::ConfigurationName=$(ConfigurationName)::GTA::TheTarget=$(TargetFileName) > $(TargetPath).gta_settings_helper @@ -157,7 +157,7 @@ true - echo SolutionPath=$(SolutionPath)::GTA::SolutionDir=$(SolutionDir)::GTA::PlatformName=$(PlatformName)::GTA::ConfigurationName=$(ConfigurationName)::GTA::LocalDebuggerCommandArguments=$(LocalDebuggerCommandArguments) > $(TargetPath).gta_settings_helper + echo SolutionPath=$(SolutionPath)::GTA::SolutionDir=$(SolutionDir)::GTA::PlatformName=$(PlatformName)::GTA::ConfigurationName=$(ConfigurationName)::GTA::TheTarget=$(TargetFileName) > $(TargetPath).gta_settings_helper @@ -181,7 +181,7 @@ true - echo SolutionPath=$(SolutionPath)::GTA::SolutionDir=$(SolutionDir)::GTA::PlatformName=$(PlatformName)::GTA::ConfigurationName=$(ConfigurationName)::GTA::LocalDebuggerCommandArguments=$(LocalDebuggerCommandArguments) > $(TargetPath).gta_settings_helper + echo SolutionPath=$(SolutionPath)::GTA::SolutionDir=$(SolutionDir)::GTA::PlatformName=$(PlatformName)::GTA::ConfigurationName=$(ConfigurationName)::GTA::TheTarget=$(TargetFileName) > $(TargetPath).gta_settings_helper @@ -205,7 +205,7 @@ true - echo SolutionPath=$(SolutionPath)::GTA::SolutionDir=$(SolutionDir)::GTA::PlatformName=$(PlatformName)::GTA::ConfigurationName=$(ConfigurationName)::GTA::LocalDebuggerCommandArguments=$(LocalDebuggerCommandArguments) > $(TargetPath).gta_settings_helper + echo SolutionPath=$(SolutionPath)::GTA::SolutionDir=$(SolutionDir)::GTA::PlatformName=$(PlatformName)::GTA::ConfigurationName=$(ConfigurationName)::GTA::TheTarget=$(TargetFileName) > $(TargetPath).gta_settings_helper diff --git a/SampleTests/HelperFileTests/Main.cpp b/SampleTests/HelperFileTests/Main.cpp index 56c205059..d4de2e593 100644 --- a/SampleTests/HelperFileTests/Main.cpp +++ b/SampleTests/HelperFileTests/Main.cpp @@ -1,19 +1,20 @@ #include "string.h" #include "gtest/gtest.h" -std::string ARCH_DIR; +std::string THE_TARGET; int main(int argc, char ** argv) { - std::string prefix_arch_dir("-arch_dir="); + std::string prefix_arch_dir("-TheTarget="); for (int i = 0; i < argc; i++) { + std::string s = argv[i]; if (strncmp(argv[i], prefix_arch_dir.c_str(), strlen(prefix_arch_dir.c_str())) == 0) { std::string arch_dir(argv[i]); arch_dir.erase(0, strlen(prefix_arch_dir.c_str())); - ARCH_DIR = arch_dir; + THE_TARGET = arch_dir; } } diff --git a/SampleTests/SampleTests.gta.runsettings b/SampleTests/SampleTests.gta.runsettings index c72947290..4923c6269 100644 --- a/SampleTests/SampleTests.gta.runsettings +++ b/SampleTests/SampleTests.gta.runsettings @@ -21,7 +21,7 @@ -is_run_by_gta - $(LocalDebuggerCommandArguments) + -TheTarget=$(TheTarget) diff --git a/appveyor.yml b/appveyor.yml index adc1ceef9..51bd6dfbe 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,7 +12,7 @@ install: nuget install secure-file -ExcludeVersion NuGetPackages\secure-file\tools\secure-file -decrypt GoogleTestAdapter\Keys\Key_Release.snk.enc -secret $env:RELEASE_KEY_PASSWORD } else { - $blockRdp = $true + # $blockRdp = $true iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) } before_build: From 94e7c3107db19356714494d8c5004f0881a15a3c Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Thu, 18 Apr 2019 16:50:31 +0200 Subject: [PATCH 72/81] added clr projects for testing and debugging --- GoogleTestAdapter/GoogleTestAdapter.sln | 41 ++++ .../Debugging/VsDebuggerAttacher.cs | 2 +- .../ClrDotNetLibProject.csproj | 51 +++++ .../ClrDotNetLibProject/DotNetClass.cs | 11 + .../Properties/AssemblyInfo.cs | 36 ++++ SampleTests/ClrLibProject/AssemblyInfo.cpp | 22 ++ SampleTests/ClrLibProject/ClrLibProject.cpp | 11 + SampleTests/ClrLibProject/ClrLibProject.h | 9 + .../ClrLibProject/ClrLibProject.vcxproj | 185 ++++++++++++++++ .../ClrLibProject.vcxproj.filters | 49 +++++ SampleTests/ClrLibProject/Resource.h | 3 + SampleTests/ClrLibProject/app.ico | Bin 0 -> 41395 bytes SampleTests/ClrLibProject/app.rc | Bin 0 -> 2556 bytes SampleTests/ClrLibProject/stdafx.cpp | 1 + SampleTests/ClrLibProject/stdafx.h | 1 + SampleTests/ClrTests/ClrTests.cpp | 14 ++ SampleTests/ClrTests/ClrTests.vcxproj | 203 ++++++++++++++++++ SampleTests/ClrTests/ClrTests.vcxproj.filters | 28 +++ SampleTests/ClrTests/Main.cpp | 7 + SampleTests/SampleTests.sln | 38 ++++ 20 files changed, 711 insertions(+), 1 deletion(-) create mode 100644 SampleTests/ClrDotNetLibProject/ClrDotNetLibProject.csproj create mode 100644 SampleTests/ClrDotNetLibProject/DotNetClass.cs create mode 100644 SampleTests/ClrDotNetLibProject/Properties/AssemblyInfo.cs create mode 100644 SampleTests/ClrLibProject/AssemblyInfo.cpp create mode 100644 SampleTests/ClrLibProject/ClrLibProject.cpp create mode 100644 SampleTests/ClrLibProject/ClrLibProject.h create mode 100644 SampleTests/ClrLibProject/ClrLibProject.vcxproj create mode 100644 SampleTests/ClrLibProject/ClrLibProject.vcxproj.filters create mode 100644 SampleTests/ClrLibProject/Resource.h create mode 100644 SampleTests/ClrLibProject/app.ico create mode 100644 SampleTests/ClrLibProject/app.rc create mode 100644 SampleTests/ClrLibProject/stdafx.cpp create mode 100644 SampleTests/ClrLibProject/stdafx.h create mode 100644 SampleTests/ClrTests/ClrTests.cpp create mode 100644 SampleTests/ClrTests/ClrTests.vcxproj create mode 100644 SampleTests/ClrTests/ClrTests.vcxproj.filters create mode 100644 SampleTests/ClrTests/Main.cpp diff --git a/GoogleTestAdapter/GoogleTestAdapter.sln b/GoogleTestAdapter/GoogleTestAdapter.sln index dfee3be1c..949a3e0ff 100644 --- a/GoogleTestAdapter/GoogleTestAdapter.sln +++ b/GoogleTestAdapter/GoogleTestAdapter.sln @@ -155,6 +155,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Donations", "Donations", "{ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LeakCheckTests", "..\SampleTests\LeakCheckTests\LeakCheckTests.vcxproj", "{41791F46-44CF-459B-9F77-049CE1C9D203}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClrDotNetLibProject", "..\SampleTests\ClrDotNetLibProject\ClrDotNetLibProject.csproj", "{8EB74B67-3B52-4734-875B-F3F27EA55FC9}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClrLibProject", "..\SampleTests\ClrLibProject\ClrLibProject.vcxproj", "{4438C703-36A0-46FB-806C-90E2C6DE9359}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClrTests", "..\SampleTests\ClrTests\ClrTests.vcxproj", "{E1CE3891-E39B-48C7-ABF6-ACDC3C06C4F7}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution VsPackage.Shared\VsPackage.Shared.projitems*{ac75f34e-190b-402a-8c46-91b0fa02450f}*SharedItemsImports = 13 @@ -539,6 +545,38 @@ Global {41791F46-44CF-459B-9F77-049CE1C9D203}.Release|x64.Build.0 = Release|x64 {41791F46-44CF-459B-9F77-049CE1C9D203}.Release|x86.ActiveCfg = Release|Win32 {41791F46-44CF-459B-9F77-049CE1C9D203}.Release|x86.Build.0 = Release|Win32 + {8EB74B67-3B52-4734-875B-F3F27EA55FC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8EB74B67-3B52-4734-875B-F3F27EA55FC9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8EB74B67-3B52-4734-875B-F3F27EA55FC9}.Debug|x64.ActiveCfg = Debug|Any CPU + {8EB74B67-3B52-4734-875B-F3F27EA55FC9}.Debug|x64.Build.0 = Debug|Any CPU + {8EB74B67-3B52-4734-875B-F3F27EA55FC9}.Debug|x86.ActiveCfg = Debug|Win32 + {8EB74B67-3B52-4734-875B-F3F27EA55FC9}.Debug|x86.Build.0 = Debug|Win32 + {8EB74B67-3B52-4734-875B-F3F27EA55FC9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8EB74B67-3B52-4734-875B-F3F27EA55FC9}.Release|Any CPU.Build.0 = Release|Any CPU + {8EB74B67-3B52-4734-875B-F3F27EA55FC9}.Release|x64.ActiveCfg = Release|Any CPU + {8EB74B67-3B52-4734-875B-F3F27EA55FC9}.Release|x64.Build.0 = Release|Any CPU + {8EB74B67-3B52-4734-875B-F3F27EA55FC9}.Release|x86.ActiveCfg = Release|Win32 + {8EB74B67-3B52-4734-875B-F3F27EA55FC9}.Release|x86.Build.0 = Release|Win32 + {4438C703-36A0-46FB-806C-90E2C6DE9359}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {4438C703-36A0-46FB-806C-90E2C6DE9359}.Debug|x64.ActiveCfg = Debug|x64 + {4438C703-36A0-46FB-806C-90E2C6DE9359}.Debug|x64.Build.0 = Debug|x64 + {4438C703-36A0-46FB-806C-90E2C6DE9359}.Debug|x86.ActiveCfg = Debug|Win32 + {4438C703-36A0-46FB-806C-90E2C6DE9359}.Debug|x86.Build.0 = Debug|Win32 + {4438C703-36A0-46FB-806C-90E2C6DE9359}.Release|Any CPU.ActiveCfg = Release|Win32 + {4438C703-36A0-46FB-806C-90E2C6DE9359}.Release|x64.ActiveCfg = Release|x64 + {4438C703-36A0-46FB-806C-90E2C6DE9359}.Release|x64.Build.0 = Release|x64 + {4438C703-36A0-46FB-806C-90E2C6DE9359}.Release|x86.ActiveCfg = Release|Win32 + {4438C703-36A0-46FB-806C-90E2C6DE9359}.Release|x86.Build.0 = Release|Win32 + {E1CE3891-E39B-48C7-ABF6-ACDC3C06C4F7}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {E1CE3891-E39B-48C7-ABF6-ACDC3C06C4F7}.Debug|x64.ActiveCfg = Debug|x64 + {E1CE3891-E39B-48C7-ABF6-ACDC3C06C4F7}.Debug|x64.Build.0 = Debug|x64 + {E1CE3891-E39B-48C7-ABF6-ACDC3C06C4F7}.Debug|x86.ActiveCfg = Debug|Win32 + {E1CE3891-E39B-48C7-ABF6-ACDC3C06C4F7}.Debug|x86.Build.0 = Debug|Win32 + {E1CE3891-E39B-48C7-ABF6-ACDC3C06C4F7}.Release|Any CPU.ActiveCfg = Release|Win32 + {E1CE3891-E39B-48C7-ABF6-ACDC3C06C4F7}.Release|x64.ActiveCfg = Release|x64 + {E1CE3891-E39B-48C7-ABF6-ACDC3C06C4F7}.Release|x64.Build.0 = Release|x64 + {E1CE3891-E39B-48C7-ABF6-ACDC3C06C4F7}.Release|x86.ActiveCfg = Release|Win32 + {E1CE3891-E39B-48C7-ABF6-ACDC3C06C4F7}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -576,6 +614,9 @@ Global {883EFE71-6B36-4813-B1DB-80D9B972B8D5} = {1F754A4D-BD42-4368-8B90-F3C03F24A2F3} {58B6EF41-D226-40A9-A959-0543270D572F} = {883EFE71-6B36-4813-B1DB-80D9B972B8D5} {41791F46-44CF-459B-9F77-049CE1C9D203} = {1FF56AF6-0ACE-4FE8-B802-4832703EC2DC} + {8EB74B67-3B52-4734-875B-F3F27EA55FC9} = {1FF56AF6-0ACE-4FE8-B802-4832703EC2DC} + {4438C703-36A0-46FB-806C-90E2C6DE9359} = {1FF56AF6-0ACE-4FE8-B802-4832703EC2DC} + {E1CE3891-E39B-48C7-ABF6-ACDC3C06C4F7} = {1FF56AF6-0ACE-4FE8-B802-4832703EC2DC} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C942DDD5-B04E-4D57-BA9F-A444392C9480} diff --git a/GoogleTestAdapter/VsPackage.Shared/Debugging/VsDebuggerAttacher.cs b/GoogleTestAdapter/VsPackage.Shared/Debugging/VsDebuggerAttacher.cs index 4f05c5bbb..6b509e72a 100644 --- a/GoogleTestAdapter/VsPackage.Shared/Debugging/VsDebuggerAttacher.cs +++ b/GoogleTestAdapter/VsPackage.Shared/Debugging/VsDebuggerAttacher.cs @@ -32,7 +32,7 @@ public bool AttachDebugger(int processId, DebuggerEngine debuggerEngine) try { Guid debuggerEngineGuid = debuggerEngine == DebuggerEngine.Native - ? VSConstants.DebugEnginesGuids.NativeOnly_guid + ? VSConstants.DebugEnginesGuids.NativeOnly : VSConstants.DebugEnginesGuids.ManagedAndNative; Marshal.StructureToPtr(debuggerEngineGuid, pDebugEngine, false); diff --git a/SampleTests/ClrDotNetLibProject/ClrDotNetLibProject.csproj b/SampleTests/ClrDotNetLibProject/ClrDotNetLibProject.csproj new file mode 100644 index 000000000..521662933 --- /dev/null +++ b/SampleTests/ClrDotNetLibProject/ClrDotNetLibProject.csproj @@ -0,0 +1,51 @@ + + + + + + + Debug + AnyCPU + {8EB74B67-3B52-4734-875B-F3F27EA55FC9} + Library + Properties + ClrDotNetLibProject + ClrDotNetLibProject + v4.6.1 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/SampleTests/ClrDotNetLibProject/DotNetClass.cs b/SampleTests/ClrDotNetLibProject/DotNetClass.cs new file mode 100644 index 000000000..63a89edc6 --- /dev/null +++ b/SampleTests/ClrDotNetLibProject/DotNetClass.cs @@ -0,0 +1,11 @@ +namespace ClrDotNetLibProject +{ + public class DotNetClass + { + public int Add(int a, int b) + { + int result = a + b; + return result; + } + } +} \ No newline at end of file diff --git a/SampleTests/ClrDotNetLibProject/Properties/AssemblyInfo.cs b/SampleTests/ClrDotNetLibProject/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..faf053511 --- /dev/null +++ b/SampleTests/ClrDotNetLibProject/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Allgemeine Informationen über eine Assembly werden über die folgenden +// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +// die einer Assembly zugeordnet sind. +[assembly: AssemblyTitle("ClrDotNetLibProject")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ClrDotNetLibProject")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly +// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von +// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen. +[assembly: ComVisible(false)] + +// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird +[assembly: Guid("8eb74b67-3b52-4734-875b-f3f27ea55fc9")] + +// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +// +// Hauptversion +// Nebenversion +// Buildnummer +// Revision +// +// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, +// indem Sie "*" wie unten gezeigt eingeben: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/SampleTests/ClrLibProject/AssemblyInfo.cpp b/SampleTests/ClrLibProject/AssemblyInfo.cpp new file mode 100644 index 000000000..1aff2b66f --- /dev/null +++ b/SampleTests/ClrLibProject/AssemblyInfo.cpp @@ -0,0 +1,22 @@ +#include "stdafx.h" + +using namespace System; +using namespace System::Reflection; +using namespace System::Runtime::CompilerServices; +using namespace System::Runtime::InteropServices; +using namespace System::Security::Permissions; + +[assembly:AssemblyTitleAttribute(L"ClrLibProject")]; +[assembly:AssemblyDescriptionAttribute(L"")]; +[assembly:AssemblyConfigurationAttribute(L"")]; +[assembly:AssemblyCompanyAttribute(L"")]; +[assembly:AssemblyProductAttribute(L"ClrLibProject")]; +[assembly:AssemblyCopyrightAttribute(L"Copyright (c) 2019")]; +[assembly:AssemblyTrademarkAttribute(L"")]; +[assembly:AssemblyCultureAttribute(L"")]; + +[assembly:AssemblyVersionAttribute("1.0.*")]; + +[assembly:ComVisible(false)]; + +[assembly:CLSCompliantAttribute(true)]; diff --git a/SampleTests/ClrLibProject/ClrLibProject.cpp b/SampleTests/ClrLibProject/ClrLibProject.cpp new file mode 100644 index 000000000..9842930c0 --- /dev/null +++ b/SampleTests/ClrLibProject/ClrLibProject.cpp @@ -0,0 +1,11 @@ +#include "stdafx.h" + +#include "ClrLibProject.h" + +using namespace ClrDotNetLibProject; + +int ClrLibProject::ClrClass::Add(int a, int b) +{ + DotNetClass^ instance = gcnew DotNetClass(); + return instance->Add(a, b); +} \ No newline at end of file diff --git a/SampleTests/ClrLibProject/ClrLibProject.h b/SampleTests/ClrLibProject/ClrLibProject.h new file mode 100644 index 000000000..a268e6579 --- /dev/null +++ b/SampleTests/ClrLibProject/ClrLibProject.h @@ -0,0 +1,9 @@ +#pragma once + +namespace ClrLibProject { + class ClrClass + { + public: + int Add(int a, int b); + }; +} \ No newline at end of file diff --git a/SampleTests/ClrLibProject/ClrLibProject.vcxproj b/SampleTests/ClrLibProject/ClrLibProject.vcxproj new file mode 100644 index 000000000..d266244e2 --- /dev/null +++ b/SampleTests/ClrLibProject/ClrLibProject.vcxproj @@ -0,0 +1,185 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {4438C703-36A0-46FB-806C-90E2C6DE9359} + v4.6.1 + ManagedCProj + ClrLibProject + 10.0.17763.0 + + + + + StaticLibrary + true + v100 + v110 + v120 + v140 + v141 + v142 + true + Unicode + + + StaticLibrary + false + v100 + v110 + v120 + v140 + v141 + v142 + true + Unicode + + + StaticLibrary + true + v100 + v110 + v120 + v140 + v141 + v142 + true + Unicode + + + StaticLibrary + false + v100 + v110 + v120 + v140 + v141 + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Use + Level3 + Disabled + WIN32;_DEBUG;%(PreprocessorDefinitions) + + + + + + + + Use + Level3 + Disabled + _DEBUG;%(PreprocessorDefinitions) + + + + + + + + Use + Level3 + WIN32;NDEBUG;%(PreprocessorDefinitions) + + + + + + + + Use + Level3 + NDEBUG;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + + + + + + + + {8eb74b67-3b52-4734-875b-f3f27ea55fc9} + + + + + + \ No newline at end of file diff --git a/SampleTests/ClrLibProject/ClrLibProject.vcxproj.filters b/SampleTests/ClrLibProject/ClrLibProject.vcxproj.filters new file mode 100644 index 000000000..7d3a04fe0 --- /dev/null +++ b/SampleTests/ClrLibProject/ClrLibProject.vcxproj.filters @@ -0,0 +1,49 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Headerdateien + + + Headerdateien + + + Headerdateien + + + + + Quelldateien + + + Quelldateien + + + Quelldateien + + + + + Ressourcendateien + + + + + Ressourcendateien + + + \ No newline at end of file diff --git a/SampleTests/ClrLibProject/Resource.h b/SampleTests/ClrLibProject/Resource.h new file mode 100644 index 000000000..c11f7d2a2 --- /dev/null +++ b/SampleTests/ClrLibProject/Resource.h @@ -0,0 +1,3 @@ +//{{NO_DEPENDENCIES}} +// Von Microsoft Visual C++ generierte Includedatei. +// Verwendet von app.rc diff --git a/SampleTests/ClrLibProject/app.ico b/SampleTests/ClrLibProject/app.ico new file mode 100644 index 0000000000000000000000000000000000000000..789d7ccbb56ed92f1bb005054ec7e67257ddc37e GIT binary patch literal 41395 zcmeHQZA=_R7=DjCkZTKK8e`L%_DrfaQ35q-NU0yk2`Okwv@x+7+O*QNL}I~`Y8$Mc zweceoTVpWz1KLD?5Tj6HjAC->RZTH5(3+Y^qR}Q*QIUg61#Btj%&kM`7H)6nj+0&P zne4DLH}A~6^UO0d@9xgBL=JKjcMi&?At%w>EL>Qq#oKdt>C$N+(Rua|At$Lyk0H7#>diEi}F0wek;+HU7|b|XXU)xB+Bzp4Xf+HR-)G) zs@#~fX!#;mY)(aa>1JM9q{b|Es@mJmiXcbB=8Zn;=)3uM7IEz^*;GQ*b!7464yF^i z>&qW&Ajxqo~ z`o$M|S6|Ksp*!JynDLQBBox`-#bTKXNNLW6@ zgkx${f)e9J7HU zW>BoNwY0UbHnH&K*Qp-nz06Nvr^+meah=M<;eY@TNCN~S6LgB(nf&r-v~=^*=c0n&Ojh75tz+RnK5HVPvXohh+3)UAs(fW-b|Sp*ELAr(aAhg;CWNC zNg-csQaH8gOTI~A>mQ?;HLt$xf4z2e-!~6*cy1{Dt+(p06<@t|uzZicMMS~oQ0<3D z0x!1grj?D(wFOt)E;k)Ed9+Tg3NEWIIN#a3e!Td!+uXBZlaG*-5o1m2`SF#ewPVG* z`nqqrRCRT#YNfyP4BvY&bah{6bzfHSM$0IhOhc`lceYNT^Phg?sL%8lI?Ns?&V`*c zRdBocy$a9gPIeW|Bs$T^;GR!b6_sshE;@YY_gp~UPvB*7Kl6N3QpB;1NN_*^2mk>f zpdrBaQ2Eo`hgtjKfdM$cIKcK+E@&TbtfT$t|Aou}RsOSm)?qt)eP5#e#_0u9G5^8-Gva`rFPQ&e|Jj)XdOjO*ANC*YKRsXU%zfB@ z$=iQ=KG;33I{(?dy?Xu8el`17kDuM+=zsLT5eMwf?|AwfwVkKM%WwB|v>)T&hy!-# zcRc-#+K%yWJT~HChjicv4%m(ZY5o2e-U9>zKp=e)5dSYJ-Z^~{vUkhl^=tHZCp?kH z`q>9+;D7)SxP}0;>rdL;uu&S+@th^rgWXn^{AFF=V`xmP6 zLQm8mZTksaRPj`m7xe&t;4gDP@IsYOs`8>9xo#d7zpIv~Dlh6m{oudM0l^DZKB>x! zdgQug{)_ZfpHctp{7*IRqI}>VjlUj`bctK)VsIXmk>B_FKdTq@^7|D0wuFay@!ess zi$&(x%>|#u+@X3Fb@P0QtXIgd%~cBlKUMBytK3=S|5B?6C@Zfc%y|tX`@>MF_Bza|9bWJ&1RG6?o!Cp zQkJ=$IdkURzO(c4+*DIRCmN`)iN>1J63w99K$~i=pBl0{)Mvh+-@4O?Hi154yoEMl z^tm~+KJ&oJ(gu2jr=btp;+AF{>rhAR4&lCyytUl4d`UcK+50-zrLJ_X zmO47q4_&AYwZ;5YU44ggNq?dPC|%~3lIdVQs`sUK&hdl|v(FM8ki5P1SSk5Rg@ZuAbKE`f2SRTm_k>Iii0)3=eb zr!Vw7(TW{rMPG;dVD#npYKvPNi(A%lJ;1v1eD5Id2C2tr(OUYjde~i$<0{fuX#I^U zWh)M;LatWrr4{CLvp!6d@EWTO;SHv($|e|E~?;; za-ye2B~R;jO+D5tw#`h%+s_-|;H?i{$goeyV1^WjSXJv*x%Y z(b}>n%OfGfT;D>hh^~2MXmW17f2X{CnPh&fwol44dW0wZAIQIt I@^QDVubpBd=l}o! literal 0 HcmV?d00001 diff --git a/SampleTests/ClrLibProject/stdafx.cpp b/SampleTests/ClrLibProject/stdafx.cpp new file mode 100644 index 000000000..fd4f341c7 --- /dev/null +++ b/SampleTests/ClrLibProject/stdafx.cpp @@ -0,0 +1 @@ +#include "stdafx.h" diff --git a/SampleTests/ClrLibProject/stdafx.h b/SampleTests/ClrLibProject/stdafx.h new file mode 100644 index 000000000..6f70f09be --- /dev/null +++ b/SampleTests/ClrLibProject/stdafx.h @@ -0,0 +1 @@ +#pragma once diff --git a/SampleTests/ClrTests/ClrTests.cpp b/SampleTests/ClrTests/ClrTests.cpp new file mode 100644 index 000000000..24c2e5e39 --- /dev/null +++ b/SampleTests/ClrTests/ClrTests.cpp @@ -0,0 +1,14 @@ +#include "gtest/gtest.h" +#include "../ClrLibProject/ClrLibProject.h" + +TEST(ClrTests, Pass) +{ + ClrLibProject::ClrClass instance; + ASSERT_EQ(2, instance.Add(1, 1)); +} + +TEST(ClrTests, Fail) +{ + ClrLibProject::ClrClass instance; + ASSERT_EQ(3, instance.Add(1, 1)); +} \ No newline at end of file diff --git a/SampleTests/ClrTests/ClrTests.vcxproj b/SampleTests/ClrTests/ClrTests.vcxproj new file mode 100644 index 000000000..bd2217d5a --- /dev/null +++ b/SampleTests/ClrTests/ClrTests.vcxproj @@ -0,0 +1,203 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {E1CE3891-E39B-48C7-ABF6-ACDC3C06C4F7} + Win32Proj + ClrTests + 10.0.17763.0 + + + + + Application + true + v100 + v110 + v120 + v140 + v141 + v142 + Unicode + + + Application + false + v100 + v110 + v120 + v140 + v141 + v142 + true + Unicode + + + Application + true + v100 + v110 + v120 + v140 + v141 + v142 + Unicode + + + Application + false + v100 + v110 + v120 + v140 + v141 + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + $(ProjectName)_gta + + + true + $(ProjectName)_gta + + + false + $(ProjectName)_gta + + + false + $(ProjectName)_gta + + + + NotUsing + Level3 + Disabled + true + _VARIADIC_MAX=10;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + $(ProjectDir)..\3rdparty\gtest-1.8.1\fused-src;%(AdditionalIncludeDirectories) + + + Console + DebugFull + true + + + + + NotUsing + Level3 + Disabled + true + _VARIADIC_MAX=10;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + $(ProjectDir)..\3rdparty\gtest-1.8.1\fused-src;%(AdditionalIncludeDirectories) + + + Console + DebugFull + true + + + + + NotUsing + Level3 + MaxSpeed + true + true + true + _VARIADIC_MAX=10;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + $(ProjectDir)..\3rdparty\gtest-1.8.1\fused-src;%(AdditionalIncludeDirectories) + + + Console + true + true + DebugFull + true + + + + + NotUsing + Level3 + MaxSpeed + true + true + true + _VARIADIC_MAX=10;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + $(ProjectDir)..\3rdparty\gtest-1.8.1\fused-src;%(AdditionalIncludeDirectories) + + + Console + true + true + DebugFull + true + + + + + + + + + + {4438c703-36a0-46fb-806c-90e2c6de9359} + + + + + + \ No newline at end of file diff --git a/SampleTests/ClrTests/ClrTests.vcxproj.filters b/SampleTests/ClrTests/ClrTests.vcxproj.filters new file mode 100644 index 000000000..a16f86cee --- /dev/null +++ b/SampleTests/ClrTests/ClrTests.vcxproj.filters @@ -0,0 +1,28 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Quelldateien + + + Quelldateien + + + Quelldateien + + + \ No newline at end of file diff --git a/SampleTests/ClrTests/Main.cpp b/SampleTests/ClrTests/Main.cpp new file mode 100644 index 000000000..db8e17dba --- /dev/null +++ b/SampleTests/ClrTests/Main.cpp @@ -0,0 +1,7 @@ +#include "gtest/gtest.h" + +int main(int argc, char ** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/SampleTests/SampleTests.sln b/SampleTests/SampleTests.sln index 18b43f429..cd00c8b40 100644 --- a/SampleTests/SampleTests.sln +++ b/SampleTests/SampleTests.sln @@ -33,6 +33,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DllProject", "DllProject\Dl EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LeakCheckTests", "LeakCheckTests\LeakCheckTests.vcxproj", "{41791F46-44CF-459B-9F77-049CE1C9D203}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClrLibProject", "ClrLibProject\ClrLibProject.vcxproj", "{4438C703-36A0-46FB-806C-90E2C6DE9359}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClrTests", "ClrTests\ClrTests.vcxproj", "{E1CE3891-E39B-48C7-ABF6-ACDC3C06C4F7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClrDotNetLibProject", "ClrDotNetLibProject\ClrDotNetLibProject.csproj", "{8EB74B67-3B52-4734-875B-F3F27EA55FC9}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -133,6 +139,38 @@ Global {41791F46-44CF-459B-9F77-049CE1C9D203}.Release|Win32.Build.0 = Release|Win32 {41791F46-44CF-459B-9F77-049CE1C9D203}.Release|x64.ActiveCfg = Release|x64 {41791F46-44CF-459B-9F77-049CE1C9D203}.Release|x64.Build.0 = Release|x64 + {4438C703-36A0-46FB-806C-90E2C6DE9359}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {4438C703-36A0-46FB-806C-90E2C6DE9359}.Debug|Win32.ActiveCfg = Debug|Win32 + {4438C703-36A0-46FB-806C-90E2C6DE9359}.Debug|Win32.Build.0 = Debug|Win32 + {4438C703-36A0-46FB-806C-90E2C6DE9359}.Debug|x64.ActiveCfg = Debug|x64 + {4438C703-36A0-46FB-806C-90E2C6DE9359}.Debug|x64.Build.0 = Debug|x64 + {4438C703-36A0-46FB-806C-90E2C6DE9359}.Release|Any CPU.ActiveCfg = Release|Win32 + {4438C703-36A0-46FB-806C-90E2C6DE9359}.Release|Win32.ActiveCfg = Release|Win32 + {4438C703-36A0-46FB-806C-90E2C6DE9359}.Release|Win32.Build.0 = Release|Win32 + {4438C703-36A0-46FB-806C-90E2C6DE9359}.Release|x64.ActiveCfg = Release|x64 + {4438C703-36A0-46FB-806C-90E2C6DE9359}.Release|x64.Build.0 = Release|x64 + {E1CE3891-E39B-48C7-ABF6-ACDC3C06C4F7}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {E1CE3891-E39B-48C7-ABF6-ACDC3C06C4F7}.Debug|Win32.ActiveCfg = Debug|Win32 + {E1CE3891-E39B-48C7-ABF6-ACDC3C06C4F7}.Debug|Win32.Build.0 = Debug|Win32 + {E1CE3891-E39B-48C7-ABF6-ACDC3C06C4F7}.Debug|x64.ActiveCfg = Debug|x64 + {E1CE3891-E39B-48C7-ABF6-ACDC3C06C4F7}.Debug|x64.Build.0 = Debug|x64 + {E1CE3891-E39B-48C7-ABF6-ACDC3C06C4F7}.Release|Any CPU.ActiveCfg = Release|Win32 + {E1CE3891-E39B-48C7-ABF6-ACDC3C06C4F7}.Release|Win32.ActiveCfg = Release|Win32 + {E1CE3891-E39B-48C7-ABF6-ACDC3C06C4F7}.Release|Win32.Build.0 = Release|Win32 + {E1CE3891-E39B-48C7-ABF6-ACDC3C06C4F7}.Release|x64.ActiveCfg = Release|x64 + {E1CE3891-E39B-48C7-ABF6-ACDC3C06C4F7}.Release|x64.Build.0 = Release|x64 + {8EB74B67-3B52-4734-875B-F3F27EA55FC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8EB74B67-3B52-4734-875B-F3F27EA55FC9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8EB74B67-3B52-4734-875B-F3F27EA55FC9}.Debug|Win32.ActiveCfg = Debug|Any CPU + {8EB74B67-3B52-4734-875B-F3F27EA55FC9}.Debug|Win32.Build.0 = Debug|Any CPU + {8EB74B67-3B52-4734-875B-F3F27EA55FC9}.Debug|x64.ActiveCfg = Debug|Any CPU + {8EB74B67-3B52-4734-875B-F3F27EA55FC9}.Debug|x64.Build.0 = Debug|Any CPU + {8EB74B67-3B52-4734-875B-F3F27EA55FC9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8EB74B67-3B52-4734-875B-F3F27EA55FC9}.Release|Any CPU.Build.0 = Release|Any CPU + {8EB74B67-3B52-4734-875B-F3F27EA55FC9}.Release|Win32.ActiveCfg = Release|Any CPU + {8EB74B67-3B52-4734-875B-F3F27EA55FC9}.Release|Win32.Build.0 = Release|Any CPU + {8EB74B67-3B52-4734-875B-F3F27EA55FC9}.Release|x64.ActiveCfg = Release|Any CPU + {8EB74B67-3B52-4734-875B-F3F27EA55FC9}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 4fde9510c2287070b590711c93156ce8d025a380 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Fri, 19 Apr 2019 08:35:32 +0200 Subject: [PATCH 73/81] added documentation --- .../Core.Tests/Core.Tests.csproj | 2 ++ .../Settings/HelperFilesCacheTests.cs | 4 +-- GoogleTestAdapter/Core.Tests/packages.config | 2 -- .../Resources/ReleaseNotes/0.15.0.md | 1 - .../Resources/ReleaseNotes/0.16.0.md | 3 +- README.md | 31 +++++++++++++------ 6 files changed, 28 insertions(+), 15 deletions(-) diff --git a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj index 5cc726aca..28a9acec8 100644 --- a/GoogleTestAdapter/Core.Tests/Core.Tests.csproj +++ b/GoogleTestAdapter/Core.Tests/Core.Tests.csproj @@ -18,6 +18,8 @@ False UnitTest + + true diff --git a/GoogleTestAdapter/Core.Tests/Settings/HelperFilesCacheTests.cs b/GoogleTestAdapter/Core.Tests/Settings/HelperFilesCacheTests.cs index 45cd3d1fa..32a43b18f 100644 --- a/GoogleTestAdapter/Core.Tests/Settings/HelperFilesCacheTests.cs +++ b/GoogleTestAdapter/Core.Tests/Settings/HelperFilesCacheTests.cs @@ -17,7 +17,7 @@ public class HelperFilesCacheTests : TestsBase public void GetReplacementsMap_NoFile_EmptyDictionary() { string executable = TestResources.Tests_DebugX86; - var extraSettings = $"{executable}{HelperFilesCache.HelperFileEnding}"; + var extraSettings = HelperFilesCache.GetHelperFile(executable); extraSettings.AsFileInfo().Should().NotExist(); var cache = new HelperFilesCache(MockLogger.Object); @@ -113,7 +113,7 @@ public void GetReplacementsMap_OnlyTwoSeparators_ProperDictionary() private void DoTest(string content, Action> assertions, string executable = TestResources.Tests_DebugX86) { - var extraSettings = $"{executable}{HelperFilesCache.HelperFileEnding}"; + var extraSettings = HelperFilesCache.GetHelperFile(executable); try { extraSettings.AsFileInfo().Should().NotExist(); diff --git a/GoogleTestAdapter/Core.Tests/packages.config b/GoogleTestAdapter/Core.Tests/packages.config index 31fd4c297..87cac3d92 100644 --- a/GoogleTestAdapter/Core.Tests/packages.config +++ b/GoogleTestAdapter/Core.Tests/packages.config @@ -3,8 +3,6 @@ - - diff --git a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md index d5588a0c9..55460be96 100644 --- a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md +++ b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.15.0.md @@ -1,5 +1,4 @@ * enhancement: setting the new option [*Exit code test name*](https://github.com/csoltenborn/GoogleTestAdapter#evaluating_exit_code) results in an additional test per test executable that passes if the executable's exit code is 0, and fails otherwise. Additionally, GTA parses the test executable's output for certain [tokens](https://github.com/csoltenborn/GoogleTestAdapter#evaluating_exit_code_tokens) which allow to influence the test's outcome and message. One interesting use case for this is memory leak detection; a complete, reusable [example](https://github.com/csoltenborn/GoogleTestAdapter#evaluating_exit_code_leak_example) is provided as part of GTA's [SampleTests solution](https://github.com/csoltenborn/GoogleTestAdapter/tree/master/SampleTests) ([#266](https://github.com/csoltenborn/GoogleTestAdapter/issues/266), thanks to [alfredskpoon](https://github.com/alfredskpoon) for report, example code, and testing) -* usability: reorganized options ([#271](https://github.com/csoltenborn/GoogleTestAdapter/issues/271)) * enhancement: the GTA extension is now loaded asynchronically by Visual Studio; the drawback is that support for Visual Studio 2012 had to be dropped ([#243](https://github.com/csoltenborn/GoogleTestAdapter/issues/243)) * enhancement: the *Show release notes* option has been removed, and this release notes dialog has been slightly changed and now has very funny buttons ([#270](https://github.com/csoltenborn/GoogleTestAdapter/issues/270)) * maintenance: reduced code duplication of streaming and batch output parsers ([#263](https://github.com/csoltenborn/GoogleTestAdapter/issues/263)) diff --git a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.16.0.md b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.16.0.md index 7dc9acfb9..b8e2f3928 100644 --- a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.16.0.md +++ b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.16.0.md @@ -1 +1,2 @@ -* usability: reorganized options ([#271](https://github.com/csoltenborn/GoogleTestAdapter/issues/271)) +* enhancement: [*settings helper files*]([tokens](https://github.com/csoltenborn/GoogleTestAdapter#settings_helper_files)) allow to provide additional information to GTA at test discovery and execution time ([example project](https://github.com/csoltenborn/GoogleTestAdapter/tree/master/SampleTests/DllProject)). This feature can be used to remove the need for a special configuration file for CI, or to reduce configuration redundancy between project and GTA settings ([#278](https://github.com/csoltenborn/GoogleTestAdapter/issues/278)) +* usability: reorganized options ([#271](https://github.com/csoltenborn/GoogleTestAdapter/issues/271)) \ No newline at end of file diff --git a/README.md b/README.md index e6158d690..98db67bf8 100644 --- a/README.md +++ b/README.md @@ -93,10 +93,20 @@ Note that due to the overriding hierarchy described above, you probably want to For reference, see a settings file [AllTestSettings.gta.runsettings](https://raw.githubusercontent.com/csoltenborn/GoogleTestAdapter/master/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings) containing all available settings, a more realistic solution settings file [SampleTests.gta.runsettings](https://raw.githubusercontent.com/csoltenborn/GoogleTestAdapter/master/SampleTests/SampleTests.gta.runsettings) as delivered with the SampleTests solution, and a user settings file [NonDeterministic.runsettings](https://raw.githubusercontent.com/csoltenborn/GoogleTestAdapter/master/SampleTests/NonDeterministic.runsettings) as used by GTA's end-to-end tests. The syntax of the GTA settings files (excluding the `` node) is specified by [this schema](https://raw.githubusercontent.com/csoltenborn/GoogleTestAdapter/master/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd). -##### GTA helper files +##### Settings helper files GTA does not provide direct access to VS project settings such as *Project* > *Properties* > *Debugging* > *Environment*. Additionally, when run as NuGet dependency, GTA does not have access to information such as solution dir or Platform/Configuration a test executable has been build with. -To overcome these problems, GTA supports so-called *helper files* which provide that information to GTA. +To overcome these problems, GTA supports so-called *settings helper files* which provide that information to GTA. Helper files are usually generated as part of the build, e.g. within a post-build event, which might look like this: + +``` +echo SolutionPath=$(SolutionPath)::GTA::SolutionDir=$(SolutionDir)::GTA::PlatformName=$(PlatformName)::GTA::ConfigurationName=$(ConfigurationName)::GTA::TheTarget=$(TargetFileName) > $(TargetPath).gta_settings_helper +``` + +This command generates a file `$(TargetPath).gta_settings_helper` (where `$(TargetPath)` is the path of the final test executable) containing key/value pairs separated by `::GTA::`. At file generation time, the VS macros will be replaced by the actual values, which can then in turn be used as placeholders within the GTA settings. In particular, the helper file generated by the above command will +* make sure that the `$(SolutionDir)`, `$(PlatformName)`, and `$(ConfigurationName)` placeholders will be available even if the runtime environment does not provide them (CI) and +* will provide the value of the VS `$(TargetFileName)` macro to GTA, where it can be referred to as the `$(TheTarget)` placeholder + +Note that the settings helper files need to be located within the same folder as their corresponding test executable, and must have the test executable's name concatenated with the `.gta_settings_helper` ending (make sure to ignore these files in version control if necessary). #### Assigning traits to tests @@ -188,7 +198,7 @@ GTA runs in three different environments: * Within Visual Studio and installed via NuGet (i.e., pulled via a project's NuGet dependencies) * Within `VsTestConsole.exe` (making use of the `/UseVsixExtensions:true` or the `/TestAdapterPath:` options) -For technical reasons, not all features are available in all environments; refer to the table below for details. +For technical reasons, not all features are available in all environments by default; refer to the table below for details. | Feature | VS/VSIX | VS/NuGet | VsTest.Console |--- |:---:|:---:|:---: @@ -201,18 +211,21 @@ For technical reasons, not all features are available in all environments; refer | - Solution test config file | yes | no | no | - User test config file | yes[1](#vs_settings) | yes[1](#vs_settings) | yes[2](#test_settings) | Placeholders | | | -| - `$(SolutionDir)` | yes | yes[3](#only_test_execution) | no -| - `$(PlatformName)` | yes | no | no -| - `$(ConfigurationName)` | yes | no | no +| - `$(SolutionDir)` | yes | yes[3](#helper_files), [4](#also_test_execution) | yes[3](#helper_files) +| - `$(PlatformName)` | yes | yes[3](#helper_files) | yes[3](#helper_files) +| - `$(ConfigurationName)` | yes | yes[3](#helper_files) | yes[3](#helper_files) | - `$(ExecutableDir)` | yes | yes | yes | - `$(Executable)` | yes | yes | yes -| - `$(TestDir)`[3](#only_test_execution) | yes | yes | yes -| - `$(ThreadId)`[3](#only_test_execution) | yes | yes | yes +| - `$(TestDir)`[5](#only_test_execution) | yes | yes | yes +| - `$(ThreadId)`[5](#only_test_execution) | yes | yes | yes +| - Additional placeholders | yes[3](#helper_files) | yes[3](#helper_files) | yes[3](#helper_files) | - Environment variables | yes | yes | yes 1: Via *Test/Test Settings/Select Test Settings File*
2: Via `/Settings` option
-3: Only during test execution; placeholders are removed in discovery mode +3: If [*settings helper files*](#settings_helper_files) are provided
+4: During test execution, placeholders are available even without settings helper files
+5: Only during test execution; placeholders are removed in discovery mode ### External resources From 9d0f96e35be69dd19c783947b2d5588c4d7eeb18 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Fri, 19 Apr 2019 09:41:57 +0200 Subject: [PATCH 74/81] added release notes, fixed docs --- GoogleTestAdapter/Core/ProcessExecution/DebuggerKind.cs | 6 +++--- GoogleTestAdapter/Core/Settings/SettingsWrapper.cs | 6 +++--- .../VsPackage.GTA/Resources/ReleaseNotes/0.16.0.md | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/GoogleTestAdapter/Core/ProcessExecution/DebuggerKind.cs b/GoogleTestAdapter/Core/ProcessExecution/DebuggerKind.cs index 5a1df384f..acb5fbf6e 100644 --- a/GoogleTestAdapter/Core/ProcessExecution/DebuggerKind.cs +++ b/GoogleTestAdapter/Core/ProcessExecution/DebuggerKind.cs @@ -17,9 +17,9 @@ public static string ToReadableString(this DebuggerKind debuggerKind) public class DebuggerKindConverter : EnumConverter { - private const string VsTestFramework = "VsTest framework"; - private const string Native = "Native"; - private const string ManagedAndNative = "Managed and native"; + public const string VsTestFramework = "VsTest framework"; + public const string Native = "Native"; + public const string ManagedAndNative = "Managed and native"; public DebuggerKindConverter(Type enumType) : base(enumType) {} diff --git a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs index a848e4a77..c2a10066a 100644 --- a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs +++ b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs @@ -274,9 +274,9 @@ public virtual int ShuffleTestsSeed public const string OptionDebuggerKind = "Debugger engine"; public const string OptionDebuggerKindDescription = - "Framework: Debugger engine as provided by VsTest framework; no test crash detection, no test output printing, less interactive UI\n" + - "Native: Debugger engine as provided by VS native API; no restrictions (default)\n" + - "ManagedAndNative: Same as Native, but allows to also debug into managed code"; + DebuggerKindConverter.VsTestFramework + ": Debugger engine as provided by the VsTest framework; no test crash detection, no test output printing, less interactive UI\n" + + DebuggerKindConverter.Native + ": Debugger engine as provided by VS native API; no restrictions (default)\n" + + DebuggerKindConverter.ManagedAndNative + ": Same as '" + DebuggerKindConverter.Native + "', but allows to also debug into managed code"; public const DebuggerKind OptionDebuggerKindDefaultValue = DebuggerKind.Native; public virtual DebuggerKind DebuggerKind => _currentSettings.DebuggerKind ?? OptionDebuggerKindDefaultValue; diff --git a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.16.0.md b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.16.0.md index 7dc9acfb9..23df408e1 100644 --- a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.16.0.md +++ b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.16.0.md @@ -1 +1,2 @@ * usability: reorganized options ([#271](https://github.com/csoltenborn/GoogleTestAdapter/issues/271)) +* enhancement: option *Debugger engine* allows to choose *Managed and native*, which allows to debug into managed code also ([#276](https://github.com/csoltenborn/GoogleTestAdapter/issues/276)) From 8e20496f9294d303e721a4073de6072f9e2f4114 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Fri, 19 Apr 2019 10:56:18 +0200 Subject: [PATCH 75/81] minor improvements to options docs --- GoogleTestAdapter/Core/Settings/SettingsWrapper.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs index 0940e5c09..18a06f7e7 100644 --- a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs +++ b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs @@ -238,7 +238,7 @@ public virtual int NrOfTestRepetitions public const string OptionShuffleTests = "Shuffle tests per execution"; public const string OptionShuffleTestsDescription = - "If true, tests will be executed in random order. Note that a true randomized order is only given when executing all tests in non-parallel fashion. Otherwise, the test excutables will most likely be executed more than once - random order is than restricted to the according executions.\n" + "If true, tests will be executed in random order. Note that a true randomized order is only given when executing all tests in non-parallel fashion. Otherwise, the test excutables will most likely be executed more than once - random order is then restricted to the according executions.\n" + "Google Test option:" + GoogleTestConstants.ShuffleTestsOption; public const bool OptionShuffleTestsDefaultValue = false; @@ -312,7 +312,7 @@ public string GetWorkingDirForDiscovery(string executable) public const string OptionPathExtension = "PATH extension"; public const string OptionPathExtensionDescription = - "If non-empty, the content will be appended to the PATH variable of the test execution and discovery processes.\nExample: C:\\MyBins;" + PlaceholderReplacer.ExecutableDirPlaceholder + "\\MyOtherBins;\n" + PlaceholderReplacer.PathExtensionPlaceholders; + "If non-empty, the content will be appended to the PATH variable of the test execution and discovery processes.\nExample: C:\\MyBins;" + PlaceholderReplacer.ExecutableDirPlaceholder + "\\MyOtherBins\n" + PlaceholderReplacer.PathExtensionPlaceholders; public const string OptionPathExtensionDefaultValue = ""; public virtual string PathExtension => _currentSettings.PathExtension ?? OptionPathExtensionDefaultValue; @@ -409,7 +409,7 @@ public virtual int MaxNrOfThreads public const string OptionTestDiscoveryRegex = "Regex for test discovery"; public const string OptionTestDiscoveryRegexDescription = - "If non-empty, this regex will be used to identify the Google Test executables containing your tests, and the executable itself will not be scanned."; + "If non-empty, only executables matching this regex will be considered as Google Test executables. Note that setting this option will slightly speed up test discovery since the executables do not need to be scanned."; public const string OptionTestDiscoveryRegexDefaultValue = ""; public virtual string TestDiscoveryRegex => _currentSettings.TestDiscoveryRegex ?? OptionTestDiscoveryRegexDefaultValue; @@ -435,7 +435,7 @@ public virtual int TestDiscoveryTimeoutInSeconds { public const string TraitsRegexesPairSeparator = "//||//"; public const string TraitsRegexesRegexSeparator = "///"; public const string TraitsRegexesTraitSeparator = ","; - public const string OptionTraitsDescription = "Allows to override/add traits for testcases matching a regex. Traits are build up in 3 phases: 1st, traits are assigned to tests according to the 'Traits before' option. 2nd, the tests' traits (defined via the macros in GTA_Traits.h) are added to the tests, overriding traits from phase 1 with new values. 3rd, the 'Traits after' option is evaluated, again in an overriding manner.\nSyntax: " + public const string OptionTraitsDescription = "Allows to override/add traits for testcases matching a regex. Traits are build up in 3 phases: 1st, traits are assigned to tests according to the '" + OptionTraitsRegexesBefore + "' option. 2nd, the tests' traits (defined via the macros in GTA_Traits.h) are added to the tests, overriding traits from phase 1 with new values. 3rd, the '" + OptionTraitsRegexesAfter + "' option is evaluated, again in an overriding manner.\nSyntax: " + TraitsRegexesRegexSeparator + " separates the regex from the traits, the trait's name and value are separated by " + TraitsRegexesTraitSeparator + @@ -483,8 +483,7 @@ public virtual List TraitsRegexesAfter public const string OptionParseSymbolInformation = "Parse symbol information"; public const string OptionParseSymbolInformationDescription = - "Parse debug symbol information for test executables to obtain source location information and traits (defined via the macros in GTA_Traits.h).\n" + - "If this is set to false step 2 of traits discovery will be left out and only traits regexes will be effective."; + "Parse debug symbol information for test executables. Setting this to false will speed up test discovery, but tests will not have source location information, and traits defined via the macros in GTA_Traits.h will not be available."; public const bool OptionParseSymbolInformationDefaultValue = true; public virtual bool ParseSymbolInformation => _currentSettings.ParseSymbolInformation ?? OptionParseSymbolInformationDefaultValue; From bc456f7a5b4fc27c1b793cc058ca4c45b1732e13 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sat, 20 Apr 2019 08:37:29 +0200 Subject: [PATCH 76/81] added options to print severity and warning --- GoogleTestAdapter/Common/Common.csproj | 1 + GoogleTestAdapter/Common/EnumConverterBase.cs | 64 +++++++++++++++ GoogleTestAdapter/Common/ILogger.cs | 35 ++++++++ .../Core.Tests/Helpers/UtilsTests.cs | 23 ------ GoogleTestAdapter/Core/Helpers/Utils.cs | 5 +- .../Core/ProcessExecution/DebuggerKind.cs | 58 +++----------- .../Settings/IGoogleTestAdapterSettings.cs | 6 +- .../Core/Settings/RunSettings.cs | 6 ++ .../Core/Settings/SettingsWrapper.cs | 20 ++++- .../Resources/AllTestSettings.gta.runsettings | 68 ++++++++-------- .../Framework/VsTestFrameworkLoggerTests.cs | 2 +- .../TestAdapter/CommonFunctions.cs | 11 ++- .../Framework/VsTestFrameworkLogger.cs | 79 ++++++++++++++----- .../TestAdapter/GoogleTestAdapterSettings.xsd | 24 +++++- .../Tests.Common/Fakes/FakeLogger.cs | 4 +- GoogleTestAdapter/Tests.Common/TestsBase.cs | 3 +- .../GoogleTestExtensionOptionsPage.cs | 3 +- .../OptionsPages/GeneralOptionsDialogPage.cs | 21 ++++- .../OptionsPages/OptionsUpdater.cs | 14 ++++ 19 files changed, 305 insertions(+), 142 deletions(-) create mode 100644 GoogleTestAdapter/Common/EnumConverterBase.cs diff --git a/GoogleTestAdapter/Common/Common.csproj b/GoogleTestAdapter/Common/Common.csproj index 38b9bb098..acc52cf44 100644 --- a/GoogleTestAdapter/Common/Common.csproj +++ b/GoogleTestAdapter/Common/Common.csproj @@ -51,6 +51,7 @@ + diff --git a/GoogleTestAdapter/Common/EnumConverterBase.cs b/GoogleTestAdapter/Common/EnumConverterBase.cs new file mode 100644 index 000000000..0e2785987 --- /dev/null +++ b/GoogleTestAdapter/Common/EnumConverterBase.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.Linq; + +namespace GoogleTestAdapter.Common +{ + public abstract class EnumConverterBase : EnumConverter + { + private readonly IDictionary _stringMap; + + protected EnumConverterBase(IDictionary stringMap) : base(typeof(TEnum)) + { + if (stringMap == null) + throw new ArgumentNullException(nameof(stringMap)); + + if (stringMap.Count != Enum.GetValues(typeof(TEnum)).Length) + throw new ArgumentException(nameof(stringMap), "Map must have the same size as the enum"); + + if (stringMap.Values.Distinct().Count() != stringMap.Values.Count) + throw new ArgumentException(nameof(stringMap), "Values of map must be pairwise distinct strings"); + + _stringMap = stringMap; + } + + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + return sourceType == typeof(TEnum) || + base.CanConvertFrom(context, sourceType); + } + + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + { + return destinationType == typeof(string) || + base.CanConvertTo(context, destinationType); + } + + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + if (value is string valueString) + { + foreach (KeyValuePair kvp in _stringMap) + { + if (kvp.Value == valueString) + return kvp.Key; + } + } + + return base.ConvertFrom(context, culture, value); + } + + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + if (!(value is TEnum enumLiteral) || destinationType != typeof(string)) + return base.ConvertTo(context, culture, value, destinationType); + + if (_stringMap.TryGetValue(enumLiteral, out string stringValue)) + return stringValue; + + return base.ConvertTo(context, culture, value, destinationType); + } + } +} \ No newline at end of file diff --git a/GoogleTestAdapter/Common/ILogger.cs b/GoogleTestAdapter/Common/ILogger.cs index 372c05d53..1400a1ed8 100644 --- a/GoogleTestAdapter/Common/ILogger.cs +++ b/GoogleTestAdapter/Common/ILogger.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.ComponentModel; namespace GoogleTestAdapter.Common { @@ -6,6 +7,12 @@ namespace GoogleTestAdapter.Common public enum Severity { Info, Warning, Error } public enum OutputMode { None = 0, Info = 10, Debug = 20, Verbose = 30 } + [TypeConverter(typeof(TimestampModeConverter))] + public enum TimestampMode { Automatic, PrintTimestamp, DoNotPrintTimestamp } + + [TypeConverter(typeof(SeverityModeConverter))] + public enum SeverityMode { Automatic, PrintSeverity, DoNotPrintSeverity } + public interface ILogger { void LogInfo(string message); @@ -20,4 +27,32 @@ public interface ILogger } + public class TimestampModeConverter : EnumConverterBase + { + public const string Automatic = "Automatic"; + public const string PrintTimeStamp = "Print timestamp"; + public const string DoNotPrintTimeStamp = "Do not print timestamp"; + + public TimestampModeConverter() : base(new Dictionary + { + {TimestampMode.Automatic, Automatic}, + {TimestampMode.PrintTimestamp, PrintTimeStamp}, + {TimestampMode.DoNotPrintTimestamp, DoNotPrintTimeStamp} + }){} + } + + public class SeverityModeConverter : EnumConverterBase + { + public const string Automatic = "Automatic"; + public const string PrintSeverity = "Print severity"; + public const string DoNotPrintSeverity = "Do not print severity"; + + public SeverityModeConverter() : base(new Dictionary + { + {SeverityMode.Automatic, Automatic}, + {SeverityMode.PrintSeverity, PrintSeverity}, + {SeverityMode.DoNotPrintSeverity, DoNotPrintSeverity} + }){} + } + } \ No newline at end of file diff --git a/GoogleTestAdapter/Core.Tests/Helpers/UtilsTests.cs b/GoogleTestAdapter/Core.Tests/Helpers/UtilsTests.cs index 041b0d9d2..4fd65dfc8 100644 --- a/GoogleTestAdapter/Core.Tests/Helpers/UtilsTests.cs +++ b/GoogleTestAdapter/Core.Tests/Helpers/UtilsTests.cs @@ -113,29 +113,6 @@ public void BinaryFileContainsStrings_EmptyFile_ShouldNotContainGoogleTestIndica Utils.BinaryFileContainsStrings(TestResources.TenSecondsWaiter, Encoding.ASCII, GoogleTestConstants.GoogleTestExecutableMarkers).Should().BeFalse(); } - [TestMethod] - [TestCategory(Unit)] - public void TimestampMessage_MessageIsNullOrEmpty_ResultIsTheSame() - { - string timestampSeparator = " - "; - string resultRegex = @"[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}" + timestampSeparator; - - string nullMessage = null; - Utils.TimestampMessage(ref nullMessage); - nullMessage.Should().MatchRegex(resultRegex); - nullMessage.Should().EndWith(timestampSeparator); - - string emptyMessage = ""; - Utils.TimestampMessage(ref emptyMessage); - emptyMessage.Should().MatchRegex(resultRegex); - emptyMessage.Should().EndWith(timestampSeparator); - - string fooMessage = "foo"; - Utils.TimestampMessage(ref fooMessage); - fooMessage.Should().MatchRegex(resultRegex); - fooMessage.Should().EndWith(timestampSeparator + "foo"); - } - [TestMethod] [TestCategory(Unit)] public void SpawnAndWait_SeveralTasks_AreExecutedInParallel() diff --git a/GoogleTestAdapter/Core/Helpers/Utils.cs b/GoogleTestAdapter/Core/Helpers/Utils.cs index e49f42c3c..4459e22d3 100644 --- a/GoogleTestAdapter/Core/Helpers/Utils.cs +++ b/GoogleTestAdapter/Core/Helpers/Utils.cs @@ -50,10 +50,9 @@ public static string GetExtendedPath(string pathExtension) return string.IsNullOrEmpty(pathExtension) ? path : $"{pathExtension};{path}"; } - public static void TimestampMessage(ref string message) + public static string GetTimestamp() { - string timestamp = DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture); - message = $"{timestamp} - {message ?? ""}"; + return DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture); } /// If at least one of the actions has thrown an exception diff --git a/GoogleTestAdapter/Core/ProcessExecution/DebuggerKind.cs b/GoogleTestAdapter/Core/ProcessExecution/DebuggerKind.cs index acb5fbf6e..a96ef5737 100644 --- a/GoogleTestAdapter/Core/ProcessExecution/DebuggerKind.cs +++ b/GoogleTestAdapter/Core/ProcessExecution/DebuggerKind.cs @@ -1,6 +1,8 @@ -using System; +using System.Collections.Generic; using System.ComponentModel; -using System.Globalization; +using GoogleTestAdapter.Common; + +// ReSharper disable NotResolvedInText namespace GoogleTestAdapter.ProcessExecution { @@ -15,58 +17,18 @@ public static string ToReadableString(this DebuggerKind debuggerKind) } } - public class DebuggerKindConverter : EnumConverter + public class DebuggerKindConverter : EnumConverterBase { public const string VsTestFramework = "VsTest framework"; public const string Native = "Native"; public const string ManagedAndNative = "Managed and native"; - - public DebuggerKindConverter(Type enumType) : base(enumType) {} - - public DebuggerKindConverter() : this(typeof(DebuggerKind)) {} - - public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) - { - return destinationType == typeof(string) || - base.CanConvertTo(context, destinationType); - } - - public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) - { - return sourceType == typeof(DebuggerKind) || - base.CanConvertFrom(context, sourceType); - } - - public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) - { - if (!(value is DebuggerKind debuggerKind) || destinationType != typeof(string)) - return base.ConvertTo(context, culture, value, destinationType); - - switch (debuggerKind) - { - case DebuggerKind.VsTestFramework: return VsTestFramework; - case DebuggerKind.Native: return Native; - case DebuggerKind.ManagedAndNative: return ManagedAndNative; - default: - return base.ConvertTo(context, culture, value, destinationType); - } - } - - public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + public DebuggerKindConverter() : base(new Dictionary { - if (!(value is string valueString)) - return base.ConvertFrom(context, culture, value); - - switch (valueString) - { - case VsTestFramework: return DebuggerKind.VsTestFramework; - case Native: return DebuggerKind.Native; - case ManagedAndNative: return DebuggerKind.ManagedAndNative; - default: - return base.ConvertFrom(context, culture, value); - } - } + { DebuggerKind.VsTestFramework, VsTestFramework}, + { DebuggerKind.Native, Native}, + { DebuggerKind.ManagedAndNative, ManagedAndNative}, + }) {} } diff --git a/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs b/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs index 21220fa0f..d5fa8acf6 100644 --- a/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs +++ b/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs @@ -13,7 +13,7 @@ namespace GoogleTestAdapter.Settings - handle property serialization in class GoogleTestAdapter.Settings.RunSettings - add Options UI integration to one of the classes in GoogleTestAdapter.VsPackage.OptionsPages.* - handle property in method GoogleTestAdapter.VsPackage.GoogleTestExtensionOptionsPage.GetRunSettingsFromOptionPages() - - update schema in GoogleTestAdapterSettings.xsd + - update schema in TestAdapter/GoogleTestAdapterSettings.xsd - add new option to Solution Items/AllTestSettings.gta.runsettings - add default mock configuration in method GoogleTestAdapter.Tests.Common.TestsBase.SetUp() */ @@ -45,6 +45,8 @@ public interface IGoogleTestAdapterSettings bool? DebugMode { get; set; } OutputMode? OutputMode { get; set; } bool? TimestampOutput { get; set; } + TimestampMode? TimestampMode { get; set; } + SeverityMode? SeverityMode { get; set; } bool? ShowReleaseNotes { get; set; } bool? KillProcessesOnCancel { get; set; } bool? SkipOriginCheck { get; set; } @@ -88,6 +90,8 @@ public static void GetUnsetValuesFrom(this IGoogleTestAdapterSettings self, IGoo self.DebugMode = self.DebugMode ?? other.DebugMode; self.OutputMode = self.OutputMode ?? other.OutputMode; self.TimestampOutput = self.TimestampOutput ?? other.TimestampOutput; + self.TimestampMode = self.TimestampMode ?? other.TimestampMode; + self.SeverityMode = self.SeverityMode ?? other.SeverityMode; self.ShowReleaseNotes = self.ShowReleaseNotes ?? other.ShowReleaseNotes; self.KillProcessesOnCancel = self.KillProcessesOnCancel ?? other.KillProcessesOnCancel; self.SkipOriginCheck = self.SkipOriginCheck ?? other.SkipOriginCheck; diff --git a/GoogleTestAdapter/Core/Settings/RunSettings.cs b/GoogleTestAdapter/Core/Settings/RunSettings.cs index 76f098281..e7da54bd7 100644 --- a/GoogleTestAdapter/Core/Settings/RunSettings.cs +++ b/GoogleTestAdapter/Core/Settings/RunSettings.cs @@ -73,6 +73,12 @@ public RunSettings(string projectRegex) public virtual bool? TimestampOutput { get; set; } public bool ShouldSerializeTimestampOutput() { return TimestampOutput != null; } + public virtual TimestampMode? TimestampMode { get; set; } + public bool ShouldSerializeTimestampMode() { return TimestampMode != null; } + + public virtual SeverityMode? SeverityMode { get; set; } + public bool ShouldSerializeSeverityMode() { return SeverityMode != null; } + public virtual bool? ShowReleaseNotes { get; set; } public bool ShouldSerializeShowReleaseNotes() { return ShowReleaseNotes != null; } diff --git a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs index 0b7997c02..b7fe15a32 100644 --- a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs +++ b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs @@ -172,10 +172,24 @@ public virtual void CheckCorrectUsage(string executable) public const string OptionTimestampOutput = "Timestamp output"; public const string OptionTimestampOutputDescription = - "If true, a timestamp is added to the output."; - public const bool OptionTimestampOutputDefaultValue = false; + "Controls whether a timestamp is added to the output.\n" + + TimestampModeConverter.Automatic + ": add timestamp on VS2013, VS2015\n" + + TimestampModeConverter.PrintTimeStamp + ": always add timestamp\n" + + TimestampModeConverter.DoNotPrintTimeStamp + ": never add timestamp"; + public const TimestampMode OptionTimestampOutputDefaultValue = TimestampMode.Automatic; - public virtual bool TimestampOutput => _currentSettings.TimestampOutput ?? OptionTimestampOutputDefaultValue; + public virtual TimestampMode TimestampMode => _currentSettings.TimestampMode ?? OptionTimestampOutputDefaultValue; + + + public const string OptionSeverityMode = "Print severity"; + public const string OptionSeverityModeDescription = + "Controls whether the messages' severity is added to the output.\n" + + SeverityModeConverter.Automatic + ": print severity on VS2013, VS2015\n" + + SeverityModeConverter.PrintSeverity + ": always print severity\n" + + SeverityModeConverter.DoNotPrintSeverity + ": never print severity"; + public const SeverityMode OptionSeverityModeDefaultValue = SeverityMode.Automatic; + + public virtual SeverityMode SeverityMode => _currentSettings.SeverityMode ?? OptionSeverityModeDefaultValue; public const string OptionSkipOriginCheck = "Skip check of file origin"; diff --git a/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings b/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings index 80731dd3c..c583893c8 100644 --- a/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings +++ b/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings @@ -1,37 +1,37 @@ - - - - -testdirectory=$(TestDir) - $(SolutionDir)Tests\Returns0.bat - $(SolutionDir)Tests\Returns1.bat - false - true - false - false - 4 - 1 - false - true - false - false - 0 - .*Tests.*.exe - - 30 - ${SolutionDir} - C:\fooDir;C:\barDir - - - - true - true - false - - - - - - + + + + -testdirectory=$(TestDir) + $(SolutionDir)Tests\Returns0.bat + $(SolutionDir)Tests\Returns1.bat + false + true + false + Automatic + Automatic + 4 + 1 + false + true + false + false + 0 + .*Tests.*.exe + + 30 + ${SolutionDir} + C:\fooDir;C:\barDir + + + + true + true + false + + + + + \ No newline at end of file diff --git a/GoogleTestAdapter/TestAdapter.Tests/Framework/VsTestFrameworkLoggerTests.cs b/GoogleTestAdapter/TestAdapter.Tests/Framework/VsTestFrameworkLoggerTests.cs index b0c48cb23..c9c679b16 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/Framework/VsTestFrameworkLoggerTests.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/Framework/VsTestFrameworkLoggerTests.cs @@ -16,7 +16,7 @@ public override void SetUp() { base.SetUp(); - _logger = new VsTestFrameworkLogger(MockVsLogger.Object, () => MockOptions.Object.OutputMode, () => MockOptions.Object.TimestampOutput); + _logger = new VsTestFrameworkLogger(MockVsLogger.Object, () => MockOptions.Object.OutputMode, () => MockOptions.Object.TimestampMode, () => MockOptions.Object.SeverityMode); } diff --git a/GoogleTestAdapter/TestAdapter/CommonFunctions.cs b/GoogleTestAdapter/TestAdapter/CommonFunctions.cs index 52c67e897..f7ab86b73 100644 --- a/GoogleTestAdapter/TestAdapter/CommonFunctions.cs +++ b/GoogleTestAdapter/TestAdapter/CommonFunctions.cs @@ -57,7 +57,8 @@ public static void CreateEnvironment(IRunSettings runSettings, IMessageLogger me var settingsWrapper = new SettingsWrapper(ourRunSettings, solutionDir); - var loggerAdapter = new VsTestFrameworkLogger(messageLogger, () => settingsWrapper.OutputMode, () => settingsWrapper.TimestampOutput); + var loggerAdapter = new VsTestFrameworkLogger(messageLogger, () => settingsWrapper.OutputMode, + () => settingsWrapper.TimestampMode, () => settingsWrapper.SeverityMode); var regexParser = new RegexTraitParser(loggerAdapter); settingsWrapper.RegexTraitParser = regexParser; @@ -170,6 +171,14 @@ private static void LogWarningsForDeprecatedSettings(RunSettingsContainer runSet logger.LogWarning($"True => {DebuggerKind.Native}"); } + var timestepOutputProperty = typeof(RunSettings).GetProperty(nameof(RunSettings.TimestampOutput)); + if (HasSetting(runSettingsContainer, timestepOutputProperty)) + { + logger.LogWarning($"GTA option '{nameof(IGoogleTestAdapterSettings.TimestampOutput)}' does not have any effect any more - check your settings files and replace any occurence with new option '{nameof(IGoogleTestAdapterSettings.TimestampMode)}' as follows:"); + logger.LogWarning($"False => {TimestampMode.DoNotPrintTimestamp}"); + logger.LogWarning($"True => {TimestampMode.PrintTimestamp}"); + } + var showReleaseNotesProperty = typeof(RunSettings).GetProperty(nameof(RunSettings.ShowReleaseNotes)); if (HasSetting(runSettingsContainer, showReleaseNotesProperty)) { diff --git a/GoogleTestAdapter/TestAdapter/Framework/VsTestFrameworkLogger.cs b/GoogleTestAdapter/TestAdapter/Framework/VsTestFrameworkLogger.cs index 512f23fb6..cbc30a8aa 100644 --- a/GoogleTestAdapter/TestAdapter/Framework/VsTestFrameworkLogger.cs +++ b/GoogleTestAdapter/TestAdapter/Framework/VsTestFrameworkLogger.cs @@ -9,38 +9,51 @@ namespace GoogleTestAdapter.TestAdapter.Framework public class VsTestFrameworkLogger : LoggerBase { private readonly IMessageLogger _logger; - private readonly Func _timeStampOutput; + private readonly Func _timeStampMode; + private readonly Func _severityMode; - public VsTestFrameworkLogger(IMessageLogger logger, Func outputMode, Func timestampOutput) + public VsTestFrameworkLogger(IMessageLogger logger, Func outputMode, Func timestampMode, Func severityMode) : base(outputMode) { _logger = logger; - _timeStampOutput = timestampOutput; + _timeStampMode = timestampMode; + _severityMode = severityMode; } public override void Log(Severity severity, string message) { - switch (severity) + TestMessageLevel level = GetTestMessageLevel(severity); + + var timestampMode = _timeStampMode(); + string timestamp = ""; + if (timestampMode == TimestampMode.PrintTimestamp || + timestampMode == TimestampMode.Automatic && VsVersionUtils.GetVisualStudioVersion() < VsVersion.VS2017) { - case Severity.Info: - LogSafe(TestMessageLevel.Informational, message); - break; - case Severity.Warning: - LogSafe(TestMessageLevel.Warning, $"Warning: {message}"); - break; - case Severity.Error: - LogSafe(TestMessageLevel.Error, $"ERROR: {message}"); - break; - default: - throw new Exception($"Unknown enum literal: {severity}"); + timestamp = Utils.GetTimestamp(); } - } - private void LogSafe(TestMessageLevel level, string message) - { - if (_timeStampOutput()) - Utils.TimestampMessage(ref message); + var severityMode = _severityMode(); + string severityString = ""; + if (severityMode == SeverityMode.PrintSeverity || + severityMode == SeverityMode.Automatic && VsVersionUtils.GetVisualStudioVersion() < VsVersion.VS2017) + { + severityString = GetSeverity(level); + } + + if (string.IsNullOrWhiteSpace(timestamp)) + { + if (!string.IsNullOrWhiteSpace(severityString)) + { + message = $"{severityString} - {message}"; + } + } + else + { + message = string.IsNullOrWhiteSpace(severityString) + ? $"{timestamp} - {message}" + : $"{timestamp} {severityString} - {message}"; + } if (string.IsNullOrWhiteSpace(message)) { @@ -58,6 +71,32 @@ private void LogSafe(TestMessageLevel level, string message) }); } + private TestMessageLevel GetTestMessageLevel(Severity severity) + { + switch (severity) + { + case Severity.Info: + return TestMessageLevel.Informational; + case Severity.Warning: + return TestMessageLevel.Warning; + case Severity.Error: + return TestMessageLevel.Error; + default: + throw new Exception($"Unknown enum literal: {severity}"); + } + } + + private string GetSeverity(TestMessageLevel level) + { + switch (level) + { + case TestMessageLevel.Informational: return ""; + case TestMessageLevel.Warning: return "Warning"; + case TestMessageLevel.Error: return "ERROR"; + default: + throw new InvalidOperationException($"Unknown literal {level}"); + } + } } } \ No newline at end of file diff --git a/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd b/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd index 9f788952a..92da2f36a 100644 --- a/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd +++ b/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd @@ -71,7 +71,29 @@ - + + + Deprecated + + + + + + + + + + + + + + + + + + + + Deprecated diff --git a/GoogleTestAdapter/Tests.Common/Fakes/FakeLogger.cs b/GoogleTestAdapter/Tests.Common/Fakes/FakeLogger.cs index e1de975ab..29b91ac41 100644 --- a/GoogleTestAdapter/Tests.Common/Fakes/FakeLogger.cs +++ b/GoogleTestAdapter/Tests.Common/Fakes/FakeLogger.cs @@ -25,7 +25,9 @@ public FakeLogger(Func outputMode, bool timestampLogMessages = true) public override void Log(Severity severity, string message) { if (_timeStampLogMessages) - Utils.TimestampMessage(ref message); + { + message = $"{Utils.GetTimestamp()} - {message}"; + } lock (this) { diff --git a/GoogleTestAdapter/Tests.Common/TestsBase.cs b/GoogleTestAdapter/Tests.Common/TestsBase.cs index d46914343..6d9cd8d30 100644 --- a/GoogleTestAdapter/Tests.Common/TestsBase.cs +++ b/GoogleTestAdapter/Tests.Common/TestsBase.cs @@ -79,7 +79,8 @@ public static void SetupOptions(Mock mockOptions) mockOptions.Setup(o => o.ShuffleTestsSeed).Returns(SettingsWrapper.OptionShuffleTestsSeedDefaultValue); mockOptions.Setup(o => o.ParseSymbolInformation).Returns(SettingsWrapper.OptionParseSymbolInformationDefaultValue); mockOptions.Setup(o => o.OutputMode).Returns(SettingsWrapper.OptionOutputModeDefaultValue); - mockOptions.Setup(o => o.TimestampOutput).Returns(SettingsWrapper.OptionTimestampOutputDefaultValue); + mockOptions.Setup(o => o.TimestampMode).Returns(TimestampMode.DoNotPrintTimestamp); + mockOptions.Setup(o => o.SeverityMode).Returns(SeverityMode.PrintSeverity); mockOptions.Setup(o => o.AdditionalTestExecutionParam) .Returns(SettingsWrapper.OptionAdditionalTestExecutionParamsDefaultValue); mockOptions.Setup(o => o.BatchForTestSetup).Returns(SettingsWrapper.OptionBatchForTestSetupDefaultValue); diff --git a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs index 3db20b822..dfb070581 100644 --- a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs @@ -247,7 +247,8 @@ private RunSettings GetRunSettingsFromOptionPages() { PrintTestOutput = _generalOptions.PrintTestOutput, OutputMode = _generalOptions.OutputMode, - TimestampOutput = _generalOptions.TimestampOutput, + TimestampMode = _generalOptions.TimestampMode, + SeverityMode = _generalOptions.SeverityMode, SkipOriginCheck = _generalOptions.SkipOriginCheck, CatchExceptions = _googleTestOptions.CatchExceptions, diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs index eb932d484..d34837934 100644 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs @@ -4,6 +4,7 @@ using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using GoogleTestAdapter.Common; +using Microsoft.VisualStudio.Shell; namespace GoogleTestAdapter.VsPackage.OptionsPages { @@ -36,12 +37,24 @@ public OutputMode OutputMode [Category(SettingsWrapper.CategoryOutputName)] [DisplayName(SettingsWrapper.OptionTimestampOutput)] [Description(SettingsWrapper.OptionTimestampOutputDescription)] - public bool TimestampOutput + [PropertyPageTypeConverter(typeof(TimestampModeConverter))] + public TimestampMode TimestampMode { - get => _timestampOutput; - set => SetAndNotify(ref _timestampOutput, value); + get => _timestampMode; + set => SetAndNotify(ref _timestampMode, value); } - private bool _timestampOutput = SettingsWrapper.OptionTimestampOutputDefaultValue; + private TimestampMode _timestampMode = SettingsWrapper.OptionTimestampOutputDefaultValue; + + [Category(SettingsWrapper.CategoryOutputName)] + [DisplayName(SettingsWrapper.OptionSeverityMode)] + [Description(SettingsWrapper.OptionSeverityModeDescription)] + [PropertyPageTypeConverter(typeof(SeverityModeConverter))] + public SeverityMode SeverityMode + { + get => _severityMode; + set => SetAndNotify(ref _severityMode, value); + } + private SeverityMode _severityMode = SettingsWrapper.OptionSeverityModeDefaultValue; #endregion diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs index 9470e85be..f5ae09a37 100644 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs @@ -91,6 +91,7 @@ private void UpdateSettings() if (GetAndDeleteValue(GeneralOptionsPage, "UseNewTestExecutionFramework2", bool.Parse, out var useNewTestExecutionFramework2)) { _testExecutionOptions.DebuggerKind = useNewTestExecutionFramework2 ? DebuggerKind.Native : DebuggerKind.VsTestFramework; } if (GetAndDeleteValue(GeneralOptionsPage, nameof(IGoogleTestAdapterSettings.DebugMode), bool.Parse, out var debugMode)) { _generalOptions.OutputMode = debugMode ? OutputMode.Debug : OutputMode.Info; } + if (GetAndDeleteValue(GeneralOptionsPage, nameof(IGoogleTestAdapterSettings.TimestampOutput), bool.Parse, out bool timestampOutput)) { _generalOptions.TimestampMode = GetTimestampMode(timestampOutput); } GetAndDeleteValue(GeneralOptionsPage, nameof(IGoogleTestAdapterSettings.ShowReleaseNotes), bool.Parse, out _); } @@ -118,5 +119,18 @@ private static bool GetAndDeleteValue(string optionsKey, string propertyName, return false; } + private TimestampMode GetTimestampMode(bool timestampOutput) + { + if (timestampOutput) + { + return VsVersionUtils.GetVisualStudioVersion() < VsVersion.VS2017 + ? TimestampMode.Automatic + : TimestampMode.PrintTimestamp; + } + return VsVersionUtils.GetVisualStudioVersion() < VsVersion.VS2017 + ? TimestampMode.DoNotPrintTimestamp + : TimestampMode.Automatic; + } + } } \ No newline at end of file From a9353d7bf14ba43694c0d33ea53f71d1bd835349 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sat, 20 Apr 2019 09:54:30 +0200 Subject: [PATCH 77/81] added option to disable warning/error summary --- GoogleTestAdapter/Common/Common.csproj | 1 + GoogleTestAdapter/Common/SummaryMode.cs | 28 +++++++++++++++++++ .../Settings/IGoogleTestAdapterSettings.cs | 2 ++ .../Core/Settings/RunSettings.cs | 3 ++ .../Core/Settings/SettingsWrapper.cs | 8 ++++++ .../Resources/AllTestSettings.gta.runsettings | 1 + .../TestAdapter/CommonFunctions.cs | 14 +++++++--- .../TestAdapter/GoogleTestAdapterSettings.xsd | 9 ++++++ .../TestAdapter/TestDiscoverer.cs | 2 +- GoogleTestAdapter/TestAdapter/TestExecutor.cs | 4 +-- GoogleTestAdapter/Tests.Common/TestsBase.cs | 1 + .../GoogleTestExtensionOptionsPage.cs | 1 + .../OptionsPages/GeneralOptionsDialogPage.cs | 11 ++++++++ 13 files changed, 78 insertions(+), 7 deletions(-) create mode 100644 GoogleTestAdapter/Common/SummaryMode.cs diff --git a/GoogleTestAdapter/Common/Common.csproj b/GoogleTestAdapter/Common/Common.csproj index acc52cf44..282df41da 100644 --- a/GoogleTestAdapter/Common/Common.csproj +++ b/GoogleTestAdapter/Common/Common.csproj @@ -62,6 +62,7 @@ + diff --git a/GoogleTestAdapter/Common/SummaryMode.cs b/GoogleTestAdapter/Common/SummaryMode.cs new file mode 100644 index 000000000..5158e6b86 --- /dev/null +++ b/GoogleTestAdapter/Common/SummaryMode.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using System.ComponentModel; + +namespace GoogleTestAdapter.Common +{ + [TypeConverter(typeof(SummaryModeConverter))] + public enum SummaryMode + { + Never, + Error, + WarningOrError + } + + public class SummaryModeConverter : EnumConverterBase + { + public const string Never = "Never"; + public const string Error = "If errors occured"; + public const string WarningOrError = "If warnings or errors occured"; + + public SummaryModeConverter() : base(new Dictionary + { + { SummaryMode.Never, Never}, + { SummaryMode.Error, Error}, + { SummaryMode.WarningOrError, WarningOrError}, + }) {} + } + +} \ No newline at end of file diff --git a/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs b/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs index d5fa8acf6..143db4593 100644 --- a/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs +++ b/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs @@ -47,6 +47,7 @@ public interface IGoogleTestAdapterSettings bool? TimestampOutput { get; set; } TimestampMode? TimestampMode { get; set; } SeverityMode? SeverityMode { get; set; } + SummaryMode? SummaryMode { get; set; } bool? ShowReleaseNotes { get; set; } bool? KillProcessesOnCancel { get; set; } bool? SkipOriginCheck { get; set; } @@ -92,6 +93,7 @@ public static void GetUnsetValuesFrom(this IGoogleTestAdapterSettings self, IGoo self.TimestampOutput = self.TimestampOutput ?? other.TimestampOutput; self.TimestampMode = self.TimestampMode ?? other.TimestampMode; self.SeverityMode = self.SeverityMode ?? other.SeverityMode; + self.SummaryMode = self.SummaryMode ?? other.SummaryMode; self.ShowReleaseNotes = self.ShowReleaseNotes ?? other.ShowReleaseNotes; self.KillProcessesOnCancel = self.KillProcessesOnCancel ?? other.KillProcessesOnCancel; self.SkipOriginCheck = self.SkipOriginCheck ?? other.SkipOriginCheck; diff --git a/GoogleTestAdapter/Core/Settings/RunSettings.cs b/GoogleTestAdapter/Core/Settings/RunSettings.cs index e7da54bd7..c26fa4fd0 100644 --- a/GoogleTestAdapter/Core/Settings/RunSettings.cs +++ b/GoogleTestAdapter/Core/Settings/RunSettings.cs @@ -79,6 +79,9 @@ public RunSettings(string projectRegex) public virtual SeverityMode? SeverityMode { get; set; } public bool ShouldSerializeSeverityMode() { return SeverityMode != null; } + public virtual SummaryMode? SummaryMode { get; set; } + public bool ShouldSerializeSummaryMode() { return SummaryMode != null; } + public virtual bool? ShowReleaseNotes { get; set; } public bool ShouldSerializeShowReleaseNotes() { return ShowReleaseNotes != null; } diff --git a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs index b7fe15a32..45986c9a0 100644 --- a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs +++ b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs @@ -192,6 +192,14 @@ public virtual void CheckCorrectUsage(string executable) public virtual SeverityMode SeverityMode => _currentSettings.SeverityMode ?? OptionSeverityModeDefaultValue; + public const string OptionSummaryMode = "Print summary"; + public const string OptionSummaryModeDescription = + "Controls whether a summary of warnings and errors is printed after test discovery/execution."; + public const SummaryMode OptionSummaryModeDefaultValue = SummaryMode.WarningOrError; + + public virtual SummaryMode SummaryMode => _currentSettings.SummaryMode ?? OptionSummaryModeDefaultValue; + + public const string OptionSkipOriginCheck = "Skip check of file origin"; public const string OptionSkipOriginCheckDescription = "If true, it will not be checked whether executables originate from this computer. Note that this might impose security risks, e.g. when building downloaded solutions. This setting can only be changed via VS Options."; diff --git a/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings b/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings index c583893c8..946192f2c 100644 --- a/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings +++ b/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings @@ -11,6 +11,7 @@ false Automatic Automatic + Error 4 1 false diff --git a/GoogleTestAdapter/TestAdapter/CommonFunctions.cs b/GoogleTestAdapter/TestAdapter/CommonFunctions.cs index f7ab86b73..a4e348ab5 100644 --- a/GoogleTestAdapter/TestAdapter/CommonFunctions.cs +++ b/GoogleTestAdapter/TestAdapter/CommonFunctions.cs @@ -18,20 +18,26 @@ public static class CommonFunctions { public const string GtaSettingsEnvVariable = "GTA_FALLBACK_SETTINGS"; - public static void ReportErrors(ILogger logger, string phase, OutputMode outputMode) + public static void ReportErrors(ILogger logger, string phase, OutputMode outputMode, SummaryMode summaryMode) { - IList errors = logger.GetMessages(Severity.Error, Severity.Warning); - if (errors.Count == 0) + if (summaryMode == SummaryMode.Never) return; bool hasErrors = logger.GetMessages(Severity.Error).Count > 0; + if (!hasErrors && summaryMode == SummaryMode.Error) + return; + + IList errors = logger.GetMessages(Severity.Error, Severity.Warning); + if (!errors.Any()) + return; + string hint = outputMode > OutputMode.Info ? "" : " (enable debug mode for more information)"; string jointErrors = string.Join(Environment.NewLine, errors); string message = $"{Environment.NewLine}================{Environment.NewLine}" - + $"The following errors and warnings occured during {phase}{hint}:{Environment.NewLine}" + + $"The following warnings and errors occured during {phase}{hint}:{Environment.NewLine}" + jointErrors; if (hasErrors) diff --git a/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd b/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd index 92da2f36a..7a65f8ae2 100644 --- a/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd +++ b/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd @@ -94,6 +94,15 @@ + + + + + + + + + Deprecated diff --git a/GoogleTestAdapter/TestAdapter/TestDiscoverer.cs b/GoogleTestAdapter/TestAdapter/TestDiscoverer.cs index f57d24a2c..23fbad02d 100644 --- a/GoogleTestAdapter/TestAdapter/TestDiscoverer.cs +++ b/GoogleTestAdapter/TestAdapter/TestDiscoverer.cs @@ -63,7 +63,7 @@ public void DiscoverTests(IEnumerable executables, IDiscoveryContext dis _logger.LogError($"Exception while discovering tests: {e}"); } - CommonFunctions.ReportErrors(_logger, "test discovery", _settings.OutputMode); + CommonFunctions.ReportErrors(_logger, "test discovery", _settings.OutputMode, _settings.SummaryMode); } private bool IsSupportedVisualStudioVersion() diff --git a/GoogleTestAdapter/TestAdapter/TestExecutor.cs b/GoogleTestAdapter/TestAdapter/TestExecutor.cs index 1aae57a28..944760838 100644 --- a/GoogleTestAdapter/TestAdapter/TestExecutor.cs +++ b/GoogleTestAdapter/TestAdapter/TestExecutor.cs @@ -56,7 +56,7 @@ public void RunTests(IEnumerable executables, IRunContext runContext, IF _logger.LogError($"Exception while running tests: {e}"); } - CommonFunctions.ReportErrors(_logger, "test execution", _settings.OutputMode); + CommonFunctions.ReportErrors(_logger, "test execution", _settings.OutputMode, _settings.SummaryMode); } public void RunTests(IEnumerable vsTestCasesToRun, IRunContext runContext, IFrameworkHandle frameworkHandle) @@ -70,7 +70,7 @@ public void RunTests(IEnumerable vsTestCasesToRun, IRunContext runCo _logger.LogError("Exception while running tests: " + e); } - CommonFunctions.ReportErrors(_logger, "test execution", _settings.OutputMode); + CommonFunctions.ReportErrors(_logger, "test execution", _settings.OutputMode, _settings.SummaryMode); } public void Cancel() diff --git a/GoogleTestAdapter/Tests.Common/TestsBase.cs b/GoogleTestAdapter/Tests.Common/TestsBase.cs index 6d9cd8d30..6ef842ecf 100644 --- a/GoogleTestAdapter/Tests.Common/TestsBase.cs +++ b/GoogleTestAdapter/Tests.Common/TestsBase.cs @@ -81,6 +81,7 @@ public static void SetupOptions(Mock mockOptions) mockOptions.Setup(o => o.OutputMode).Returns(SettingsWrapper.OptionOutputModeDefaultValue); mockOptions.Setup(o => o.TimestampMode).Returns(TimestampMode.DoNotPrintTimestamp); mockOptions.Setup(o => o.SeverityMode).Returns(SeverityMode.PrintSeverity); + mockOptions.Setup(o => o.SummaryMode).Returns(SettingsWrapper.OptionSummaryModeDefaultValue); mockOptions.Setup(o => o.AdditionalTestExecutionParam) .Returns(SettingsWrapper.OptionAdditionalTestExecutionParamsDefaultValue); mockOptions.Setup(o => o.BatchForTestSetup).Returns(SettingsWrapper.OptionBatchForTestSetupDefaultValue); diff --git a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs index dfb070581..a7fcdd440 100644 --- a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs @@ -249,6 +249,7 @@ private RunSettings GetRunSettingsFromOptionPages() OutputMode = _generalOptions.OutputMode, TimestampMode = _generalOptions.TimestampMode, SeverityMode = _generalOptions.SeverityMode, + SummaryMode = _generalOptions.SummaryMode, SkipOriginCheck = _generalOptions.SkipOriginCheck, CatchExceptions = _googleTestOptions.CatchExceptions, diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs index d34837934..eb2c90595 100644 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs @@ -56,6 +56,17 @@ public SeverityMode SeverityMode } private SeverityMode _severityMode = SettingsWrapper.OptionSeverityModeDefaultValue; + [Category(SettingsWrapper.CategoryOutputName)] + [DisplayName(SettingsWrapper.OptionSummaryMode)] + [Description(SettingsWrapper.OptionSummaryModeDescription)] + [PropertyPageTypeConverter(typeof(SummaryModeConverter))] + public SummaryMode SummaryMode + { + get => _summaryMode; + set => SetAndNotify(ref _summaryMode, value); + } + private SummaryMode _summaryMode = SettingsWrapper.OptionSummaryModeDefaultValue; + #endregion #region Security From d85ec210075370d94bf9fa3f28e6e67f3c5beb20 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sun, 21 Apr 2019 08:42:17 +0200 Subject: [PATCH 78/81] added option to tag output with [GTA]; VsVersion is not loaded lazily any more --- .../Settings/SettingsWrapperTests.cs | 4 +- .../Settings/IGoogleTestAdapterSettings.cs | 2 + .../Core/Settings/RunSettings.cs | 3 + .../Core/Settings/SettingsWrapper.cs | 8 ++ .../Resources/AllTestSettings.gta.runsettings | 1 + .../Framework/VsTestFrameworkLoggerTests.cs | 3 +- .../TestAdapter/CommonFunctions.cs | 4 +- .../TestAdapter/DataConversionExtensions.cs | 23 +++-- .../Framework/VSTestFrameworkReporter.cs | 2 +- .../Framework/VsTestFrameworkLogger.cs | 88 +++++++++---------- .../TestAdapter/Framework/VsVersion.cs | 46 ++++++---- .../TestAdapter/GoogleTestAdapterSettings.xsd | 1 + .../TestAdapter/TestDiscoverer.cs | 2 +- GoogleTestAdapter/Tests.Common/TestsBase.cs | 2 + .../GoogleTestExtensionOptionsPage.cs | 1 + .../OptionsPages/GeneralOptionsDialogPage.cs | 10 +++ .../OptionsPages/OptionsUpdater.cs | 6 +- 17 files changed, 127 insertions(+), 79 deletions(-) diff --git a/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs b/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs index 229f474c8..add2b41d9 100644 --- a/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs +++ b/GoogleTestAdapter/Core.Tests/Settings/SettingsWrapperTests.cs @@ -522,7 +522,9 @@ public void ToString_PrintsCorrectly() optionsString.Should().Contain("TestNameSeparator: ''"); optionsString.Should().Contain("ParseSymbolInformation: True"); optionsString.Should().Contain("OutputMode: Info"); - optionsString.Should().Contain("TimestampOutput: False"); + optionsString.Should().Contain("TimestampMode: Automatic"); + optionsString.Should().Contain("SeverityMode: Automatic"); + optionsString.Should().Contain("SummaryMode: WarningOrError"); optionsString.Should().Contain("AdditionalTestExecutionParam: ''"); optionsString.Should().Contain("BatchForTestSetup: 'C:\\\\myfolder\\myfile.xml'"); optionsString.Should().Contain("BatchForTestTeardown: ''"); diff --git a/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs b/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs index 143db4593..771a18a45 100644 --- a/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs +++ b/GoogleTestAdapter/Core/Settings/IGoogleTestAdapterSettings.cs @@ -48,6 +48,7 @@ public interface IGoogleTestAdapterSettings TimestampMode? TimestampMode { get; set; } SeverityMode? SeverityMode { get; set; } SummaryMode? SummaryMode { get; set; } + bool? PrefixOutputWithGta { get; set; } bool? ShowReleaseNotes { get; set; } bool? KillProcessesOnCancel { get; set; } bool? SkipOriginCheck { get; set; } @@ -94,6 +95,7 @@ public static void GetUnsetValuesFrom(this IGoogleTestAdapterSettings self, IGoo self.TimestampMode = self.TimestampMode ?? other.TimestampMode; self.SeverityMode = self.SeverityMode ?? other.SeverityMode; self.SummaryMode = self.SummaryMode ?? other.SummaryMode; + self.PrefixOutputWithGta = self.PrefixOutputWithGta ?? other.PrefixOutputWithGta; self.ShowReleaseNotes = self.ShowReleaseNotes ?? other.ShowReleaseNotes; self.KillProcessesOnCancel = self.KillProcessesOnCancel ?? other.KillProcessesOnCancel; self.SkipOriginCheck = self.SkipOriginCheck ?? other.SkipOriginCheck; diff --git a/GoogleTestAdapter/Core/Settings/RunSettings.cs b/GoogleTestAdapter/Core/Settings/RunSettings.cs index c26fa4fd0..938ec92a4 100644 --- a/GoogleTestAdapter/Core/Settings/RunSettings.cs +++ b/GoogleTestAdapter/Core/Settings/RunSettings.cs @@ -82,6 +82,9 @@ public RunSettings(string projectRegex) public virtual SummaryMode? SummaryMode { get; set; } public bool ShouldSerializeSummaryMode() { return SummaryMode != null; } + public virtual bool? PrefixOutputWithGta { get; set; } + public bool ShouldSerializePrefixOutputWithGta() { return PrefixOutputWithGta != null; } + public virtual bool? ShowReleaseNotes { get; set; } public bool ShouldSerializeShowReleaseNotes() { return ShowReleaseNotes != null; } diff --git a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs index 45986c9a0..8df076100 100644 --- a/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs +++ b/GoogleTestAdapter/Core/Settings/SettingsWrapper.cs @@ -200,6 +200,14 @@ public virtual void CheckCorrectUsage(string executable) public virtual SummaryMode SummaryMode => _currentSettings.SummaryMode ?? OptionSummaryModeDefaultValue; + public const string OptionPrefixOutputWithGta = "Prefix output with [GTA]"; + public const string OptionPrefixOutputWithGtaDescription = + "Controls whether the prefix [GTA] is added to GTA's output."; + public const bool OptionPrefixOutputWithGtaDefaultValue = false; + + public virtual bool PrefixOutputWithGta => _currentSettings.PrefixOutputWithGta ?? OptionPrefixOutputWithGtaDefaultValue; + + public const string OptionSkipOriginCheck = "Skip check of file origin"; public const string OptionSkipOriginCheckDescription = "If true, it will not be checked whether executables originate from this computer. Note that this might impose security risks, e.g. when building downloaded solutions. This setting can only be changed via VS Options."; diff --git a/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings b/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings index 946192f2c..12723c294 100644 --- a/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings +++ b/GoogleTestAdapter/Resources/AllTestSettings.gta.runsettings @@ -12,6 +12,7 @@ Automatic Automatic Error + true 4 1 false diff --git a/GoogleTestAdapter/TestAdapter.Tests/Framework/VsTestFrameworkLoggerTests.cs b/GoogleTestAdapter/TestAdapter.Tests/Framework/VsTestFrameworkLoggerTests.cs index c9c679b16..768017ad7 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/Framework/VsTestFrameworkLoggerTests.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/Framework/VsTestFrameworkLoggerTests.cs @@ -16,7 +16,8 @@ public override void SetUp() { base.SetUp(); - _logger = new VsTestFrameworkLogger(MockVsLogger.Object, () => MockOptions.Object.OutputMode, () => MockOptions.Object.TimestampMode, () => MockOptions.Object.SeverityMode); + _logger = new VsTestFrameworkLogger(MockVsLogger.Object, () => MockOptions.Object.OutputMode, + () => MockOptions.Object.TimestampMode, () => MockOptions.Object.SeverityMode, () => MockOptions.Object.PrefixOutputWithGta); } diff --git a/GoogleTestAdapter/TestAdapter/CommonFunctions.cs b/GoogleTestAdapter/TestAdapter/CommonFunctions.cs index a4e348ab5..a7414f980 100644 --- a/GoogleTestAdapter/TestAdapter/CommonFunctions.cs +++ b/GoogleTestAdapter/TestAdapter/CommonFunctions.cs @@ -64,7 +64,7 @@ public static void CreateEnvironment(IRunSettings runSettings, IMessageLogger me var settingsWrapper = new SettingsWrapper(ourRunSettings, solutionDir); var loggerAdapter = new VsTestFrameworkLogger(messageLogger, () => settingsWrapper.OutputMode, - () => settingsWrapper.TimestampMode, () => settingsWrapper.SeverityMode); + () => settingsWrapper.TimestampMode, () => settingsWrapper.SeverityMode, () => settingsWrapper.PrefixOutputWithGta); var regexParser = new RegexTraitParser(loggerAdapter); settingsWrapper.RegexTraitParser = regexParser; @@ -200,7 +200,7 @@ private static bool HasSetting(RunSettingsContainer runSettingsContainer, Proper public static void LogVisualStudioVersion(ILogger logger) { - VsVersion version = VsVersionUtils.GetVisualStudioVersion(logger); + VsVersion version = VsVersionUtils.VsVersion; switch (version) { // warning printed while checking version diff --git a/GoogleTestAdapter/TestAdapter/DataConversionExtensions.cs b/GoogleTestAdapter/TestAdapter/DataConversionExtensions.cs index 661b1f504..e84096683 100644 --- a/GoogleTestAdapter/TestAdapter/DataConversionExtensions.cs +++ b/GoogleTestAdapter/TestAdapter/DataConversionExtensions.cs @@ -98,7 +98,7 @@ public static VsTestOutcome ToVsTestOutcome(this TestOutcome testOutcome) case TestOutcome.NotFound: return VsTestOutcome.NotFound; default: - throw new Exception(); + throw new InvalidOperationException($"Unknown enum literal: {testOutcome}"); } } @@ -106,17 +106,26 @@ public static Severity GetSeverity(this TestMessageLevel level) { switch (level) { - case TestMessageLevel.Informational: - return Severity.Info; - case TestMessageLevel.Warning: - return Severity.Warning; - case TestMessageLevel.Error: - return Severity.Error; + case TestMessageLevel.Informational: return Severity.Info; + case TestMessageLevel.Warning: return Severity.Warning; + case TestMessageLevel.Error: return Severity.Error; default: throw new InvalidOperationException($"Unknown enum literal: {level}"); } } + public static TestMessageLevel GetTestMessageLevel(this Severity severity) + { + switch (severity) + { + case Severity.Info: return TestMessageLevel.Informational; + case Severity.Warning: return TestMessageLevel.Warning; + case Severity.Error: return TestMessageLevel.Error; + default: + throw new InvalidOperationException($"Unknown enum literal: {severity}"); + } + } + } } \ No newline at end of file diff --git a/GoogleTestAdapter/TestAdapter/Framework/VSTestFrameworkReporter.cs b/GoogleTestAdapter/TestAdapter/Framework/VSTestFrameworkReporter.cs index 846d07646..2e4bd4931 100644 --- a/GoogleTestAdapter/TestAdapter/Framework/VSTestFrameworkReporter.cs +++ b/GoogleTestAdapter/TestAdapter/Framework/VSTestFrameworkReporter.cs @@ -95,7 +95,7 @@ public void ReportTestResults(IEnumerable testResults) private bool TestReportingNeedsToBeThrottled() { - return VsVersionUtils.GetVisualStudioVersion(_logger).NeedsToBeThrottled(); + return VsVersionUtils.VsVersion.NeedsToBeThrottled(); } private void ReportTestResult(TestResult testResult) diff --git a/GoogleTestAdapter/TestAdapter/Framework/VsTestFrameworkLogger.cs b/GoogleTestAdapter/TestAdapter/Framework/VsTestFrameworkLogger.cs index cbc30a8aa..cae8fcfa7 100644 --- a/GoogleTestAdapter/TestAdapter/Framework/VsTestFrameworkLogger.cs +++ b/GoogleTestAdapter/TestAdapter/Framework/VsTestFrameworkLogger.cs @@ -1,4 +1,5 @@ using System; +using System.Text; using GoogleTestAdapter.Common; using GoogleTestAdapter.Helpers; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; @@ -11,78 +12,75 @@ public class VsTestFrameworkLogger : LoggerBase private readonly IMessageLogger _logger; private readonly Func _timeStampMode; private readonly Func _severityMode; + private readonly Func _prefixOutput; - public VsTestFrameworkLogger(IMessageLogger logger, Func outputMode, Func timestampMode, Func severityMode) + public VsTestFrameworkLogger(IMessageLogger logger, Func outputMode, Func timestampMode, Func severityMode, Func prefixOutput) : base(outputMode) { _logger = logger; _timeStampMode = timestampMode; _severityMode = severityMode; + _prefixOutput = prefixOutput; } public override void Log(Severity severity, string message) { - TestMessageLevel level = GetTestMessageLevel(severity); + TestMessageLevel level = severity.GetTestMessageLevel(); - var timestampMode = _timeStampMode(); - string timestamp = ""; - if (timestampMode == TimestampMode.PrintTimestamp || - timestampMode == TimestampMode.Automatic && VsVersionUtils.GetVisualStudioVersion() < VsVersion.VS2017) - { - timestamp = Utils.GetTimestamp(); - } - - var severityMode = _severityMode(); - string severityString = ""; - if (severityMode == SeverityMode.PrintSeverity || - severityMode == SeverityMode.Automatic && VsVersionUtils.GetVisualStudioVersion() < VsVersion.VS2017) - { - severityString = GetSeverity(level); - } + var builder = new StringBuilder(); + AppendOutputPrefix(builder, level); + builder.Append(message); - if (string.IsNullOrWhiteSpace(timestamp)) - { - if (!string.IsNullOrWhiteSpace(severityString)) - { - message = $"{severityString} - {message}"; - } - } - else - { - message = string.IsNullOrWhiteSpace(severityString) - ? $"{timestamp} - {message}" - : $"{timestamp} {severityString} - {message}"; - } - - if (string.IsNullOrWhiteSpace(message)) + var finalMessage = builder.ToString(); + if (string.IsNullOrWhiteSpace(finalMessage)) { // Visual Studio 2013 is very picky about empty lines... // But it accepts an 'INVISIBLE SEPARATOR' (U+2063) :-) - message = "\u2063"; + finalMessage = "\u2063"; } - _logger.SendMessage(level, message); + _logger.SendMessage(level, finalMessage); ReportFinalLogEntry( new LogEntry { Severity = level.GetSeverity(), - Message = message + Message = finalMessage }); } - private TestMessageLevel GetTestMessageLevel(Severity severity) + private void AppendOutputPrefix(StringBuilder builder, TestMessageLevel level) { - switch (severity) + if (_prefixOutput()) { - case Severity.Info: - return TestMessageLevel.Informational; - case Severity.Warning: - return TestMessageLevel.Warning; - case Severity.Error: - return TestMessageLevel.Error; - default: - throw new Exception($"Unknown enum literal: {severity}"); + builder.Append("GTA"); + } + + var timestampMode = _timeStampMode(); + if (timestampMode == TimestampMode.PrintTimestamp || + timestampMode == TimestampMode.Automatic && !VsVersionUtils.VsVersion.PrintsTimeStampAndSeverity()) + { + if (builder.Length > 0) + builder.Append(' '); + + builder.Append(Utils.GetTimestamp()); + } + + var severityMode = _severityMode(); + if (level > TestMessageLevel.Informational && + (severityMode == SeverityMode.PrintSeverity || + severityMode == SeverityMode.Automatic && !VsVersionUtils.VsVersion.PrintsTimeStampAndSeverity())) + { + if (builder.Length > 0) + builder.Append(' '); + + builder.Append(GetSeverity(level)); + } + + if (builder.Length > 0) + { + builder.Insert(0, '['); + builder.Append("] "); } } diff --git a/GoogleTestAdapter/TestAdapter/Framework/VsVersion.cs b/GoogleTestAdapter/TestAdapter/Framework/VsVersion.cs index f3da7ba90..f7f4914e7 100644 --- a/GoogleTestAdapter/TestAdapter/Framework/VsVersion.cs +++ b/GoogleTestAdapter/TestAdapter/Framework/VsVersion.cs @@ -4,7 +4,6 @@ using System.IO; using System.Linq; using System.Text.RegularExpressions; -using GoogleTestAdapter.Common; using GoogleTestAdapter.TestAdapter.Helpers; using Process = System.Diagnostics.Process; @@ -68,6 +67,21 @@ public static bool NeedsToBeThrottled(this VsVersion version) return false; } } + + public static bool PrintsTimeStampAndSeverity(this VsVersion version) + { + switch (version) + { + case VsVersion.Unknown: + case VsVersion.VS2012: + case VsVersion.VS2012_1: + case VsVersion.VS2013: + case VsVersion.VS2015: + return false; + default: + return true; + } + } } public static class VsVersionUtils @@ -80,27 +94,23 @@ public static class VsVersionUtils public static readonly VsVersion FirstSupportedVersion = VsVersion.VS2012_1; public static readonly VsVersion LastSupportedVersion = Enum.GetValues(typeof(VsVersion)).Cast().Max(); - private static readonly object Lock = new object(); - private static VsVersion? _version; + public static readonly VsVersion VsVersion; - public static VsVersion GetVisualStudioVersion(ILogger logger = null) + static VsVersionUtils() { - lock (Lock) - { - if (_version.HasValue) - return _version.Value; + VsVersion = GetVisualStudioVersion(); + } - try - { - _version = GetVsVersionFromProcess(); - } - catch (Exception e) - { - logger?.LogError($"Could not find out VisualStudio version: {e.Message}"); - _version = VsVersion.Unknown; - } - return _version.Value; + private static VsVersion GetVisualStudioVersion() + { + try + { + return GetVsVersionFromProcess(); + } + catch (Exception) + { + return VsVersion.Unknown; } } diff --git a/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd b/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd index 7a65f8ae2..67ecdd6b3 100644 --- a/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd +++ b/GoogleTestAdapter/TestAdapter/GoogleTestAdapterSettings.xsd @@ -103,6 +103,7 @@ + Deprecated diff --git a/GoogleTestAdapter/TestAdapter/TestDiscoverer.cs b/GoogleTestAdapter/TestAdapter/TestDiscoverer.cs index 23fbad02d..1ca7ff011 100644 --- a/GoogleTestAdapter/TestAdapter/TestDiscoverer.cs +++ b/GoogleTestAdapter/TestAdapter/TestDiscoverer.cs @@ -68,7 +68,7 @@ public void DiscoverTests(IEnumerable executables, IDiscoveryContext dis private bool IsSupportedVisualStudioVersion() { - var version = VsVersionUtils.GetVisualStudioVersion(_logger); + var version = VsVersionUtils.VsVersion; switch (version) { case VsVersion.Unknown: diff --git a/GoogleTestAdapter/Tests.Common/TestsBase.cs b/GoogleTestAdapter/Tests.Common/TestsBase.cs index 6ef842ecf..0ba0be695 100644 --- a/GoogleTestAdapter/Tests.Common/TestsBase.cs +++ b/GoogleTestAdapter/Tests.Common/TestsBase.cs @@ -82,6 +82,8 @@ public static void SetupOptions(Mock mockOptions) mockOptions.Setup(o => o.TimestampMode).Returns(TimestampMode.DoNotPrintTimestamp); mockOptions.Setup(o => o.SeverityMode).Returns(SeverityMode.PrintSeverity); mockOptions.Setup(o => o.SummaryMode).Returns(SettingsWrapper.OptionSummaryModeDefaultValue); + mockOptions.Setup(o => o.PrefixOutputWithGta) + .Returns(SettingsWrapper.OptionPrefixOutputWithGtaDefaultValue); mockOptions.Setup(o => o.AdditionalTestExecutionParam) .Returns(SettingsWrapper.OptionAdditionalTestExecutionParamsDefaultValue); mockOptions.Setup(o => o.BatchForTestSetup).Returns(SettingsWrapper.OptionBatchForTestSetupDefaultValue); diff --git a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs index a7fcdd440..ea1d09ac8 100644 --- a/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/GoogleTestExtensionOptionsPage.cs @@ -250,6 +250,7 @@ private RunSettings GetRunSettingsFromOptionPages() TimestampMode = _generalOptions.TimestampMode, SeverityMode = _generalOptions.SeverityMode, SummaryMode = _generalOptions.SummaryMode, + PrefixOutputWithGta = _generalOptions.PrefixOutputWithGta, SkipOriginCheck = _generalOptions.SkipOriginCheck, CatchExceptions = _googleTestOptions.CatchExceptions, diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs index eb2c90595..fd54d28b3 100644 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/GeneralOptionsDialogPage.cs @@ -67,6 +67,16 @@ public SummaryMode SummaryMode } private SummaryMode _summaryMode = SettingsWrapper.OptionSummaryModeDefaultValue; + [Category(SettingsWrapper.CategoryOutputName)] + [DisplayName(SettingsWrapper.OptionPrefixOutputWithGta)] + [Description(SettingsWrapper.OptionPrefixOutputWithGtaDescription)] + public bool PrefixOutputWithGta + { + get => _prefixOutputWithGta; + set => SetAndNotify(ref _prefixOutputWithGta, value); + } + private bool _prefixOutputWithGta = SettingsWrapper.OptionPrefixOutputWithGtaDefaultValue; + #endregion #region Security diff --git a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs index f5ae09a37..962d591df 100644 --- a/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs +++ b/GoogleTestAdapter/VsPackage.Shared/OptionsPages/OptionsUpdater.cs @@ -13,7 +13,7 @@ namespace VsPackage.Shared.Settings { public class OptionsUpdater { - private static readonly string OptionsBase = $@"SOFTWARE\Microsoft\VisualStudio\{VsVersionUtils.GetVisualStudioVersion().VersionString()}\DialogPage\GoogleTestAdapter.VsPackage.OptionsPages."; + private static readonly string OptionsBase = $@"SOFTWARE\Microsoft\VisualStudio\{VsVersionUtils.VsVersion.VersionString()}\DialogPage\GoogleTestAdapter.VsPackage.OptionsPages."; private static readonly string GeneralOptionsPage = OptionsBase + "GeneralOptionsDialogPage"; private static readonly string ParallelizationOptionsPage = OptionsBase + "ParallelizationOptionsDialogPage"; @@ -123,11 +123,11 @@ private TimestampMode GetTimestampMode(bool timestampOutput) { if (timestampOutput) { - return VsVersionUtils.GetVisualStudioVersion() < VsVersion.VS2017 + return VsVersionUtils.VsVersion < VsVersion.VS2017 ? TimestampMode.Automatic : TimestampMode.PrintTimestamp; } - return VsVersionUtils.GetVisualStudioVersion() < VsVersion.VS2017 + return VsVersionUtils.VsVersion < VsVersion.VS2017 ? TimestampMode.DoNotPrintTimestamp : TimestampMode.Automatic; } From 97d5b7139181f2cda677826f0baa6a91996e6afe Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sat, 27 Apr 2019 10:02:45 +0200 Subject: [PATCH 79/81] fixed merging problem --- .../TestAdapter.Tests/Settings/HelperFileTests.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/GoogleTestAdapter/TestAdapter.Tests/Settings/HelperFileTests.cs b/GoogleTestAdapter/TestAdapter.Tests/Settings/HelperFileTests.cs index 2bc61ee8c..d7a9e2808 100644 --- a/GoogleTestAdapter/TestAdapter.Tests/Settings/HelperFileTests.cs +++ b/GoogleTestAdapter/TestAdapter.Tests/Settings/HelperFileTests.cs @@ -1,4 +1,5 @@ using System.Linq; +using GoogleTestAdapter.Common; using GoogleTestAdapter.Helpers; using GoogleTestAdapter.ProcessExecution; using GoogleTestAdapter.TestAdapter.ProcessExecution; @@ -22,7 +23,7 @@ public override void SetUp() base.SetUp(); _mockDebuggerAttacher.Reset(); - _mockDebuggerAttacher.Setup(a => a.AttachDebugger(It.IsAny())).Returns(true); + _mockDebuggerAttacher.Setup(a => a.AttachDebugger(It.IsAny(), It.IsAny())).Returns(true); } [TestMethod] From c8dd60b1e947b5ce0d4c87e6cdedb2fee9fbc502 Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Fri, 26 Apr 2019 18:29:32 +0200 Subject: [PATCH 80/81] speedup of test discovery by hacking C#'s ThreadPool --- GoogleTestAdapter/Core/Helpers/Utils.cs | 2 +- .../Core/ProcessExecution/DebuggerKind.cs | 4 +++- .../Core/TestCases/TestCaseFactory.cs | 8 +++++--- GoogleTestAdapter/TestAdapter/CommonFunctions.cs | 14 ++++++++++++++ .../VsPackage.GTA/Resources/ReleaseNotes/0.16.0.md | 1 + 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/GoogleTestAdapter/Core/Helpers/Utils.cs b/GoogleTestAdapter/Core/Helpers/Utils.cs index 4459e22d3..afe357b6c 100644 --- a/GoogleTestAdapter/Core/Helpers/Utils.cs +++ b/GoogleTestAdapter/Core/Helpers/Utils.cs @@ -61,7 +61,7 @@ public static bool SpawnAndWait(Action[] actions, int timeoutInMs = Timeout.Infi var tasks = new Task[actions.Length]; for (int i = 0; i < actions.Length; i++) { - tasks[i] = Task.Factory.StartNew(actions[i]); + tasks[i] = Task.Run(actions[i]); } return Task.WaitAll(tasks, timeoutInMs); diff --git a/GoogleTestAdapter/Core/ProcessExecution/DebuggerKind.cs b/GoogleTestAdapter/Core/ProcessExecution/DebuggerKind.cs index a96ef5737..49bbf66c7 100644 --- a/GoogleTestAdapter/Core/ProcessExecution/DebuggerKind.cs +++ b/GoogleTestAdapter/Core/ProcessExecution/DebuggerKind.cs @@ -11,9 +11,11 @@ public enum DebuggerKind { VsTestFramework, Native, ManagedAndNative } public static class DebuggerKindExtensions { + private static readonly DebuggerKindConverter Converter = new DebuggerKindConverter(); + public static string ToReadableString(this DebuggerKind debuggerKind) { - return TypeDescriptor.GetConverter(typeof(DebuggerKind)).ConvertToString(debuggerKind); + return Converter.ConvertToString(debuggerKind); } } diff --git a/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs b/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs index f1e057e17..6a927210b 100644 --- a/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs +++ b/GoogleTestAdapter/Core/TestCases/TestCaseFactory.cs @@ -83,8 +83,9 @@ void OnReportOutputLine(string line) parser.ReportLine(line); } - var listAndParseTestsTask = new Task(() => + var listAndParseTestsTask = Task.Run(() => { + _logger.VerboseInfo($"Starting test discovery for {_executable}"); executor = _processExecutorFactory.CreateExecutor(false, _logger); processExitCode = executor.ExecuteCommandBlocking( _executable, @@ -92,8 +93,9 @@ void OnReportOutputLine(string line) workingDir, _settings.GetPathExtension(_executable), OnReportOutputLine); - }, TaskCreationOptions.AttachedToParent); - listAndParseTestsTask.Start(); + _logger.VerboseInfo($"Finished execution of {_executable}"); + }); + _logger.VerboseInfo($"Scheduled test discovery for {_executable}"); if (!listAndParseTestsTask.Wait(TimeSpan.FromSeconds(_settings.TestDiscoveryTimeoutInSeconds))) { diff --git a/GoogleTestAdapter/TestAdapter/CommonFunctions.cs b/GoogleTestAdapter/TestAdapter/CommonFunctions.cs index 2adccd343..509d45d58 100644 --- a/GoogleTestAdapter/TestAdapter/CommonFunctions.cs +++ b/GoogleTestAdapter/TestAdapter/CommonFunctions.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; using System.Reflection; +using System.Threading; using GoogleTestAdapter.Common; using GoogleTestAdapter.Helpers; using GoogleTestAdapter.ProcessExecution; @@ -17,6 +18,7 @@ namespace GoogleTestAdapter.TestAdapter public static class CommonFunctions { public const string GtaSettingsEnvVariable = "GTA_FALLBACK_SETTINGS"; + private const int MinWorkerThreads = 32; public static void ReportErrors(ILogger logger, string phase, OutputMode outputMode, SummaryMode summaryMode) { @@ -72,6 +74,8 @@ public static void CreateEnvironment(IRunSettings runSettings, IMessageLogger me settings = settingsWrapper; logger = loggerAdapter; + + SpeedupThreadPoolHack(logger); } private static RunSettingsProvider SafeGetRunSettingsProvider(IRunSettings runSettings, IMessageLogger messageLogger) @@ -225,5 +229,15 @@ private static bool AreFallbackSettingsConfigured() } } + // after https://stackoverflow.com/questions/22036365/newly-created-threads-using-task-factory-startnew-starts-very-slowly/22074892#22074892 + private static void SpeedupThreadPoolHack(ILogger logger) + { + int workerThreadsMin, workerThreadsMax, completionPortThreadsMin, completionPortThreadsMax; + ThreadPool.GetMinThreads(out workerThreadsMin, out completionPortThreadsMin); + ThreadPool.GetMaxThreads(out workerThreadsMax, out completionPortThreadsMax); + + ThreadPool.SetMinThreads(MinWorkerThreads, completionPortThreadsMin); + logger.VerboseInfo($"Tuned ThreadPool. MinThreads: ({workerThreadsMin}->{MinWorkerThreads}, {completionPortThreadsMin}); MaxThreads: ({workerThreadsMax}, {completionPortThreadsMax})"); + } } } \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.16.0.md b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.16.0.md index c8a8324d3..b739a24a7 100644 --- a/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.16.0.md +++ b/GoogleTestAdapter/VsPackage.GTA/Resources/ReleaseNotes/0.16.0.md @@ -1,3 +1,4 @@ * enhancement: option *Debugger engine* allows to choose *Managed and native*, which allows to debug into managed code also ([#276](https://github.com/csoltenborn/GoogleTestAdapter/issues/276)) * enhancement: [*settings helper files*]([tokens](https://github.com/csoltenborn/GoogleTestAdapter#settings_helper_files)) allow to provide additional information to GTA at test discovery and execution time ([example project](https://github.com/csoltenborn/GoogleTestAdapter/tree/master/SampleTests/DllProject)). This feature can be used to remove the need for a special configuration file for CI, or to reduce configuration redundancy between project and GTA settings ([#278](https://github.com/csoltenborn/GoogleTestAdapter/issues/278)) +* enhancement: speedup of test discovery ([#TODO](https://github.com/csoltenborn/GoogleTestAdapter/issues/TODO)) * usability: reorganized options ([#271](https://github.com/csoltenborn/GoogleTestAdapter/issues/271)) \ No newline at end of file From 15d479c92a1dda427c8d8c976210f43096e1962a Mon Sep 17 00:00:00 2001 From: Christian Soltenborn Date: Sat, 13 Apr 2019 10:46:18 +0200 Subject: [PATCH 81/81] changed donations request --- .../GoogleTestExtensionOptionsPage.cs | 2 - .../VsPackage.GTA/ReleaseNotes/Donations.cs | 13 -- .../ReleaseNotes/ReleaseNotesCreator.cs | 5 +- .../ReleaseNotesDialog.Designer.cs | 147 +++++++++--------- .../ReleaseNotes/ReleaseNotesDialog.cs | 15 +- .../VsPackage.GTA/VsPackage.GTA.csproj | 1 - 6 files changed, 81 insertions(+), 102 deletions(-) delete mode 100644 GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/Donations.cs diff --git a/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs b/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs index 49cfe09bf..cff4e760c 100644 --- a/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs +++ b/GoogleTestAdapter/VsPackage.GTA/GoogleTestExtensionOptionsPage.cs @@ -5,7 +5,6 @@ using System.IO; using System.Threading; using GoogleTestAdapter.Common; -using GoogleTestAdapter.VsPackage.GTA.ReleaseNotes; using GoogleTestAdapter.VsPackage.Helpers; namespace GoogleTestAdapter.VsPackage @@ -71,7 +70,6 @@ private void DisplayReleaseNotes(string html) HtmlFile = new Uri($"file://{htmlFile}") }) { - dialog.AddExternalUri(Donations.Uri); dialog.Closed += (sender, args) => File.Delete(htmlFile); dialog.ShowDialog(); } diff --git a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/Donations.cs b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/Donations.cs deleted file mode 100644 index be73ccb70..000000000 --- a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/Donations.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; - -namespace GoogleTestAdapter.VsPackage.GTA.ReleaseNotes -{ - public static class Donations - { - public static readonly Uri Uri = new Uri("https://github.com/csoltenborn/GoogleTestAdapter#donations"); - - public static readonly string Header = $@"
Please consider to donate!
-
-"; - } -} \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesCreator.cs b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesCreator.cs index 975e055d9..68716f220 100644 --- a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesCreator.cs +++ b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesCreator.cs @@ -1,7 +1,6 @@ using System; using System.IO; using CommonMark; -using GoogleTestAdapter.VsPackage.GTA.ReleaseNotes; namespace GoogleTestAdapter.VsPackage.ReleaseNotes { @@ -23,9 +22,7 @@ private string CreateMarkdown() if (_formerlyInstalledVersion == _currentVersion) return ""; - string releaseNotes = Donations.Header; - - releaseNotes += Environment.NewLine + CreateHeader(); + string releaseNotes = CreateHeader(); int startIndex = Array.IndexOf(Versions, _currentVersion); int endIndex = _formerlyInstalledVersion == null ? -1 : Array.IndexOf(Versions, _formerlyInstalledVersion); diff --git a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesDialog.Designer.cs b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesDialog.Designer.cs index dbc873a98..9cb54a4e5 100644 --- a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesDialog.Designer.cs +++ b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesDialog.Designer.cs @@ -1,11 +1,16 @@ -namespace GoogleTestAdapter.VsPackage.ReleaseNotes +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; + +namespace GoogleTestAdapter.VsPackage.ReleaseNotes { partial class ReleaseNotesDialog { /// /// Required designer variable. /// - private System.ComponentModel.IContainer components = null; + private IContainer components = null; /// /// Clean up any resources being used. @@ -28,17 +33,17 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ReleaseNotesDialog)); - this.RootPanel = new System.Windows.Forms.TableLayoutPanel(); - this.NavigationPanel = new System.Windows.Forms.FlowLayoutPanel(); - this.BackButton = new System.Windows.Forms.Button(); - this.ForwardButton = new System.Windows.Forms.Button(); - this.WebBrowser = new System.Windows.Forms.WebBrowser(); - this.OkButtonPanel = new System.Windows.Forms.TableLayoutPanel(); - this.DonateButton = new System.Windows.Forms.Button(); - this.OkButton = new System.Windows.Forms.Button(); - this.toolTip = new System.Windows.Forms.ToolTip(this.components); + this.components = new Container(); + ComponentResourceManager resources = new ComponentResourceManager(typeof(ReleaseNotesDialog)); + this.RootPanel = new TableLayoutPanel(); + this.NavigationPanel = new FlowLayoutPanel(); + this.BackButton = new Button(); + this.ForwardButton = new Button(); + this.WebBrowser = new WebBrowser(); + this.OkButtonPanel = new TableLayoutPanel(); + this.DonateButton = new Button(); + this.OkButton = new Button(); + this.toolTip = new ToolTip(this.components); this.RootPanel.SuspendLayout(); this.NavigationPanel.SuspendLayout(); this.OkButtonPanel.SuspendLayout(); @@ -47,21 +52,21 @@ private void InitializeComponent() // RootPanel // this.RootPanel.ColumnCount = 2; - this.RootPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); - this.RootPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.RootPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F)); + this.RootPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F)); this.RootPanel.Controls.Add(this.NavigationPanel, 0, 0); this.RootPanel.Controls.Add(this.WebBrowser, 0, 1); this.RootPanel.Controls.Add(this.OkButtonPanel, 0, 2); - this.RootPanel.Dock = System.Windows.Forms.DockStyle.Fill; - this.RootPanel.Location = new System.Drawing.Point(0, 0); - this.RootPanel.Margin = new System.Windows.Forms.Padding(7); + this.RootPanel.Dock = DockStyle.Fill; + this.RootPanel.Location = new Point(0, 0); + this.RootPanel.Margin = new Padding(7); this.RootPanel.Name = "RootPanel"; this.RootPanel.RowCount = 3; - this.RootPanel.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.RootPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.RootPanel.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.RootPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 45F)); - this.RootPanel.Size = new System.Drawing.Size(1829, 1251); + this.RootPanel.RowStyles.Add(new RowStyle()); + this.RootPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100F)); + this.RootPanel.RowStyles.Add(new RowStyle()); + this.RootPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, 45F)); + this.RootPanel.Size = new Size(1829, 1251); this.RootPanel.TabIndex = 0; // // NavigationPanel @@ -70,21 +75,21 @@ private void InitializeComponent() this.RootPanel.SetColumnSpan(this.NavigationPanel, 2); this.NavigationPanel.Controls.Add(this.BackButton); this.NavigationPanel.Controls.Add(this.ForwardButton); - this.NavigationPanel.Dock = System.Windows.Forms.DockStyle.Fill; - this.NavigationPanel.Location = new System.Drawing.Point(7, 7); - this.NavigationPanel.Margin = new System.Windows.Forms.Padding(7); + this.NavigationPanel.Dock = DockStyle.Fill; + this.NavigationPanel.Location = new Point(7, 7); + this.NavigationPanel.Margin = new Padding(7); this.NavigationPanel.Name = "NavigationPanel"; - this.NavigationPanel.Size = new System.Drawing.Size(1815, 65); + this.NavigationPanel.Size = new Size(1815, 65); this.NavigationPanel.TabIndex = 3; // // BackButton // this.BackButton.AccessibleName = "Go back"; this.BackButton.Enabled = false; - this.BackButton.Location = new System.Drawing.Point(7, 7); - this.BackButton.Margin = new System.Windows.Forms.Padding(7); + this.BackButton.Location = new Point(7, 7); + this.BackButton.Margin = new Padding(7); this.BackButton.Name = "BackButton"; - this.BackButton.Size = new System.Drawing.Size(54, 51); + this.BackButton.Size = new Size(54, 51); this.BackButton.TabIndex = 3; this.BackButton.Text = "<"; this.BackButton.UseVisualStyleBackColor = true; @@ -93,10 +98,10 @@ private void InitializeComponent() // this.ForwardButton.AccessibleName = "Go forward"; this.ForwardButton.Enabled = false; - this.ForwardButton.Location = new System.Drawing.Point(75, 7); - this.ForwardButton.Margin = new System.Windows.Forms.Padding(7); + this.ForwardButton.Location = new Point(75, 7); + this.ForwardButton.Margin = new Padding(7); this.ForwardButton.Name = "ForwardButton"; - this.ForwardButton.Size = new System.Drawing.Size(54, 51); + this.ForwardButton.Size = new Size(54, 51); this.ForwardButton.TabIndex = 4; this.ForwardButton.Text = ">"; this.ForwardButton.UseVisualStyleBackColor = true; @@ -106,44 +111,44 @@ private void InitializeComponent() this.WebBrowser.AccessibleName = "Browser"; this.WebBrowser.AllowWebBrowserDrop = false; this.RootPanel.SetColumnSpan(this.WebBrowser, 2); - this.WebBrowser.Dock = System.Windows.Forms.DockStyle.Fill; + this.WebBrowser.Dock = DockStyle.Fill; this.WebBrowser.IsWebBrowserContextMenuEnabled = false; - this.WebBrowser.Location = new System.Drawing.Point(7, 86); - this.WebBrowser.Margin = new System.Windows.Forms.Padding(7); - this.WebBrowser.MinimumSize = new System.Drawing.Size(47, 45); + this.WebBrowser.Location = new Point(7, 86); + this.WebBrowser.Margin = new Padding(7); + this.WebBrowser.MinimumSize = new Size(47, 45); this.WebBrowser.Name = "WebBrowser"; this.WebBrowser.ScriptErrorsSuppressed = true; - this.WebBrowser.Size = new System.Drawing.Size(1815, 1079); + this.WebBrowser.Size = new Size(1815, 1079); this.WebBrowser.TabIndex = 2; this.WebBrowser.WebBrowserShortcutsEnabled = false; - this.WebBrowser.Navigating += new System.Windows.Forms.WebBrowserNavigatingEventHandler(this.WebBrowser_Navigating); + this.WebBrowser.Navigating += new WebBrowserNavigatingEventHandler(this.WebBrowser_Navigating); // // OkButtonPanel // - this.OkButtonPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.OkButtonPanel.Anchor = ((AnchorStyles)((AnchorStyles.Left | AnchorStyles.Right))); this.OkButtonPanel.AutoSize = true; this.OkButtonPanel.ColumnCount = 2; this.RootPanel.SetColumnSpan(this.OkButtonPanel, 2); - this.OkButtonPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); - this.OkButtonPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); + this.OkButtonPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 33.33333F)); + this.OkButtonPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 33.33333F)); this.OkButtonPanel.Controls.Add(this.DonateButton, 0, 0); this.OkButtonPanel.Controls.Add(this.OkButton, 1, 0); - this.OkButtonPanel.Location = new System.Drawing.Point(7, 1179); - this.OkButtonPanel.Margin = new System.Windows.Forms.Padding(7); + this.OkButtonPanel.Location = new Point(7, 1179); + this.OkButtonPanel.Margin = new Padding(7); this.OkButtonPanel.Name = "OkButtonPanel"; this.OkButtonPanel.RowCount = 1; - this.OkButtonPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.OkButtonPanel.Size = new System.Drawing.Size(1815, 65); + this.OkButtonPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100F)); + this.OkButtonPanel.Size = new Size(1815, 65); this.OkButtonPanel.TabIndex = 4; // // DonateButton // this.DonateButton.AccessibleName = "Close release notes dialog"; - this.DonateButton.Anchor = System.Windows.Forms.AnchorStyles.None; - this.DonateButton.Location = new System.Drawing.Point(303, 7); - this.DonateButton.Margin = new System.Windows.Forms.Padding(7); + this.DonateButton.Anchor = AnchorStyles.None; + this.DonateButton.Location = new Point(303, 7); + this.DonateButton.Margin = new Padding(7); this.DonateButton.Name = "DonateButton"; - this.DonateButton.Size = new System.Drawing.Size(301, 51); + this.DonateButton.Size = new Size(301, 51); this.DonateButton.TabIndex = 0; this.DonateButton.Text = "Cool - I want to donate!"; this.DonateButton.UseVisualStyleBackColor = true; @@ -151,30 +156,30 @@ private void InitializeComponent() // OkButton // this.OkButton.AccessibleName = "Close release notes dialog"; - this.OkButton.Anchor = System.Windows.Forms.AnchorStyles.None; - this.OkButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.OkButton.Location = new System.Drawing.Point(1273, 7); - this.OkButton.Margin = new System.Windows.Forms.Padding(7); + this.OkButton.Anchor = AnchorStyles.None; + this.OkButton.DialogResult = DialogResult.Cancel; + this.OkButton.Location = new Point(1273, 7); + this.OkButton.Margin = new Padding(7); this.OkButton.Name = "OkButton"; - this.OkButton.Size = new System.Drawing.Size(175, 51); + this.OkButton.Size = new Size(175, 51); this.OkButton.TabIndex = 1; - this.OkButton.Text = "Whatever..."; + this.OkButton.Text = "Thanks anyways..."; this.OkButton.UseVisualStyleBackColor = true; // // ReleaseNotesDialog // this.AcceptButton = this.OkButton; this.AccessibleName = "Release notes of Google Test Adapter"; - this.AutoScaleDimensions = new System.Drawing.SizeF(14F, 29F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScaleDimensions = new SizeF(14F, 29F); + this.AutoScaleMode = AutoScaleMode.Font; this.CancelButton = this.OkButton; this.CausesValidation = false; - this.ClientSize = new System.Drawing.Size(1829, 1251); + this.ClientSize = new Size(1829, 1251); this.Controls.Add(this.RootPanel); - this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); - this.Margin = new System.Windows.Forms.Padding(7); + this.Icon = ((Icon)(resources.GetObject("$this.Icon"))); + this.Margin = new Padding(7); this.Name = "ReleaseNotesDialog"; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.StartPosition = FormStartPosition.CenterParent; this.Text = "Google Test Adapter: Release notes"; this.RootPanel.ResumeLayout(false); this.RootPanel.PerformLayout(); @@ -186,14 +191,14 @@ private void InitializeComponent() #endregion - private System.Windows.Forms.TableLayoutPanel RootPanel; - private System.Windows.Forms.WebBrowser WebBrowser; - private System.Windows.Forms.Button OkButton; - private System.Windows.Forms.FlowLayoutPanel NavigationPanel; - private System.Windows.Forms.Button BackButton; - private System.Windows.Forms.Button ForwardButton; - private System.Windows.Forms.TableLayoutPanel OkButtonPanel; - private System.Windows.Forms.ToolTip toolTip; - private System.Windows.Forms.Button DonateButton; + private TableLayoutPanel RootPanel; + private WebBrowser WebBrowser; + private Button OkButton; + private FlowLayoutPanel NavigationPanel; + private Button BackButton; + private Button ForwardButton; + private TableLayoutPanel OkButtonPanel; + private ToolTip toolTip; + private Button DonateButton; } } \ No newline at end of file diff --git a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesDialog.cs b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesDialog.cs index 99717e602..b3fc02cfa 100644 --- a/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesDialog.cs +++ b/GoogleTestAdapter/VsPackage.GTA/ReleaseNotes/ReleaseNotesDialog.cs @@ -1,20 +1,18 @@ using System; -using System.Collections.Generic; using System.Diagnostics; using System.Windows.Forms; -using GoogleTestAdapter.VsPackage.GTA.ReleaseNotes; namespace GoogleTestAdapter.VsPackage.ReleaseNotes { public partial class ReleaseNotesDialog : Form { - private readonly ISet _externalUris = new HashSet(); + private static readonly Uri DonationsUri = new Uri("https://github.com/csoltenborn/GoogleTestAdapter#donations"); public ReleaseNotesDialog() { InitializeComponent(); - Load += (sender, args) => DonateButton.Select(); + Load += (sender, args) => OkButton.Select(); WebBrowser.CanGoBackChanged += (sender, args) => BackButton.Enabled = WebBrowser.CanGoBack; BackButton.Click += (sender, args) => WebBrowser.GoBack(); @@ -25,7 +23,7 @@ public ReleaseNotesDialog() OkButton.Click += (sender, args) => Close(); DonateButton.Click += (sender, args) => { - OpenUriInDefaultBrowser(Donations.Uri); + OpenUriInDefaultBrowser(DonationsUri); Close(); }; } @@ -36,14 +34,9 @@ internal Uri HtmlFile set => WebBrowser.Url = value; } - internal void AddExternalUri(Uri externalUri) - { - _externalUris.Add(externalUri); - } - private void WebBrowser_Navigating(object sender, WebBrowserNavigatingEventArgs e) { - if (_externalUris.Contains(e.Url)) + if (DonationsUri.Equals(e.Url)) { e.Cancel = true; OpenUriInDefaultBrowser(e.Url); diff --git a/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj b/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj index d023155e9..c41375c23 100644 --- a/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj +++ b/GoogleTestAdapter/VsPackage.GTA/VsPackage.GTA.csproj @@ -74,7 +74,6 @@ - Form