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