| """ |
| Test that stepping works even when the OS Plugin doesn't report |
| all threads at every stop. |
| """ |
| |
| from __future__ import print_function |
| |
| |
| import os |
| import lldb |
| from lldbsuite.test.decorators import * |
| from lldbsuite.test.lldbtest import * |
| import lldbsuite.test.lldbutil as lldbutil |
| |
| |
| class TestOSPluginStepping(TestBase): |
| |
| mydir = TestBase.compute_mydir(__file__) |
| NO_DEBUG_INFO_TESTCASE = True |
| |
| @skipIfWindows |
| def test_python_os_plugin(self): |
| """Test that stepping works when the OS Plugin doesn't report all |
| threads at every stop""" |
| self.build() |
| self.main_file = lldb.SBFileSpec('main.cpp') |
| self.run_python_os_step_missing_thread(False) |
| |
| @skipIfWindows |
| def test_python_os_plugin_prune(self): |
| """Test that pruning the unreported PlanStacks works""" |
| self.build() |
| self.main_file = lldb.SBFileSpec('main.cpp') |
| self.run_python_os_step_missing_thread(True) |
| |
| def get_os_thread(self): |
| return self.process.GetThreadByID(0x111111111) |
| |
| def is_os_thread(self, thread): |
| id = thread.GetID() |
| return id == 0x111111111 |
| |
| def run_python_os_step_missing_thread(self, do_prune): |
| """Test that the Python operating system plugin works correctly""" |
| |
| # Our OS plugin does NOT report all threads: |
| result = self.dbg.HandleCommand("settings set target.experimental.os-plugin-reports-all-threads false") |
| |
| python_os_plugin_path = os.path.join(self.getSourceDir(), |
| "operating_system.py") |
| (target, self.process, thread, thread_bkpt) = lldbutil.run_to_source_breakpoint( |
| self, "first stop in thread - do a step out", self.main_file) |
| |
| main_bkpt = target.BreakpointCreateBySourceRegex('Stop here and do not make a memory thread for thread_1', |
| self.main_file) |
| self.assertEqual(main_bkpt.GetNumLocations(), 1, "Main breakpoint has one location") |
| |
| # There should not be an os thread before we load the plugin: |
| self.assertFalse(self.get_os_thread().IsValid(), "No OS thread before loading plugin") |
| |
| # Now load the python OS plug-in which should update the thread list and we should have |
| # an OS plug-in thread overlaying thread_1 with id 0x111111111 |
| command = "settings set target.process.python-os-plugin-path '%s'" % python_os_plugin_path |
| self.dbg.HandleCommand(command) |
| |
| # Verify our OS plug-in threads showed up |
| os_thread = self.get_os_thread() |
| self.assertTrue( |
| os_thread.IsValid(), |
| "Make sure we added the thread 0x111111111 after we load the python OS plug-in") |
| |
| # Now we are going to step-out. This should get interrupted by main_bkpt. We've |
| # set up the OS plugin so at this stop, we have lost the OS thread 0x111111111. |
| # Make sure both of these are true: |
| os_thread.StepOut() |
| |
| stopped_threads = lldbutil.get_threads_stopped_at_breakpoint(self.process, main_bkpt) |
| self.assertEqual(len(stopped_threads), 1, "Stopped at main_bkpt") |
| thread = self.process.GetThreadByID(0x111111111) |
| self.assertFalse(thread.IsValid(), "No thread 0x111111111 on second stop.") |
| |
| # Make sure we still have the thread plans for this thread: |
| # First, don't show unreported threads, that should fail: |
| command = "thread plan list -t 0x111111111" |
| result = lldb.SBCommandReturnObject() |
| interp = self.dbg.GetCommandInterpreter() |
| interp.HandleCommand(command, result) |
| self.assertFalse(result.Succeeded(), "We found no plans for the unreported thread.") |
| # Now do it again but with the -u flag: |
| command = "thread plan list -u -t 0x111111111" |
| result = lldb.SBCommandReturnObject() |
| interp.HandleCommand(command, result) |
| self.assertTrue(result.Succeeded(), "We found plans for the unreported thread.") |
| |
| if do_prune: |
| # Prune the thread plan and continue, and we will run to exit. |
| interp.HandleCommand("thread plan prune 0x111111111", result) |
| self.assertTrue(result.Succeeded(), "Found the plan for 0x111111111 and pruned it") |
| |
| # List again, make sure it doesn't work: |
| command = "thread plan list -u -t 0x111111111" |
| interp.HandleCommand(command, result) |
| self.assertFalse(result.Succeeded(), "We still found plans for the unreported thread.") |
| |
| self.process.Continue() |
| self.assertEqual(self.process.GetState(), lldb.eStateExited, "We exited.") |
| else: |
| # Now we are going to continue, and when we hit the step-out breakpoint, we will |
| # put the OS plugin thread back, lldb will recover its ThreadPlanStack, and |
| # we will stop with a "step-out" reason. |
| self.process.Continue() |
| os_thread = self.get_os_thread() |
| self.assertTrue(os_thread.IsValid(), "The OS thread is back after continue") |
| self.assertTrue("step out" in os_thread.GetStopDescription(100), "Completed step out plan") |
| |
| |