xref: /llvm-project/lldb/test/API/functionalities/plugins/python_os_plugin/TestPythonOSPlugin.py (revision 80fcecb13c388ff087a27a4b0e7ca3dd8c98eaa4)
1"""
2Test that the Python operating system plugin works correctly
3"""
4
5
6import os
7import lldb
8from lldbsuite.test.lldbtest import *
9import lldbsuite.test.lldbutil as lldbutil
10
11
12class PluginPythonOSPlugin(TestBase):
13    NO_DEBUG_INFO_TESTCASE = True
14
15    def test_python_os_plugin(self):
16        """Test that the Python operating system plugin works correctly"""
17        self.build()
18        self.run_python_os_funcionality()
19
20    def run_python_os_step(self):
21        """Test that the Python operating system plugin works correctly when single stepping a virtual thread"""
22        self.build()
23        self.run_python_os_step()
24
25    def verify_os_thread_registers(self, thread):
26        frame = thread.GetFrameAtIndex(0)
27        registers = frame.GetRegisters().GetValueAtIndex(0)
28        reg_value = thread.GetThreadID() + 1
29        for reg in registers:
30            self.assertEqual(
31                reg.GetValueAsUnsigned(),
32                reg_value,
33                "Verify the registers contains the correct value",
34            )
35            reg_value = reg_value + 1
36
37    def run_python_os_funcionality(self):
38        """Test that the Python operating system plugin works correctly"""
39
40        # Set debugger into synchronous mode
41        self.dbg.SetAsync(False)
42
43        # Create a target by the debugger.
44        exe = self.getBuildArtifact("a.out")
45        python_os_plugin_path = os.path.join(self.getSourceDir(), "operating_system.py")
46        target = self.dbg.CreateTarget(exe)
47        self.assertTrue(target, VALID_TARGET)
48
49        # Set breakpoints inside and outside methods that take pointers to the
50        # containing struct.
51        lldbutil.run_break_set_by_source_regexp(self, "// Set breakpoint here")
52
53        # Register our shared libraries for remote targets so they get
54        # automatically uploaded
55        arguments = None
56        environment = None
57
58        # Now launch the process, and do not stop at entry point.
59        process = target.LaunchSimple(
60            arguments, environment, self.get_process_working_directory()
61        )
62        self.assertTrue(process, PROCESS_IS_VALID)
63
64        # Make sure there are no OS plug-in created thread when we first stop
65        # at our breakpoint in main
66        thread = process.GetThreadByID(0x111111111)
67        self.assertFalse(
68            thread.IsValid(),
69            "Make sure there is no thread 0x111111111 before we load the python OS plug-in",
70        )
71        thread = process.GetThreadByID(0x222222222)
72        self.assertFalse(
73            thread.IsValid(),
74            "Make sure there is no thread 0x222222222 before we load the python OS plug-in",
75        )
76        thread = process.GetThreadByID(0x333333333)
77        self.assertFalse(
78            thread.IsValid(),
79            "Make sure there is no thread 0x333333333 before we load the python OS plug-in",
80        )
81
82        # Now load the python OS plug-in which should update the thread list and we should have
83        # OS plug-in created threads with the IDs: 0x111111111, 0x222222222,
84        # 0x333333333
85        command = (
86            "settings set target.process.python-os-plugin-path '%s'"
87            % python_os_plugin_path
88        )
89        self.dbg.HandleCommand(command)
90
91        # Verify our OS plug-in threads showed up
92        thread = process.GetThreadByID(0x111111111)
93        self.assertTrue(
94            thread.IsValid(),
95            "Make sure there is a thread 0x111111111 after we load the python OS plug-in",
96        )
97        self.verify_os_thread_registers(thread)
98        thread = process.GetThreadByID(0x222222222)
99        self.assertTrue(
100            thread.IsValid(),
101            "Make sure there is a thread 0x222222222 after we load the python OS plug-in",
102        )
103        self.verify_os_thread_registers(thread)
104        thread = process.GetThreadByID(0x333333333)
105        self.assertTrue(
106            thread.IsValid(),
107            "Make sure there is a thread 0x333333333 after we load the python OS plug-in",
108        )
109        self.verify_os_thread_registers(thread)
110
111        # Now clear the OS plug-in path to make the OS plug-in created threads
112        # disappear
113        self.dbg.HandleCommand("settings clear target.process.python-os-plugin-path")
114
115        # Verify the threads are gone after unloading the python OS plug-in
116        thread = process.GetThreadByID(0x111111111)
117        self.assertFalse(
118            thread.IsValid(),
119            "Make sure there is no thread 0x111111111 after we unload the python OS plug-in",
120        )
121        thread = process.GetThreadByID(0x222222222)
122        self.assertFalse(
123            thread.IsValid(),
124            "Make sure there is no thread 0x222222222 after we unload the python OS plug-in",
125        )
126        thread = process.GetThreadByID(0x333333333)
127        self.assertFalse(
128            thread.IsValid(),
129            "Make sure there is no thread 0x333333333 after we unload the python OS plug-in",
130        )
131
132    def run_python_os_step(self):
133        """Test that the Python operating system plugin works correctly and allows single stepping of a virtual thread that is backed by a real thread"""
134
135        # Set debugger into synchronous mode
136        self.dbg.SetAsync(False)
137
138        # Create a target by the debugger.
139        exe = self.getBuildArtifact("a.out")
140        python_os_plugin_path = os.path.join(
141            self.getSourceDir(), "operating_system2.py"
142        )
143        target = self.dbg.CreateTarget(exe)
144        self.assertTrue(target, VALID_TARGET)
145
146        # Set breakpoints inside and outside methods that take pointers to the
147        # containing struct.
148        lldbutil.run_break_set_by_source_regexp(self, "// Set breakpoint here")
149
150        # Register our shared libraries for remote targets so they get
151        # automatically uploaded
152        arguments = None
153        environment = None
154
155        # Now launch the process, and do not stop at entry point.
156        process = target.LaunchSimple(
157            arguments, environment, self.get_process_working_directory()
158        )
159        self.assertTrue(process, PROCESS_IS_VALID)
160
161        # Make sure there are no OS plug-in created thread when we first stop
162        # at our breakpoint in main
163        thread = process.GetThreadByID(0x111111111)
164        self.assertFalse(
165            thread.IsValid(),
166            "Make sure there is no thread 0x111111111 before we load the python OS plug-in",
167        )
168
169        # Now load the python OS plug-in which should update the thread list and we should have
170        # OS plug-in created threads with the IDs: 0x111111111, 0x222222222,
171        # 0x333333333
172        command = (
173            "settings set target.process.python-os-plugin-path '%s'"
174            % python_os_plugin_path
175        )
176        self.dbg.HandleCommand(command)
177
178        # Verify our OS plug-in threads showed up
179        thread = process.GetThreadByID(0x111111111)
180        self.assertTrue(
181            thread.IsValid(),
182            "Make sure there is a thread 0x111111111 after we load the python OS plug-in",
183        )
184
185        frame = thread.GetFrameAtIndex(0)
186        self.assertTrue(
187            frame.IsValid(), "Make sure we get a frame from thread 0x111111111"
188        )
189        line_entry = frame.GetLineEntry()
190
191        self.assertEqual(
192            line_entry.GetFileSpec().GetFilename(),
193            "main.c",
194            "Make sure we stopped on line 5 in main.c",
195        )
196        self.assertEqual(
197            line_entry.GetLine(), 5, "Make sure we stopped on line 5 in main.c"
198        )
199
200        # Now single step thread 0x111111111 and make sure it does what we need
201        # it to
202        thread.StepOver()
203
204        frame = thread.GetFrameAtIndex(0)
205        self.assertTrue(
206            frame.IsValid(), "Make sure we get a frame from thread 0x111111111"
207        )
208        line_entry = frame.GetLineEntry()
209
210        self.assertEqual(
211            line_entry.GetFileSpec().GetFilename(),
212            "main.c",
213            "Make sure we stepped from line 5 to line 6 in main.c",
214        )
215        self.assertEqual(
216            line_entry.GetLine(),
217            6,
218            "Make sure we stepped from line 5 to line 6 in main.c",
219        )
220