From 7b6a8d93a72cb9786690f7afc53d4cc94f91f7b8 Mon Sep 17 00:00:00 2001 From: Andrew Wang Date: Mon, 18 May 2026 11:23:18 -0700 Subject: [PATCH] Enable disabled DAR Linux tests (CppTests) Re-enable 5 tests on GitHub Linux runners: - CoreDumpBasic, CoreDumpBasicMismatchedSourceAndSymbols, CoreDumpVerifyActions - ExecutionAsyncBreak - RunModeBreakpoints CI changes: - Set kernel.core_pattern=core so dumps land in CWD (debuggee output dir) - Set core_uses_pid=0 (test expects file named 'core', no PID suffix) - Disable apport service which intercepts core dumps on Ubuntu - Run tests in subshell with ulimit -c unlimited (scoped, resets on exit) Test fixes (latent bugs in previously-disabled tests): - CoreDumpVerifyActions: Assert.Contains args were inverted. xUnit signature is (expectedSubstring, actualString) but the test had them backwards. - ExecutionAsyncBreak: Test was sending pause before the inferior was running. Use a function breakpoint to confirm the loop is executing, then continue and async break. Also fix shouldExit access via 'this' (member variable). Relates to: https://github.com/microsoft/MIEngine/issues/1170 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/Build-And-Test.yml | 9 ++++----- eng/Scripts/CI-Test.sh | 6 +++++- test/CppTests/Tests/BreakpointTests.cs | 3 +-- test/CppTests/Tests/CoreDumpTests.cs | 19 +++++-------------- test/CppTests/Tests/ExecutionTests.cs | 22 +++++++++++++++++++--- 5 files changed, 34 insertions(+), 25 deletions(-) diff --git a/.github/workflows/Build-And-Test.yml b/.github/workflows/Build-And-Test.yml index aec71a4df..db5f95201 100644 --- a/.github/workflows/Build-And-Test.yml +++ b/.github/workflows/Build-And-Test.yml @@ -130,11 +130,10 @@ jobs: which g++ which gdb echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope - # TODO: Try to make core dumps work - # Related CoreDump Tests: https://github.com/microsoft/MIEngine/issues/1170 - # echo 1 | sudo tee /proc/sys/kernel/core_uses_pid - # ulimit -S -c unlimited - # sudo sysctl -w kernel.core_pattern=${{ github.workspace }}/core.%e + # Enable core dumps: set pattern to "core" so dumps land in CWD (the debuggee output dir) + echo core | sudo tee /proc/sys/kernel/core_pattern + echo 0 | sudo tee /proc/sys/kernel/core_uses_pid + sudo systemctl disable apport.service 2>/dev/null || true - run: | ${{ github.workspace }}/eng/Scripts/CI-Build.sh diff --git a/eng/Scripts/CI-Test.sh b/eng/Scripts/CI-Test.sh index fd9c4c60a..24f9a9bf1 100755 --- a/eng/Scripts/CI-Test.sh +++ b/eng/Scripts/CI-Test.sh @@ -19,4 +19,8 @@ if [ ! -f "$RootDir/bin/DebugAdapterProtocolTests/Debug/CppTests/config.xml" ]; fi fi -dotnet test "$RootDir"/bin/DebugAdapterProtocolTests/Debug/CppTests/CppTests.dll --logger "trx;LogFileName=$RootDir/bin/DebugAdapterProtocolTests/Debug/CppTests/results.trx" \ No newline at end of file +# Run tests in a subshell with core dumps enabled (ulimit resets when subshell exits) +( + ulimit -c unlimited + dotnet test "$RootDir"/bin/DebugAdapterProtocolTests/Debug/CppTests/CppTests.dll --logger "trx;LogFileName=$RootDir/bin/DebugAdapterProtocolTests/Debug/CppTests/results.trx" +) diff --git a/test/CppTests/Tests/BreakpointTests.cs b/test/CppTests/Tests/BreakpointTests.cs index 15de99b8f..358d70a8f 100644 --- a/test/CppTests/Tests/BreakpointTests.cs +++ b/test/CppTests/Tests/BreakpointTests.cs @@ -202,9 +202,8 @@ public void LineLogBreakpointsBasic(ITestSettings settings) [DependsOnTest(nameof(CompileKitchenSinkForBreakpointTests))] [RequiresTestSettings] // TODO: https://github.com/microsoft/MIEngine/issues/1170 - // - gdb_gnu // - lldb - [UnsupportedDebugger(SupportedDebugger.Lldb | SupportedDebugger.Gdb_Gnu | SupportedDebugger.Gdb_Cygwin | SupportedDebugger.Gdb_MinGW, SupportedArchitecture.x64 | SupportedArchitecture.x86)] + [UnsupportedDebugger(SupportedDebugger.Lldb | SupportedDebugger.Gdb_Cygwin | SupportedDebugger.Gdb_MinGW, SupportedArchitecture.x64 | SupportedArchitecture.x86)] public void RunModeBreakpoints(ITestSettings settings) { this.TestPurpose("Tests setting breakpoints while in run mode"); diff --git a/test/CppTests/Tests/CoreDumpTests.cs b/test/CppTests/Tests/CoreDumpTests.cs index f1a6e00e7..ef85aa366 100644 --- a/test/CppTests/Tests/CoreDumpTests.cs +++ b/test/CppTests/Tests/CoreDumpTests.cs @@ -51,9 +51,6 @@ public CoreDumpTests(ITestOutputHelper outputHelper) : base(outputHelper) [Theory] [RequiresTestSettings] [SupportedPlatform(SupportedPlatform.Linux, SupportedArchitecture.x64 | SupportedArchitecture.x86)] - // TODO: https://github.com/microsoft/MIEngine/issues/1170 - // - gdb_gnu - [UnsupportedDebugger(SupportedDebugger.Gdb_Gnu, SupportedArchitecture.x64 | SupportedArchitecture.x86)] public void CoreDumpBasic(ITestSettings settings) { this.TestPurpose("This test checks to see if core dump can be launched successfully"); @@ -69,9 +66,6 @@ public void CoreDumpBasic(ITestSettings settings) [Theory] [RequiresTestSettings] [SupportedPlatform(SupportedPlatform.Linux, SupportedArchitecture.x64 | SupportedArchitecture.x86)] - // TODO: https://github.com/microsoft/MIEngine/issues/1170 - // - gdb_gnu - [UnsupportedDebugger(SupportedDebugger.Gdb_Gnu, SupportedArchitecture.x64 | SupportedArchitecture.x86)] public void CoreDumpBasicMismatchedSourceAndSymbols(ITestSettings settings) { this.TestPurpose("This test checks to see if core dump can be launched successfully with mismathed source code."); @@ -90,9 +84,6 @@ public void CoreDumpBasicMismatchedSourceAndSymbols(ITestSettings settings) [Theory] [RequiresTestSettings] [SupportedPlatform(SupportedPlatform.Linux, SupportedArchitecture.x64 | SupportedArchitecture.x86)] - // TODO: https://github.com/microsoft/MIEngine/issues/1170 - // - gdb_gnu - [UnsupportedDebugger(SupportedDebugger.Gdb_Gnu, SupportedArchitecture.x64 | SupportedArchitecture.x86)] public void CoreDumpVerifyActions(ITestSettings settings) { this.TestPurpose("This test checks to see the behavior when do actions during core dump debugging."); @@ -144,32 +135,32 @@ public void CoreDumpVerifyActions(ITestSettings settings) StepInCommand stepInCommand = new StepInCommand(runner.DarRunner.CurrentThreadId); runner.RunCommandExpectFailure(stepInCommand); this.WriteLine(string.Format(CultureInfo.InvariantCulture, "Actual respone message: {0}", stepInCommand.Message)); - Assert.Contains(stepInCommand.Message, string.Format(CultureInfo.InvariantCulture, stepError, "step in")); + Assert.Contains(string.Format(CultureInfo.InvariantCulture, stepError, "step in"), stepInCommand.Message); this.Comment("Try to step over and verify the error message"); StepOverCommand stepOverCommand = new StepOverCommand(runner.DarRunner.CurrentThreadId); runner.RunCommandExpectFailure(stepOverCommand); this.WriteLine(string.Format(CultureInfo.InvariantCulture, "Actual respone message: {0}", stepOverCommand.Message)); - Assert.Contains(stepOverCommand.Message, string.Format(CultureInfo.InvariantCulture, stepError, "step next")); + Assert.Contains(string.Format(CultureInfo.InvariantCulture, stepError, "step next"), stepOverCommand.Message); this.Comment("Try to step out and verify the error message"); StepOutCommand stepOutCommand = new StepOutCommand(runner.DarRunner.CurrentThreadId); runner.RunCommandExpectFailure(stepOutCommand); this.WriteLine(string.Format(CultureInfo.InvariantCulture, "Actual respone message: {0}", stepOutCommand.Message)); - Assert.Contains(stepOutCommand.Message, string.Format(CultureInfo.InvariantCulture, stepError, "step out")); + Assert.Contains(string.Format(CultureInfo.InvariantCulture, stepError, "step out"), stepOutCommand.Message); this.Comment("Try to continue and verify the error message"); ContinueCommand continueCommand = new ContinueCommand(runner.DarRunner.CurrentThreadId); runner.RunCommandExpectFailure(continueCommand); this.WriteLine(string.Format(CultureInfo.InvariantCulture, "Actual respone message: {0}", continueCommand.Message)); - Assert.Contains(continueCommand.Message, string.Format(CultureInfo.InvariantCulture, stepError, "continue")); + Assert.Contains(string.Format(CultureInfo.InvariantCulture, stepError, "continue"), continueCommand.Message); this.Comment("Try to set a breakpoint and verify the error message"); SourceBreakpoints bp = debuggee.Breakpoints(srcAppName, 16); SetBreakpointsResponseValue setBpResponse = runner.SetBreakpoints(bp); Assert.False(setBpResponse.body.breakpoints[0].verified); this.WriteLine(string.Format(CultureInfo.InvariantCulture, "Actual respone message: {0}", setBpResponse.body.breakpoints[0].message)); - Assert.Contains(setBpResponse.body.breakpoints[0].message, bpError); + Assert.Contains(bpError, setBpResponse.body.breakpoints[0].message); this.Comment("Stop core dump debugging"); runner.DisconnectAndVerify(); diff --git a/test/CppTests/Tests/ExecutionTests.cs b/test/CppTests/Tests/ExecutionTests.cs index 916285b9b..0439c2658 100644 --- a/test/CppTests/Tests/ExecutionTests.cs +++ b/test/CppTests/Tests/ExecutionTests.cs @@ -177,8 +177,8 @@ public void ExecutionStepRecursiveCall(ITestSettings settings) [Theory] [DependsOnTest(nameof(CompileKitchenSinkForExecution))] [RequiresTestSettings] - // TODO: Re-enable for VsDbg and Gdb_Gnu - [UnsupportedDebugger(SupportedDebugger.Gdb_Cygwin | SupportedDebugger.Gdb_MinGW | SupportedDebugger.Gdb_Gnu | SupportedDebugger.Lldb | SupportedDebugger.VsDbg, SupportedArchitecture.x86 | SupportedArchitecture.x64)] + // TODO: Re-enable for VsDbg + [UnsupportedDebugger(SupportedDebugger.Gdb_Cygwin | SupportedDebugger.Gdb_MinGW | SupportedDebugger.Lldb | SupportedDebugger.VsDbg, SupportedArchitecture.x86 | SupportedArchitecture.x64)] public void ExecutionAsyncBreak(ITestSettings settings) { this.TestPurpose("Verify break all should work run function"); @@ -192,6 +192,22 @@ public void ExecutionAsyncBreak(ITestSettings settings) this.Comment("Configure launch"); runner.Launch(settings.DebuggerSettings, debuggee, "-fNonTerminating", "-fCalling"); + // Use a function breakpoint to deterministically confirm the debuggee is running + // before sending async break. Without this, the pause can arrive before GDB has + // fully started the inferior, resulting in no stopped event. + this.Comment("Set a function breakpoint to verify the debuggee enters the loop"); + FunctionBreakpoints funcBp = new FunctionBreakpoints("NonTerminating::DoSleep"); + runner.SetFunctionBreakpoints(funcBp); + + this.Comment("Start running and hit the function breakpoint"); + runner.ExpectBreakpointAndStepToTarget(SinkHelper.NonTerminating, startLine: 37, targetLine: 38) + .AfterConfigurationDone(); + + this.Comment("Remove the function breakpoint and continue so the debuggee is in run mode"); + funcBp.Remove("NonTerminating::DoSleep"); + runner.SetFunctionBreakpoints(funcBp); + runner.Continue(); + this.Comment("Try to break all"); StoppedEvent breakAllEvent = new StoppedEvent(StoppedReason.Pause); runner.Expects.Event(breakAllEvent).AfterAsyncBreak(); @@ -210,7 +226,7 @@ public void ExecutionAsyncBreak(ITestSettings settings) { IFrameInspector firstFrame = threadInspector.Stack.First(); this.WriteLine(firstFrame.ToString()); - firstFrame.GetVariable("shouldExit").Value = "true"; + firstFrame.GetVariable("this", "shouldExit").Value = "1"; } this.Comment("Continue running at the end of application");