xref: /llvm-project/lldb/test/API/functionalities/inferior-changed/TestInferiorChanged.py (revision 2238dcc39358353cac21df75c3c3286ab20b8f53)
1"""Test lldb reloads the inferior after it was changed during the session."""
2
3
4import time
5import lldb
6from lldbsuite.test.decorators import *
7from lldbsuite.test.lldbtest import *
8from lldbsuite.test import configuration
9from lldbsuite.test import lldbutil
10
11
12class ChangedInferiorTestCase(TestBase):
13    @skipIf(hostoslist=["windows"])
14    @no_debug_info_test
15    def test_inferior_crashing(self):
16        """Test lldb reloads the inferior after it was changed during the session."""
17        self.build()
18        self.inferior_crashing()
19        self.cleanup()
20        # lldb needs to recognize the inferior has changed. If lldb needs to check the
21        # new module timestamp, make sure it is not the same as the old one, so add a
22        # 1 second delay.
23        time.sleep(1)
24        d = {"C_SOURCES": "main2.c"}
25        self.build(dictionary=d)
26        self.setTearDownCleanup(dictionary=d)
27        self.inferior_not_crashing()
28
29    def setUp(self):
30        # Call super's setUp().
31        TestBase.setUp(self)
32        # Find the line number of the crash.
33        self.line1 = line_number("main.c", "// Crash here.")
34        self.line2 = line_number("main2.c", "// Not crash here.")
35
36    def inferior_crashing(self):
37        """Inferior crashes upon launching; lldb should catch the event and stop."""
38        self.exe = self.getBuildArtifact("a.out")
39        self.runCmd("file " + self.exe, CURRENT_EXECUTABLE_SET)
40
41        self.runCmd("run", RUN_SUCCEEDED)
42
43        # We should have one crashing thread
44        self.assertEqual(
45            len(
46                lldbutil.get_crashed_threads(
47                    self, self.dbg.GetSelectedTarget().GetProcess()
48                )
49            ),
50            1,
51            STOPPED_DUE_TO_EXC_BAD_ACCESS,
52        )
53
54        # And it should report the correct line number.
55        self.expect("thread backtrace all", substrs=["main.c:%d" % self.line1])
56
57    def inferior_not_crashing(self):
58        """Test lldb reloads the inferior after it was changed during the session."""
59        self.runCmd("process kill")
60        self.runCmd("run", RUN_SUCCEEDED)
61        self.runCmd("process status")
62
63        self.assertNotEqual(
64            len(
65                lldbutil.get_crashed_threads(
66                    self, self.dbg.GetSelectedTarget().GetProcess()
67                )
68            ),
69            1,
70            "Inferior changed, but lldb did not perform a reload",
71        )
72
73        # Break inside the main.
74        lldbutil.run_break_set_by_file_and_line(
75            self, "main2.c", self.line2, num_expected_locations=1, loc_exact=True
76        )
77
78        self.runCmd("run", RUN_SUCCEEDED)
79
80        # The stop reason of the thread should be breakpoint.
81        self.expect(
82            "thread list",
83            STOPPED_DUE_TO_BREAKPOINT,
84            substrs=["stopped", "stop reason = breakpoint"],
85        )
86
87        self.runCmd("frame variable int_ptr")
88        self.expect("frame variable *int_ptr", substrs=["= 7"])
89        self.expect("expression *int_ptr", substrs=["= 7"])
90