private async Task <RunSummary> RunAsyncCore(VsixTestCase testCase, IMessageBus messageBus, ExceptionAggregator aggregator) { if (!EnsureConnected(testCase, messageBus)) { return(new RunSummary { Failed = 1, }); } var xunitTest = new XunitTest(testCase, testCase.DisplayName); try { var remoteBus = _remoteBuses.GetOrAdd(messageBus, bus => { var instance = new RemoteMessageBus(bus); _remoteObjects.Add(instance); return(instance); }); var outputBus = new TraceOutputMessageBus(remoteBus); var summary = await Task.Run( () => _runner.Run(testCase, outputBus)) .TimeoutAfter(testCase.TimeoutSeconds * 1000); if (summary.Exception != null) { aggregator.Add(summary.Exception); } return(summary.ToRunSummary()); } catch (Exception ex) { if (ex is RemotingException || ex is TimeoutException) { Stop(); } aggregator.Add(ex); messageBus.QueueMessage(new TestFailed(xunitTest, 0, ex.Message, ex)); return(new RunSummary { Failed = 1 }); } }
public async Task<RunSummary> RunAsync (VsixTestCase testCase, IMessageBus messageBus, ExceptionAggregator aggregator, object[] constructorArguments) { if (Process == null) { if (!Start ()) { Stop (); if (!Start ()) { Stop (); messageBus.QueueMessage (new TestFailed (new XunitTest (testCase, testCase.DisplayName), 0, string.Format ("Failed to start Visual Studio {0}{1}.", visualStudioVersion, rootSuffix), new TimeoutException ())); return new RunSummary { Failed = 1, }; } } } if (runner == null) { var hostUrl = RemotingUtil.GetHostUri (pipeName); var clientPipeName = Guid.NewGuid ().ToString ("N"); clientChannel = RemotingUtil.CreateChannel (Constants.ClientChannelName + clientPipeName, clientPipeName); try { runner = (IVsRemoteRunner)RemotingServices.Connect (typeof (IVsRemoteRunner), hostUrl); // We don't require restart anymore since we write to the registry directly the binding paths, // rather than installing a VSIX //if (runner.ShouldRestart ()) { // Stop (); // return await RunAsync (testCase, messageBus, aggregator, constructorArguments); //} if (Debugger.IsAttached) { // Add default trace listeners to the remote process. foreach (var listener in Trace.Listeners.OfType<TraceListener> ()) { runner.AddListener (listener); } } } catch (Exception ex) { messageBus.QueueMessage (new TestFailed (new XunitTest (testCase, testCase.DisplayName), 0, ex.Message, ex)); return new RunSummary { Failed = 1 }; } } var xunitTest = new XunitTest (testCase, testCase.DisplayName); try { var outputHelper = constructorArguments.OfType<TestOutputHelper> ().FirstOrDefault (); if (outputHelper != null) outputHelper.Initialize (messageBus, xunitTest); // Special case for test output, since it's not MBR. var args = constructorArguments.Select (arg => { var helper = arg as ITestOutputHelper; if (helper != null) { var remoteHeper = new RemoteTestOutputHelper (helper); remoteObjects.Add (remoteHeper); return remoteHeper; } return arg; }).ToArray (); var remoteBus = new RemoteMessageBus (messageBus); remoteObjects.Add (remoteBus); var summary = await System.Threading.Tasks.Task.Run ( () => runner.Run (testCase, remoteBus, args)) .TimeoutAfter (testCase.TimeoutSeconds * 1000); // Dump output only if a debugger is attached, meaning that most likely // there is a single test being run/debugged. if (Debugger.IsAttached && outputHelper != null && !string.IsNullOrEmpty (outputHelper.Output)) { Trace.WriteLine (outputHelper.Output); Debugger.Log (0, "", outputHelper.Output); Console.WriteLine (outputHelper.Output); } if (summary.Exception != null) aggregator.Add (summary.Exception); return summary.ToRunSummary (); } catch (Exception ex) { aggregator.Add (ex); messageBus.QueueMessage (new TestFailed (xunitTest, 0, ex.Message, ex)); return new RunSummary { Failed = 1 }; } finally { var outputHelper = constructorArguments.OfType<TestOutputHelper> ().FirstOrDefault (); if (outputHelper != null) outputHelper.Uninitialize (); } }