From 48d5ef68535d44fc58641a51c6844da6e4e3f7b7 Mon Sep 17 00:00:00 2001 From: Brad Wilson Date: Thu, 12 Oct 2023 18:27:33 -0700 Subject: [PATCH] Add diagnostic messages around DiaSession failures --- .../Utility/DiaSessionWrapper.cs | 55 ++++++++++++++----- .../VisualStudioSourceInformationProvider.cs | 7 ++- src/xunit.runner.visualstudio/VsTestRunner.cs | 4 +- 3 files changed, 49 insertions(+), 17 deletions(-) diff --git a/src/xunit.runner.visualstudio/Utility/DiaSessionWrapper.cs b/src/xunit.runner.visualstudio/Utility/DiaSessionWrapper.cs index f94ce89..461ec67 100644 --- a/src/xunit.runner.visualstudio/Utility/DiaSessionWrapper.cs +++ b/src/xunit.runner.visualstudio/Utility/DiaSessionWrapper.cs @@ -1,6 +1,8 @@ using System; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Navigation; +using Xunit.Abstractions; +using Xunit.Internal; namespace Xunit.Runner.VisualStudio.Utility; @@ -13,38 +15,65 @@ class DiaSessionWrapper : IDisposable readonly AppDomainManager? appDomainManager; #endif readonly DiaSessionWrapperHelper? helper; - readonly DiaSession session; + readonly DiaSession? session; + readonly DiagnosticMessageSink diagnosticMessageSink; - public DiaSessionWrapper(string assemblyFileName) + public DiaSessionWrapper( + string assemblyFileName, + DiagnosticMessageSink diagnosticMessageSink) { - session = new DiaSession(assemblyFileName); + this.diagnosticMessageSink = Guard.ArgumentNotNull(diagnosticMessageSink); -#if NETFRAMEWORK - var adapterFileName = typeof(DiaSessionWrapperHelper).Assembly.GetLocalCodeBase(); - if (adapterFileName is not null) + try + { + session = new DiaSession(assemblyFileName); + } + catch (Exception ex) { - appDomainManager = new AppDomainManager(assemblyFileName); - helper = appDomainManager.CreateObject(typeof(DiaSessionWrapperHelper).Assembly.GetName(), typeof(DiaSessionWrapperHelper).FullName!, adapterFileName); + diagnosticMessageSink.OnMessage(new DiagnosticMessage($"Exception creating DiaSession: {ex}")); } + + try + { +#if NETFRAMEWORK + var adapterFileName = typeof(DiaSessionWrapperHelper).Assembly.GetLocalCodeBase(); + if (adapterFileName is not null) + { + appDomainManager = new AppDomainManager(assemblyFileName); + helper = appDomainManager.CreateObject(typeof(DiaSessionWrapperHelper).Assembly.GetName(), typeof(DiaSessionWrapperHelper).FullName!, adapterFileName); + } #else - helper = new DiaSessionWrapperHelper(assemblyFileName); + helper = new DiaSessionWrapperHelper(assemblyFileName); #endif + } + catch (Exception ex) + { + diagnosticMessageSink.OnMessage(new DiagnosticMessage($"Exception creating DiaSessionWrapperHelper: {ex}")); + } } public INavigationData? GetNavigationData( string typeName, string methodName) { - if (helper is null) + if (session is null || helper is null) return null; - helper.Normalize(ref typeName, ref methodName); - return session.GetNavigationDataForMethod(typeName, methodName); + try + { + helper.Normalize(ref typeName, ref methodName); + return session.GetNavigationDataForMethod(typeName, methodName); + } + catch (Exception ex) + { + diagnosticMessageSink.OnMessage(new DiagnosticMessage($"Exception getting source mapping for {typeName}.{methodName}: {ex}")); + return null; + } } public void Dispose() { - session.Dispose(); + session?.Dispose(); #if NETFRAMEWORK appDomainManager?.Dispose(); #endif diff --git a/src/xunit.runner.visualstudio/Utility/VisualStudioSourceInformationProvider.cs b/src/xunit.runner.visualstudio/Utility/VisualStudioSourceInformationProvider.cs index c969677..d80e26f 100644 --- a/src/xunit.runner.visualstudio/Utility/VisualStudioSourceInformationProvider.cs +++ b/src/xunit.runner.visualstudio/Utility/VisualStudioSourceInformationProvider.cs @@ -18,9 +18,12 @@ public class VisualStudioSourceInformationProvider : LongLivedMarshalByRefObject /// Initializes a new instance of the class. /// /// The assembly file name. - public VisualStudioSourceInformationProvider(string assemblyFileName) + /// The message sink to send internal diagnostic messages to. + public VisualStudioSourceInformationProvider( + string assemblyFileName, + DiagnosticMessageSink diagnosticMessageSink) { - session = new DiaSessionWrapper(assemblyFileName); + session = new DiaSessionWrapper(assemblyFileName, diagnosticMessageSink); } /// diff --git a/src/xunit.runner.visualstudio/VsTestRunner.cs b/src/xunit.runner.visualstudio/VsTestRunner.cs index c6f90fb..4c79e6c 100644 --- a/src/xunit.runner.visualstudio/VsTestRunner.cs +++ b/src/xunit.runner.visualstudio/VsTestRunner.cs @@ -240,7 +240,7 @@ void DiscoverTests( var diagnosticSink = DiagnosticMessageSink.ForDiagnostics(logger, fileName, assembly.Configuration.DiagnosticMessagesOrDefault); var appDomain = assembly.Configuration.AppDomain ?? AppDomainDefaultBehavior; - using var sourceInformationProvider = new VisualStudioSourceInformationProvider(assembly.AssemblyFilename); + using var sourceInformationProvider = new VisualStudioSourceInformationProvider(assembly.AssemblyFilename, diagnosticSink); using var controller = new XunitFrontController(appDomain, assembly.AssemblyFilename, shadowCopy: shadowCopy, sourceInformationProvider: sourceInformationProvider, diagnosticMessageSink: MessageSinkAdapter.Wrap(diagnosticSink)); if (!DiscoverTestsInSource(controller, logger, testPlatformContext, runSettings, visitorFactory, visitComplete, assembly)) break; @@ -428,7 +428,7 @@ void RunTestsInAssembly( var diagnosticSink = DiagnosticMessageSink.ForDiagnostics(logger, assemblyDisplayName, runInfo.Assembly.Configuration.DiagnosticMessagesOrDefault); var diagnosticMessageSink = MessageSinkAdapter.Wrap(diagnosticSink); - using var sourceInformationProvider = new VisualStudioSourceInformationProvider(assemblyFileName); + using var sourceInformationProvider = new VisualStudioSourceInformationProvider(assemblyFileName, diagnosticSink); using var controller = new XunitFrontController(appDomain, assemblyFileName, shadowCopy: shadowCopy, sourceInformationProvider: sourceInformationProvider, diagnosticMessageSink: diagnosticMessageSink); var testCasesMap = new Dictionary(); var testCases = new List();