Files
speckle.xunit.runner.wpf/xunit.runner.wpf/Impl/RemoteTestUtil.cs
T
Jared Parsons cf5c313d28 Used a changing pipe name
This ensures that we can have multiple worker processes running at the
same time.
2015-08-19 13:47:48 -07:00

131 lines
4.1 KiB
C#

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Threading;
using xunit.runner.data;
using xunit.runner.wpf.ViewModel;
namespace xunit.runner.wpf.Impl
{
internal sealed partial class RemoteTestUtil : ITestUtil
{
private sealed class Connection : IDisposable
{
private NamedPipeClientStream _stream;
private Process _process;
internal NamedPipeClientStream Stream => _stream;
internal Connection(NamedPipeClientStream stream, Process process)
{
_stream = stream;
_process = process;
}
void IDisposable.Dispose()
{
if (_process != null)
{
Debug.Assert(_stream != null);
_stream.Close();
try
{
_process.Kill();
}
catch
{
// Inherent race condition shutting down the process.
}
}
}
}
private static Connection StartWorkerProcess(string action, string argument)
{
var pipeName = $"xunit.runner.wpf.pipe.{Guid.NewGuid()}";
var processStartInfo = new ProcessStartInfo();
processStartInfo.FileName = typeof(xunit.runner.worker.Program).Assembly.Location;
processStartInfo.Arguments = $"{pipeName} {action} {argument}";
processStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
var process = Process.Start(processStartInfo);
try
{
var stream = new NamedPipeClientStream(pipeName);
stream.Connect();
return new Connection(stream, process);
}
catch
{
process.Kill();
throw;
}
}
private List<TestCaseViewModel> Discover(string assemblyPath)
{
var list = DiscoverCore(assemblyPath);
return list
.Select(x => new TestCaseViewModel(x.SerializedForm, x.DisplayName, x.AssemblyPath))
.ToList();
}
private List<TestCaseData> DiscoverCore(string assemblyPath)
{
var list = new List<TestCaseData>();
using (var connection = StartWorkerProcess(Constants.ActionDiscover, assemblyPath))
using (var reader = new BinaryReader(connection.Stream, Constants.Encoding, leaveOpen: true))
{
try
{
while (true)
{
var testCaseData = TestCaseData.ReadFrom(reader);
list.Add(testCaseData);
}
}
catch
{
// Hacky way of catching end of stream
}
}
return list;
}
private RunSession Run(Dispatcher dispatcher, string assemblyPath, CancellationToken cancellationToken)
{
var connection = StartWorkerProcess(Constants.ActionRun, assemblyPath);
var queue = new ConcurrentQueue<TestResultData>();
var backgroundRunner = new BackgroundRunner(queue, new BinaryReader(connection.Stream, Constants.Encoding, leaveOpen: true), cancellationToken);
Task.Run(backgroundRunner.GoOnBackground);
return new RunSession(connection, dispatcher, queue);
}
#region ITestUtil
List<TestCaseViewModel> ITestUtil.Discover(string assemblyPath)
{
return Discover(assemblyPath);
}
ITestRunSession ITestUtil.Run(Dispatcher dispatcher, string assemblyPath, CancellationToken cancellationToken)
{
return Run(dispatcher, assemblyPath, cancellationToken);
}
#endregion
}
}