private static void TestBody(string loggerCategory)
{
Console.Error.WriteLine("Starting remote test process");
+ Console.Error.Flush();
ServiceCollection serviceCollection = new ServiceCollection();
serviceCollection.AddLogging(builder =>
var logger = loggerFactory.CreateLogger(loggerCategory);
Console.Error.WriteLine($"{DateTime.UtcNow} Awaiting start");
+ Console.Error.Flush();
if (Console.Read() == -1)
{
throw new InvalidOperationException("Unable to receive start signal");
}
Console.Error.WriteLine($"{DateTime.UtcNow} Starting test body");
+ Console.Error.Flush();
TestBodyCore(logger);
//Signal end of test data
Console.WriteLine("1");
Console.Error.WriteLine($"{DateTime.UtcNow} Awaiting end");
+ Console.Error.Flush();
if (Console.Read() == -1)
{
throw new InvalidOperationException("Unable to receive end signal");
}
-
-
-
Console.Error.WriteLine($"{DateTime.UtcNow} Ending remote test process");
}
public async Task TestTraceStopAsync()
{
using var buffer = new MemoryStream();
-
+ Stream eventStream = null;
await using (var testExecution = StartTraceeProcess("TraceStopTest"))
{
//TestRunner should account for start delay to make sure that the diagnostic pipe is available.
await using var pipeline = new EventTracePipeline(client, settings, async (s, token) =>
{
- //The buffer must be read in order to not hang. The Stop message will not be processed otherwise.
await s.CopyToAsync(buffer);
+ eventStream = s;
});
await PipelineTestUtilities.ExecutePipelineWithDebugee(pipeline, testExecution);
}
+ //Validate that the stream is only valid for the lifetime of the callback in the trace pipeline.
+ Assert.Throws<ObjectDisposedException>(() => eventStream.Read(new byte[4], 0, 4));
+
Assert.True(buffer.Length > 0);
var eventSource = new EventPipeEventSource(buffer);
Assert.True(foundCpuProvider);
}
+ [SkippableFact]
+ public async Task TestEventStreamCleanup()
+ {
+ if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ throw new SkipTestException("Test debugee sigfaults for OSX/Linux");
+ }
+
+ Stream eventStream = null;
+ using var cancellationTokenSource = new CancellationTokenSource();
+ await using (var testExecution = StartTraceeProcess("TestEventStreamCleanup"))
+ {
+ //TestRunner should account for start delay to make sure that the diagnostic pipe is available.
+
+ var client = new DiagnosticsClient(testExecution.TestRunner.Pid);
+ var settings = new EventTracePipelineSettings()
+ {
+ Duration = Timeout.InfiniteTimeSpan,
+ Configuration = new CpuProfileConfiguration()
+ };
+
+ await using var pipeline = new EventTracePipeline(client, settings, (s, token) =>
+ {
+ eventStream = s; //Clients should not do this.
+ cancellationTokenSource.Cancel();
+ token.ThrowIfCancellationRequested();
+ return Task.CompletedTask;
+ });
+
+ await Assert.ThrowsAsync<OperationCanceledException>(async () => await PipelineTestUtilities.ExecutePipelineWithDebugee(pipeline, testExecution, cancellationTokenSource.Token));
+ }
+
+ //Validate that the stream is only valid for the lifetime of the callback in the trace pipeline.
+ Assert.Throws<ObjectDisposedException>(() => eventStream.Read(new byte[4], 0, 4));
+ }
+
private RemoteTestExecution StartTraceeProcess(string loggerCategory)
{
return RemoteTestExecution.StartProcess(CommonHelper.GetTraceePathWithArgs("EventPipeTracee") + " " + loggerCategory, _output);
{
internal static class PipelineTestUtilities
{
- public static async Task ExecutePipelineWithDebugee(Pipeline pipeline, RemoteTestExecution testExecution)
+ public static async Task ExecutePipelineWithDebugee(Pipeline pipeline, RemoteTestExecution testExecution, CancellationToken token = default)
{
- Task processingTask = pipeline.RunAsync(CancellationToken.None);
+ Task processingTask = pipeline.RunAsync(token);
//Begin event production
testExecution.SendSignal();
//Wait for event production to be done
testExecution.WaitForSignal();
- //Signal for the pipeline to stop
- await pipeline.StopAsync();
-
- //After a pipeline is stopped, we should expect the RunTask to eventually finish
- await processingTask;
-
- //Signal for debugee that's ok to end/move on.
- testExecution.SendSignal();
+ try
+ {
+ //Signal for the pipeline to stop
+ await pipeline.StopAsync(token);
+ //After a pipeline is stopped, we should expect the RunTask to eventually finish
+ await processingTask;
+ }
+ finally
+ {
+ //Signal for debugee that's ok to end/move on.
+ testExecution.SendSignal();
+ }
}
}
}