using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; 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 partial class RemoteTestUtil { private sealed class RunSession : ITestRunSession { private readonly Task _task; private event EventHandler _testFinished; private event EventHandler _sessionFinished; internal RunSession(Connection connection, Dispatcher dispatcher, ImmutableArray testCaseDisplayNames, CancellationToken cancellationToken) { var queue = CreateQueue(connection, testCaseDisplayNames, cancellationToken); var backgroundProducer = new BackgroundProducer(connection, dispatcher, queue, OnDataProduced); _task = backgroundProducer.Task; } /// /// Create the which will be populated with the /// as it arrives from the worker. /// private static ConcurrentQueue CreateQueue(Connection connection, ImmutableArray testCaseDisplayNames, CancellationToken cancellationToken) { var queue = new ConcurrentQueue(); var unused = CreateQueueCore(queue, connection, testCaseDisplayNames, cancellationToken); return queue; } private static async Task CreateQueueCore(ConcurrentQueue queue, Connection connection, ImmutableArray testCaseDisplayNames, CancellationToken cancellationToken) { try { if (!testCaseDisplayNames.IsDefaultOrEmpty) { var backgroundWriter = new BackgroundWriter(new ClientWriter(connection.Stream), testCaseDisplayNames, (w, s) => w.Write(s), cancellationToken); await backgroundWriter.WriteAsync(); } var backgroundReader = new BackgroundReader(queue, new ClientReader(connection.Stream), r => r.ReadTestResultData(), cancellationToken); await backgroundReader.ReadAsync(); } catch (Exception ex) { Debug.Fail(ex.Message); // Signal data completed queue.Enqueue(null); } } private void OnDataProduced(List list) { Debug.Assert(!_task.IsCompleted); if (list == null) { _sessionFinished?.Invoke(this, EventArgs.Empty); return; } foreach (var cur in list) { _testFinished?.Invoke(this, new wpf.TestResultDataEventArgs(cur)); } } #region ITestRunSession Task ITestSession.Task => _task; event EventHandler ITestRunSession.TestFinished { add { _testFinished += value; } remove { _testFinished -= value; } } event EventHandler ITestRunSession.SessionFinished { add { _sessionFinished += value; } remove { _sessionFinished -= value; } } #endregion } } }