Converge implementations of AwaitableProcess and ProcessEx (#26069)
* Converge implementations of AwaitableProcess and ProcessEx * dotnet-watch tests are running in to the same issue as GRPC tests (https://github.com/dotnet/aspnetcore/pull/20341/files). This change carries over some of the patterns from the other type to remedy this issue. * Revive dotnet-watch tests on OSX * Remove build artifacts that were accidentally commited to source.
This commit is contained in:
parent
7afaf45b54
commit
140f177d9e
|
|
@ -15,6 +15,8 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests
|
||||||
{
|
{
|
||||||
public class AwaitableProcess : IDisposable
|
public class AwaitableProcess : IDisposable
|
||||||
{
|
{
|
||||||
|
private readonly object _testOutputLock = new object();
|
||||||
|
|
||||||
private Process _process;
|
private Process _process;
|
||||||
private readonly ProcessSpec _spec;
|
private readonly ProcessSpec _spec;
|
||||||
private readonly List<string> _lines;
|
private readonly List<string> _lines;
|
||||||
|
|
@ -22,6 +24,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests
|
||||||
private ITestOutputHelper _logger;
|
private ITestOutputHelper _logger;
|
||||||
private TaskCompletionSource<int> _exited;
|
private TaskCompletionSource<int> _exited;
|
||||||
private bool _started;
|
private bool _started;
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
public AwaitableProcess(ProcessSpec spec, ITestOutputHelper logger)
|
public AwaitableProcess(ProcessSpec spec, ITestOutputHelper logger)
|
||||||
{
|
{
|
||||||
|
|
@ -29,7 +32,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_source = new BufferBlock<string>();
|
_source = new BufferBlock<string>();
|
||||||
_lines = new List<string>();
|
_lines = new List<string>();
|
||||||
_exited = new TaskCompletionSource<int>();
|
_exited = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<string> Output => _lines;
|
public IEnumerable<string> Output => _lines;
|
||||||
|
|
@ -72,17 +75,17 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests
|
||||||
_process.ErrorDataReceived += OnData;
|
_process.ErrorDataReceived += OnData;
|
||||||
_process.Exited += OnExit;
|
_process.Exited += OnExit;
|
||||||
|
|
||||||
_logger.WriteLine($"{DateTime.Now}: starting process: '{_process.StartInfo.FileName} {_process.StartInfo.Arguments}'");
|
WriteTestOutput($"{DateTime.Now}: starting process: '{_process.StartInfo.FileName} {_process.StartInfo.Arguments}'");
|
||||||
_process.Start();
|
_process.Start();
|
||||||
_started = true;
|
_started = true;
|
||||||
_process.BeginErrorReadLine();
|
_process.BeginErrorReadLine();
|
||||||
_process.BeginOutputReadLine();
|
_process.BeginOutputReadLine();
|
||||||
_logger.WriteLine($"{DateTime.Now}: process started: '{_process.StartInfo.FileName} {_process.StartInfo.Arguments}'");
|
WriteTestOutput($"{DateTime.Now}: process started: '{_process.StartInfo.FileName} {_process.StartInfo.Arguments}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> GetOutputLineAsync(string message, TimeSpan timeout)
|
public async Task<string> GetOutputLineAsync(string message, TimeSpan timeout)
|
||||||
{
|
{
|
||||||
_logger.WriteLine($"Waiting for output line [msg == '{message}']. Will wait for {timeout.TotalSeconds} sec.");
|
WriteTestOutput($"Waiting for output line [msg == '{message}']. Will wait for {timeout.TotalSeconds} sec.");
|
||||||
var cts = new CancellationTokenSource();
|
var cts = new CancellationTokenSource();
|
||||||
cts.CancelAfter(timeout);
|
cts.CancelAfter(timeout);
|
||||||
return await GetOutputLineAsync($"[msg == '{message}']", m => string.Equals(m, message, StringComparison.Ordinal), cts.Token);
|
return await GetOutputLineAsync($"[msg == '{message}']", m => string.Equals(m, message, StringComparison.Ordinal), cts.Token);
|
||||||
|
|
@ -90,7 +93,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests
|
||||||
|
|
||||||
public async Task<string> GetOutputLineStartsWithAsync(string message, TimeSpan timeout)
|
public async Task<string> GetOutputLineStartsWithAsync(string message, TimeSpan timeout)
|
||||||
{
|
{
|
||||||
_logger.WriteLine($"Waiting for output line [msg.StartsWith('{message}')]. Will wait for {timeout.TotalSeconds} sec.");
|
WriteTestOutput($"Waiting for output line [msg.StartsWith('{message}')]. Will wait for {timeout.TotalSeconds} sec.");
|
||||||
var cts = new CancellationTokenSource();
|
var cts = new CancellationTokenSource();
|
||||||
cts.CancelAfter(timeout);
|
cts.CancelAfter(timeout);
|
||||||
return await GetOutputLineAsync($"[msg.StartsWith('{message}')]", m => m != null && m.StartsWith(message, StringComparison.Ordinal), cts.Token);
|
return await GetOutputLineAsync($"[msg.StartsWith('{message}')]", m => m != null && m.StartsWith(message, StringComparison.Ordinal), cts.Token);
|
||||||
|
|
@ -105,7 +108,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests
|
||||||
var next = await _source.ReceiveAsync(cancellationToken);
|
var next = await _source.ReceiveAsync(cancellationToken);
|
||||||
_lines.Add(next);
|
_lines.Add(next);
|
||||||
var match = predicate(next);
|
var match = predicate(next);
|
||||||
_logger.WriteLine($"{DateTime.Now}: recv: '{next}'. {(match ? "Matches" : "Does not match")} condition '{predicateName}'.");
|
WriteTestOutput($"{DateTime.Now}: recv: '{next}'. {(match ? "Matches" : "Does not match")} condition '{predicateName}'.");
|
||||||
if (match)
|
if (match)
|
||||||
{
|
{
|
||||||
return next;
|
return next;
|
||||||
|
|
@ -124,7 +127,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests
|
||||||
while (await _source.OutputAvailableAsync(cancellationToken))
|
while (await _source.OutputAvailableAsync(cancellationToken))
|
||||||
{
|
{
|
||||||
var next = await _source.ReceiveAsync(cancellationToken);
|
var next = await _source.ReceiveAsync(cancellationToken);
|
||||||
_logger.WriteLine($"{DateTime.Now}: recv: '{next}'");
|
WriteTestOutput($"{DateTime.Now}: recv: '{next}'");
|
||||||
lines.Add(next);
|
lines.Add(next);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -134,23 +137,40 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests
|
||||||
private void OnData(object sender, DataReceivedEventArgs args)
|
private void OnData(object sender, DataReceivedEventArgs args)
|
||||||
{
|
{
|
||||||
var line = args.Data ?? string.Empty;
|
var line = args.Data ?? string.Empty;
|
||||||
_logger.WriteLine($"{DateTime.Now}: post: '{line}'");
|
|
||||||
|
WriteTestOutput($"{DateTime.Now}: post: '{line}'");
|
||||||
_source.Post(line);
|
_source.Post(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void WriteTestOutput(string text)
|
||||||
|
{
|
||||||
|
lock (_testOutputLock)
|
||||||
|
{
|
||||||
|
if (!_disposed)
|
||||||
|
{
|
||||||
|
_logger.WriteLine(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void OnExit(object sender, EventArgs args)
|
private void OnExit(object sender, EventArgs args)
|
||||||
{
|
{
|
||||||
// Wait to ensure the process has exited and all output consumed
|
// Wait to ensure the process has exited and all output consumed
|
||||||
_process.WaitForExit();
|
_process.WaitForExit();
|
||||||
_source.Complete();
|
_source.Complete();
|
||||||
_exited.TrySetResult(_process.ExitCode);
|
_exited.TrySetResult(_process.ExitCode);
|
||||||
_logger.WriteLine($"Process {_process.Id} has exited");
|
WriteTestOutput($"Process {_process.Id} has exited");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_source.Complete();
|
_source.Complete();
|
||||||
|
|
||||||
|
lock (_testOutputLock)
|
||||||
|
{
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (_process != null)
|
if (_process != null)
|
||||||
{
|
{
|
||||||
if (_started && !_process.HasExited)
|
if (_started && !_process.HasExited)
|
||||||
|
|
@ -158,6 +178,9 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests
|
||||||
_process.KillTree();
|
_process.KillTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_process.CancelErrorRead();
|
||||||
|
_process.CancelOutputRead();
|
||||||
|
|
||||||
_process.ErrorDataReceived -= OnData;
|
_process.ErrorDataReceived -= OnData;
|
||||||
_process.OutputDataReceived -= OnData;
|
_process.OutputDataReceived -= OnData;
|
||||||
_process.Exited -= OnExit;
|
_process.Exited -= OnExit;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
// <autogenerated />
|
|
||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v5.0", FrameworkDisplayName = "")]
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// <auto-generated>
|
|
||||||
// This code was generated by a tool.
|
|
||||||
// Runtime Version:4.0.30319.42000
|
|
||||||
//
|
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
|
||||||
// the code is regenerated.
|
|
||||||
// </auto-generated>
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
[assembly: System.Reflection.AssemblyMetadataAttribute("SourceCommitUrl", "https://github.com/dotnet/aspnetcore/tree/")]
|
|
||||||
[assembly: System.Reflection.AssemblyMetadataAttribute("Serviceable", "True")]
|
|
||||||
[assembly: System.Reflection.AssemblyCompanyAttribute("Microsoft Corporation")]
|
|
||||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
|
||||||
[assembly: System.Reflection.AssemblyCopyrightAttribute("© Microsoft Corporation. All rights reserved.")]
|
|
||||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("42.42.42.42424")]
|
|
||||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("5.0.0-dev")]
|
|
||||||
[assembly: System.Reflection.AssemblyProductAttribute("Microsoft ASP.NET Core")]
|
|
||||||
[assembly: System.Reflection.AssemblyTitleAttribute("KitchenSink")]
|
|
||||||
[assembly: System.Reflection.AssemblyVersionAttribute("5.0.0.0")]
|
|
||||||
[assembly: System.Reflection.AssemblyMetadataAttribute("RepositoryUrl", "https://github.com/dotnet/aspnetcore")]
|
|
||||||
[assembly: System.Resources.NeutralResourcesLanguageAttribute("en-US")]
|
|
||||||
|
|
||||||
// Generated by the MSBuild WriteCodeFragment class.
|
|
||||||
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
5426b0432f23f134c800ff0d43b24a23681aac3d
|
|
||||||
|
|
@ -12,9 +12,6 @@
|
||||||
-->
|
-->
|
||||||
<UseAspNetCoreSharedRuntime>true</UseAspNetCoreSharedRuntime>
|
<UseAspNetCoreSharedRuntime>true</UseAspNetCoreSharedRuntime>
|
||||||
<DoNotApplyWorkaroundsToMicrosoftAspNetCoreApp>true</DoNotApplyWorkaroundsToMicrosoftAspNetCoreApp>
|
<DoNotApplyWorkaroundsToMicrosoftAspNetCoreApp>true</DoNotApplyWorkaroundsToMicrosoftAspNetCoreApp>
|
||||||
|
|
||||||
<!-- Skipped due to https://github.com/dotnet/aspnetcore/issues/26061 -->
|
|
||||||
<SkipTests Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</SkipTests>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue