diff --git a/lldb/packages/Python/lldbsuite/test/lldbutil.py b/lldb/packages/Python/lldbsuite/test/lldbutil.py --- a/lldb/packages/Python/lldbsuite/test/lldbutil.py +++ b/lldb/packages/Python/lldbsuite/test/lldbutil.py @@ -235,7 +235,7 @@ elif enum == lldb.eStateSuspended: return "suspended" else: - raise Exception("Unknown StateType enum") + raise Exception("Unknown StateType enum: " + str(enum)) def stop_reason_to_str(enum): @@ -945,7 +945,22 @@ test.assertFalse(error.Fail(), "Process launch failed: %s" % (error.GetCString())) - test.assertState(process.GetState(), lldb.eStateStopped) + def processStateInfo(process): + info = "state: {}".format(state_type_to_str(process.state)) + if process.state == lldb.eStateExited: + info += ", exit code: {}".format(process.GetExitStatus()) + if process.exit_description: + info += ", exit description: '{}'".format(process.exit_description) + stdout = process.GetSTDOUT(999) + if stdout: + info += ", stdout: '{}'".format(stdout) + stderr = process.GetSTDERR(999) + if stderr: + info += ", stderr: '{}'".format(stderr) + return info + + if process.state != lldb.eStateStopped: + test.fail("Test process is not stopped at breakpoint: {}".format(processStateInfo(process))) # Frame #0 should be at our breakpoint. threads = get_threads_stopped_at_breakpoint( diff --git a/lldb/test/API/lldbutil-tests/failed-to-hit-breakpoint/Makefile b/lldb/test/API/lldbutil-tests/failed-to-hit-breakpoint/Makefile new file mode 100644 --- /dev/null +++ b/lldb/test/API/lldbutil-tests/failed-to-hit-breakpoint/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/lldb/test/API/lldbutil-tests/failed-to-hit-breakpoint/TestLLDBUtilFailedToHitBreakpoint.py b/lldb/test/API/lldbutil-tests/failed-to-hit-breakpoint/TestLLDBUtilFailedToHitBreakpoint.py new file mode 100644 --- /dev/null +++ b/lldb/test/API/lldbutil-tests/failed-to-hit-breakpoint/TestLLDBUtilFailedToHitBreakpoint.py @@ -0,0 +1,27 @@ +""" +Tests lldbutil's behavior when running to a source breakpoint fails. +""" + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * + + +class LLDBUtilFailedToHitBreakpointTest(TestBase): + + NO_DEBUG_INFO_TESTCASE = True + + @expectedFailureAll(oslist=["windows"]) + def test_error_message(self): + """ + Tests that run_to_source_breakpoint prints the right error message + when failing to hit the wanted breakpoint. + """ + self.build() + with self.assertRaisesRegex( + AssertionError, + "Test process is not stopped at breakpoint: state: exited, exit code: 0, stdout: 'stdout_needlestderr_needle'" + ): + lldbutil.run_to_source_breakpoint(self, "// break here", + lldb.SBFileSpec("main.cpp")) diff --git a/lldb/test/API/lldbutil-tests/failed-to-hit-breakpoint/main.cpp b/lldb/test/API/lldbutil-tests/failed-to-hit-breakpoint/main.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/API/lldbutil-tests/failed-to-hit-breakpoint/main.cpp @@ -0,0 +1,21 @@ +#include +#include + +int main(int argc, char **argv) { + // Print the string that the test looks for to make sure stdout and stderr + // got recorded. + std::cout << "stdout_needle" << std::flush; + std::cerr << "stderr_needle" << std::flush; + + // Work around a timing issue that sometimes prevents stderr from being + // captured. + std::this_thread::sleep_for(std::chrono::seconds(1)); + + // This is unreachable during normal test execution as we don't pass any + // (or +100) arguments. This still needs to be theoretically reachable code + // so that the compiler will generate code for this (that we can set a + // breakpoint on). + if (argc > 100) + return 1; // break here + return 0; +}