public Task DumpTest(DiagnosticPortConnectionMode mode, DumpType type) { #if !NET6_0_OR_GREATER // Capturing non-full dumps via diagnostic command works inconsistently // on Alpine for .NET 5 and lower (the dump command will return successfully, but) // the dump file will not exist). Only test other dump types on .NET 6+ if (DistroInformation.IsAlpineLinux && type != DumpType.Full) { _outputHelper.WriteLine("Skipped on Alpine for .NET 5 and lower."); return(Task.CompletedTask); } #endif return(ScenarioRunner.SingleTarget( _outputHelper, _httpClientFactory, mode, TestAppScenarios.AsyncWait.Name, appValidate: async(runner, client) => { int processId = await runner.ProcessIdTask; using ResponseStreamHolder holder = await client.CaptureDumpAsync(processId, type); Assert.NotNull(holder); // The dump operation may still be in progress but the process should still be discoverable. // If this check fails, then the dump operation is causing dotnet-monitor to not be able // to observe the process any more. ProcessInfo processInfo = await client.GetProcessAsync(processId); Assert.NotNull(processInfo); await DumpTestUtilities.ValidateDump(runner.Environment.ContainsKey(DumpTestUtilities.EnableElfDumpOnMacOS), holder.Stream); await runner.SendCommandAsync(TestAppScenarios.AsyncWait.Commands.Continue); }, configureApp: runner => { // MachO not supported on .NET 5, only ELF: https://github.com/dotnet/runtime/blob/main/docs/design/coreclr/botr/xplat-minidump-generation.md#os-x if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && DotNetHost.RuntimeVersion.Major == 5) { runner.Environment.Add(DumpTestUtilities.EnableElfDumpOnMacOS, "1"); } }, configureTool: runner => { string dumpTempFolder = Path.Combine(runner.TempPath, "Dumps"); // The dump temp folder should not exist in order to test that capturing dumps into the folder // will work since dotnet-monitor should ensure the folder is created before issuing the dump command. Assert.False(Directory.Exists(dumpTempFolder), "The dump temp folder should not exist."); runner.ConfigurationFromEnvironment.SetDumpTempFolder(dumpTempFolder); })); }
public async Task CollectDumpAction_Success(TargetFrameworkMoniker tfm, DumpType?dumpType) { // MacOS dumps inconsistently segfault the runtime on .NET 5: https://github.com/dotnet/dotnet-monitor/issues/174 if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && tfm == TargetFrameworkMoniker.Net50) { return; } using TemporaryDirectory tempDirectory = new(_outputHelper); await TestHostHelper.CreateCollectionRulesHost(_outputHelper, rootOptions => { rootOptions.AddFileSystemEgress(ActionTestsConstants.ExpectedEgressProvider, tempDirectory.FullName); rootOptions.CreateCollectionRule(DefaultRuleName) .AddCollectDumpAction(ActionTestsConstants.ExpectedEgressProvider, dumpType) .SetStartupTrigger(); }, async host => { CollectDumpOptions options = ActionTestsHelper.GetActionOptions <CollectDumpOptions>(host, DefaultRuleName); ICollectionRuleActionFactoryProxy factory; Assert.True(host.Services.GetService <ICollectionRuleActionOperations>().TryCreateFactory(KnownCollectionRuleActions.CollectDump, out factory)); EndpointInfoSourceCallback callback = new(_outputHelper); await using ServerSourceHolder sourceHolder = await _endpointUtilities.StartServerAsync(callback); AppRunner runner = _endpointUtilities.CreateAppRunner(sourceHolder.TransportName, tfm); Task <IEndpointInfo> newEndpointInfoTask = callback.WaitAddedEndpointInfoAsync(runner, CommonTestTimeouts.StartProcess); await runner.ExecuteAsync(async() => { IEndpointInfo endpointInfo = await newEndpointInfoTask; ICollectionRuleAction action = factory.Create(endpointInfo, options); CollectionRuleActionResult result = await ActionTestsHelper.ExecuteAndDisposeAsync(action, CommonTestTimeouts.DumpTimeout); string egressPath = ActionTestsHelper.ValidateEgressPath(result); using FileStream dumpStream = new(egressPath, FileMode.Open, FileAccess.Read); Assert.NotNull(dumpStream); await DumpTestUtilities.ValidateDump(runner.Environment.ContainsKey(DumpTestUtilities.EnableElfDumpOnMacOS), dumpStream); await runner.SendCommandAsync(TestAppScenarios.AsyncWait.Commands.Continue); }); }); }