-
-
Notifications
You must be signed in to change notification settings - Fork 119
Expand file tree
/
Copy pathDumpCapture.cs
More file actions
92 lines (86 loc) · 2.34 KB
/
DumpCapture.cs
File metadata and controls
92 lines (86 loc) · 2.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
using System.Diagnostics;
using System.Runtime.CompilerServices;
using Xunit;
namespace Bunit.TestAssets;
/// <summary>
/// Wrap a test action or function in a try-catch block that captures a dump file if the test fails.
/// </summary>
/// <remarks>
/// This requires the <c>dotnet-dump</c> tool to be installed as a local dotnet tool.
/// </remarks>
public static class DumpCapture
{
public static async Task OnFailureAsync(
Action testAction,
ITestOutputHelper outputHelper,
[CallerMemberName] string testName = "",
[CallerFilePath] string testFilePath = "")
{
try
{
testAction();
}
catch
{
await CaptureDump(testName, testFilePath, outputHelper);
throw;
}
}
public static async Task OnFailureAsync(
Func<Task> testAction,
ITestOutputHelper outputHelper,
[CallerMemberName] string testName = "",
[CallerFilePath] string testFilePath = "")
{
try
{
await testAction();
}
catch
{
await CaptureDump(testName, testFilePath, outputHelper);
throw;
}
}
private static async Task CaptureDump(string testName, string testFilePath, ITestOutputHelper outputHelper)
{
#if NETSTANDARD2_1
var processId = Process.GetCurrentProcess().Id;
#else
var processId = Environment.ProcessId;
#endif
var dumpFilePath = Path.Combine(Directory.GetCurrentDirectory(), $"{Path.GetFileNameWithoutExtension(testFilePath)}-{testName}-wait-failed-{Guid.NewGuid()}.dmp");
// Attempt to start the dotnet-dump process
var startInfo = new ProcessStartInfo
{
FileName = "dotnet",
Arguments = $"dotnet-dump collect -p {processId} -o {dumpFilePath}",
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
};
using var process = Process.Start(startInfo);
if (process is null)
{
outputHelper.WriteLine(" Failed to start dotnet-dump process.");
return;
}
#if NETSTANDARD2_1
process.WaitForExit();
#else
await process.WaitForExitAsync();
#endif
var output = await process.StandardOutput.ReadToEndAsync();
var error = await process.StandardError.ReadToEndAsync();
outputHelper.WriteLine($"Dump status: {{process.ExitCode}}. Dump file: {dumpFilePath}");
if (!string.IsNullOrWhiteSpace(output))
{
outputHelper.WriteLine($"Dump output: {output}");
}
if (!string.IsNullOrWhiteSpace(error))
{
outputHelper.WriteLine($"Dump error: {error}");
}
}
}