|
|
@@ -1,12 +1,12 @@
|
|
|
-// Copyright (c) .NET Foundation. All rights reserved.
|
|
|
+// Copyright (c) .NET Foundation. All rights reserved.
|
|
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
|
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Diagnostics;
|
|
|
+using System.Threading;
|
|
|
using System.Threading.Tasks;
|
|
|
using System.Threading.Tasks.Dataflow;
|
|
|
-using Microsoft.AspNetCore.Testing;
|
|
|
using Microsoft.Extensions.Internal;
|
|
|
using Microsoft.Extensions.CommandLineUtils;
|
|
|
using Xunit.Abstractions;
|
|
|
@@ -17,16 +17,26 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests
|
|
|
{
|
|
|
private Process _process;
|
|
|
private readonly ProcessSpec _spec;
|
|
|
+ private readonly List<string> _lines;
|
|
|
private BufferBlock<string> _source;
|
|
|
private ITestOutputHelper _logger;
|
|
|
+ private TaskCompletionSource<int> _exited;
|
|
|
|
|
|
public AwaitableProcess(ProcessSpec spec, ITestOutputHelper logger)
|
|
|
{
|
|
|
_spec = spec;
|
|
|
_logger = logger;
|
|
|
_source = new BufferBlock<string>();
|
|
|
+ _lines = new List<string>();
|
|
|
+ _exited = new TaskCompletionSource<int>();
|
|
|
}
|
|
|
|
|
|
+ public IEnumerable<string> Output => _lines;
|
|
|
+
|
|
|
+ public Task Exited => _exited.Task;
|
|
|
+
|
|
|
+ public int Id => _process.Id;
|
|
|
+
|
|
|
public void Start()
|
|
|
{
|
|
|
if (_process != null)
|
|
|
@@ -52,6 +62,11 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+ foreach (var env in _spec.EnvironmentVariables)
|
|
|
+ {
|
|
|
+ _process.StartInfo.EnvironmentVariables[env.Key] = env.Value;
|
|
|
+ }
|
|
|
+
|
|
|
_process.OutputDataReceived += OnData;
|
|
|
_process.ErrorDataReceived += OnData;
|
|
|
_process.Exited += OnExit;
|
|
|
@@ -65,24 +80,30 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests
|
|
|
public async Task<string> GetOutputLineAsync(string message, TimeSpan timeout)
|
|
|
{
|
|
|
_logger.WriteLine($"Waiting for output line [msg == '{message}']. Will wait for {timeout.TotalSeconds} sec.");
|
|
|
- return await GetOutputLineAsync(m => message == m).TimeoutAfter(timeout);
|
|
|
+ var cts = new CancellationTokenSource();
|
|
|
+ cts.CancelAfter(timeout);
|
|
|
+ return await GetOutputLineAsync($"[msg == '{message}']", m => string.Equals(m, message, StringComparison.Ordinal), cts.Token);
|
|
|
}
|
|
|
|
|
|
public async Task<string> GetOutputLineStartsWithAsync(string message, TimeSpan timeout)
|
|
|
{
|
|
|
_logger.WriteLine($"Waiting for output line [msg.StartsWith('{message}')]. Will wait for {timeout.TotalSeconds} sec.");
|
|
|
- return await GetOutputLineAsync(m => m.StartsWith(message)).TimeoutAfter(timeout);
|
|
|
+ var cts = new CancellationTokenSource();
|
|
|
+ cts.CancelAfter(timeout);
|
|
|
+ return await GetOutputLineAsync($"[msg.StartsWith('{message}')]", m => m != null && m.StartsWith(message, StringComparison.Ordinal), cts.Token);
|
|
|
}
|
|
|
|
|
|
- private async Task<string> GetOutputLineAsync(Predicate<string> predicate)
|
|
|
+ private async Task<string> GetOutputLineAsync(string predicateName, Predicate<string> predicate, CancellationToken cancellationToken)
|
|
|
{
|
|
|
while (!_source.Completion.IsCompleted)
|
|
|
{
|
|
|
- while (await _source.OutputAvailableAsync())
|
|
|
+ while (await _source.OutputAvailableAsync(cancellationToken))
|
|
|
{
|
|
|
- var next = await _source.ReceiveAsync();
|
|
|
- _logger.WriteLine($"{DateTime.Now}: recv: '{next}'");
|
|
|
- if (predicate(next))
|
|
|
+ var next = await _source.ReceiveAsync(cancellationToken);
|
|
|
+ _lines.Add(next);
|
|
|
+ var match = predicate(next);
|
|
|
+ _logger.WriteLine($"{DateTime.Now}: recv: '{next}'. {(match ? "Matches" : "Does not match")} condition '{predicateName}'.");
|
|
|
+ if (match)
|
|
|
{
|
|
|
return next;
|
|
|
}
|
|
|
@@ -92,14 +113,14 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- public async Task<IList<string>> GetAllOutputLines()
|
|
|
+ public async Task<IList<string>> GetAllOutputLinesAsync(CancellationToken cancellationToken)
|
|
|
{
|
|
|
var lines = new List<string>();
|
|
|
while (!_source.Completion.IsCompleted)
|
|
|
{
|
|
|
- while (await _source.OutputAvailableAsync())
|
|
|
+ while (await _source.OutputAvailableAsync(cancellationToken))
|
|
|
{
|
|
|
- var next = await _source.ReceiveAsync();
|
|
|
+ var next = await _source.ReceiveAsync(cancellationToken);
|
|
|
_logger.WriteLine($"{DateTime.Now}: recv: '{next}'");
|
|
|
lines.Add(next);
|
|
|
}
|
|
|
@@ -119,6 +140,8 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests
|
|
|
// Wait to ensure the process has exited and all output consumed
|
|
|
_process.WaitForExit();
|
|
|
_source.Complete();
|
|
|
+ _exited.TrySetResult(_process.ExitCode);
|
|
|
+ _logger.WriteLine($"Process {_process.Id} has exited");
|
|
|
}
|
|
|
|
|
|
public void Dispose()
|
|
|
@@ -135,6 +158,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests
|
|
|
_process.ErrorDataReceived -= OnData;
|
|
|
_process.OutputDataReceived -= OnData;
|
|
|
_process.Exited -= OnExit;
|
|
|
+ _process.Dispose();
|
|
|
}
|
|
|
}
|
|
|
}
|