xref: /llvm-project/lldb/test/API/python_api/thread/TestThreadAPI.py (revision 3e06392c7db0eacfca94a176d430d9988b3ffbd6)
199451b44SJordan Rupprecht"""
299451b44SJordan RupprechtTest SBThread APIs.
399451b44SJordan Rupprecht"""
499451b44SJordan Rupprecht
599451b44SJordan Rupprechtimport lldb
699451b44SJordan Rupprechtfrom lldbsuite.test.decorators import *
799451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import *
899451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil
999451b44SJordan Rupprechtfrom lldbsuite.test.lldbutil import get_stopped_thread, get_caller_symbol
1099451b44SJordan Rupprecht
1199451b44SJordan Rupprecht
1299451b44SJordan Rupprechtclass ThreadAPITestCase(TestBase):
1399451b44SJordan Rupprecht    def test_get_process(self):
1499451b44SJordan Rupprecht        """Test Python SBThread.GetProcess() API."""
1599451b44SJordan Rupprecht        self.build()
1699451b44SJordan Rupprecht        self.get_process()
1799451b44SJordan Rupprecht
1899451b44SJordan Rupprecht    def test_get_stop_description(self):
1999451b44SJordan Rupprecht        """Test Python SBThread.GetStopDescription() API."""
2099451b44SJordan Rupprecht        self.build()
2199451b44SJordan Rupprecht        self.get_stop_description()
2299451b44SJordan Rupprecht
2399451b44SJordan Rupprecht    def test_run_to_address(self):
2499451b44SJordan Rupprecht        """Test Python SBThread.RunToAddress() API."""
2599451b44SJordan Rupprecht        # We build a different executable than the default build() does.
262238dcc3SJonas Devlieghere        d = {"CXX_SOURCES": "main2.cpp", "EXE": self.exe_name}
2799451b44SJordan Rupprecht        self.build(dictionary=d)
2899451b44SJordan Rupprecht        self.setTearDownCleanup(dictionary=d)
2999451b44SJordan Rupprecht        self.run_to_address(self.exe_name)
3099451b44SJordan Rupprecht
3160dff35fSAdrian Prantl    @skipIfAsan  # The output looks different under ASAN.
322238dcc3SJonas Devlieghere    @expectedFailureAll(oslist=["linux"], archs=["arm"], bugnumber="llvm.org/pr45892")
3399451b44SJordan Rupprecht    @expectedFailureAll(oslist=["windows"])
3499451b44SJordan Rupprecht    def test_step_out_of_malloc_into_function_b(self):
3599451b44SJordan Rupprecht        """Test Python SBThread.StepOut() API to step out of a malloc call where the call site is at function b()."""
3699451b44SJordan Rupprecht        # We build a different executable than the default build() does.
372238dcc3SJonas Devlieghere        d = {"CXX_SOURCES": "main2.cpp", "EXE": self.exe_name}
3899451b44SJordan Rupprecht        self.build(dictionary=d)
3999451b44SJordan Rupprecht        self.setTearDownCleanup(dictionary=d)
4099451b44SJordan Rupprecht        self.step_out_of_malloc_into_function_b(self.exe_name)
4199451b44SJordan Rupprecht
4299451b44SJordan Rupprecht    def test_step_over_3_times(self):
4399451b44SJordan Rupprecht        """Test Python SBThread.StepOver() API."""
4499451b44SJordan Rupprecht        # We build a different executable than the default build() does.
452238dcc3SJonas Devlieghere        d = {"CXX_SOURCES": "main2.cpp", "EXE": self.exe_name}
4699451b44SJordan Rupprecht        self.build(dictionary=d)
4799451b44SJordan Rupprecht        self.setTearDownCleanup(dictionary=d)
4899451b44SJordan Rupprecht        self.step_over_3_times(self.exe_name)
4999451b44SJordan Rupprecht
503ff63672SDave Lee    def test_negative_indexing(self):
513ff63672SDave Lee        """Test SBThread.frame with negative indexes."""
523ff63672SDave Lee        self.build()
533ff63672SDave Lee        self.validate_negative_indexing()
543ff63672SDave Lee
55845dee36Sjimingham    def test_StepInstruction(self):
56845dee36Sjimingham        """Test that StepInstruction preserves the plan stack."""
57845dee36Sjimingham        self.build()
58845dee36Sjimingham        self.step_instruction_in_called_function()
59845dee36Sjimingham
6099451b44SJordan Rupprecht    def setUp(self):
6199451b44SJordan Rupprecht        # Call super's setUp().
6299451b44SJordan Rupprecht        TestBase.setUp(self)
6399451b44SJordan Rupprecht        # Find the line number within main.cpp to break inside main().
6499451b44SJordan Rupprecht        self.break_line = line_number(
652238dcc3SJonas Devlieghere            "main.cpp", "// Set break point at this line and check variable 'my_char'."
662238dcc3SJonas Devlieghere        )
6799451b44SJordan Rupprecht        # Find the line numbers within main2.cpp for
6899451b44SJordan Rupprecht        # step_out_of_malloc_into_function_b() and step_over_3_times().
6999451b44SJordan Rupprecht        self.step_out_of_malloc = line_number(
702238dcc3SJonas Devlieghere            "main2.cpp", "// thread step-out of malloc into function b."
712238dcc3SJonas Devlieghere        )
7299451b44SJordan Rupprecht        self.after_3_step_overs = line_number(
732238dcc3SJonas Devlieghere            "main2.cpp", "// we should reach here after 3 step-over's."
742238dcc3SJonas Devlieghere        )
7599451b44SJordan Rupprecht
7699451b44SJordan Rupprecht        # We'll use the test method name as the exe_name for executable
77e9264b74SKazuaki Ishizaki        # compiled from main2.cpp.
7899451b44SJordan Rupprecht        self.exe_name = self.testMethodName
7999451b44SJordan Rupprecht
8099451b44SJordan Rupprecht    def get_process(self):
8199451b44SJordan Rupprecht        """Test Python SBThread.GetProcess() API."""
8299451b44SJordan Rupprecht        exe = self.getBuildArtifact("a.out")
8399451b44SJordan Rupprecht
8499451b44SJordan Rupprecht        target = self.dbg.CreateTarget(exe)
8599451b44SJordan Rupprecht        self.assertTrue(target, VALID_TARGET)
8699451b44SJordan Rupprecht
872238dcc3SJonas Devlieghere        breakpoint = target.BreakpointCreateByLocation("main.cpp", self.break_line)
8899451b44SJordan Rupprecht        self.assertTrue(breakpoint, VALID_BREAKPOINT)
8999451b44SJordan Rupprecht        self.runCmd("breakpoint list")
9099451b44SJordan Rupprecht
9199451b44SJordan Rupprecht        # Launch the process, and do not stop at the entry point.
922238dcc3SJonas Devlieghere        process = target.LaunchSimple(None, None, self.get_process_working_directory())
9399451b44SJordan Rupprecht
9499451b44SJordan Rupprecht        thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
9599451b44SJordan Rupprecht        self.assertTrue(
962238dcc3SJonas Devlieghere            thread.IsValid(), "There should be a thread stopped due to breakpoint"
972238dcc3SJonas Devlieghere        )
9899451b44SJordan Rupprecht        self.runCmd("process status")
9999451b44SJordan Rupprecht
10099451b44SJordan Rupprecht        proc_of_thread = thread.GetProcess()
101b321b429SJonas Devlieghere        self.trace("proc_of_thread:", proc_of_thread)
1020ed758b2SDave Lee        self.assertEqual(proc_of_thread.GetProcessID(), process.GetProcessID())
10399451b44SJordan Rupprecht
10499451b44SJordan Rupprecht    def get_stop_description(self):
10599451b44SJordan Rupprecht        """Test Python SBThread.GetStopDescription() API."""
10699451b44SJordan Rupprecht        exe = self.getBuildArtifact("a.out")
10799451b44SJordan Rupprecht
10899451b44SJordan Rupprecht        target = self.dbg.CreateTarget(exe)
10999451b44SJordan Rupprecht        self.assertTrue(target, VALID_TARGET)
11099451b44SJordan Rupprecht
1112238dcc3SJonas Devlieghere        breakpoint = target.BreakpointCreateByLocation("main.cpp", self.break_line)
11299451b44SJordan Rupprecht        self.assertTrue(breakpoint, VALID_BREAKPOINT)
11399451b44SJordan Rupprecht        # self.runCmd("breakpoint list")
11499451b44SJordan Rupprecht
11599451b44SJordan Rupprecht        # Launch the process, and do not stop at the entry point.
1162238dcc3SJonas Devlieghere        process = target.LaunchSimple(None, None, self.get_process_working_directory())
11799451b44SJordan Rupprecht
11899451b44SJordan Rupprecht        thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
11999451b44SJordan Rupprecht        self.assertTrue(
1202238dcc3SJonas Devlieghere            thread.IsValid(), "There should be a thread stopped due to breakpoint"
1212238dcc3SJonas Devlieghere        )
12299451b44SJordan Rupprecht
12399451b44SJordan Rupprecht        # Get the stop reason. GetStopDescription expects that we pass in the size of the description
12499451b44SJordan Rupprecht        # we expect plus an additional byte for the null terminator.
12599451b44SJordan Rupprecht
12699451b44SJordan Rupprecht        # Test with a buffer that is exactly as large as the expected stop reason.
1272238dcc3SJonas Devlieghere        self.assertEqual(
1282238dcc3SJonas Devlieghere            "breakpoint 1.1", thread.GetStopDescription(len("breakpoint 1.1") + 1)
1292238dcc3SJonas Devlieghere        )
13099451b44SJordan Rupprecht
13199451b44SJordan Rupprecht        # Test some smaller buffer sizes.
1322238dcc3SJonas Devlieghere        self.assertEqual("breakpoint", thread.GetStopDescription(len("breakpoint") + 1))
1332238dcc3SJonas Devlieghere        self.assertEqual("break", thread.GetStopDescription(len("break") + 1))
1342238dcc3SJonas Devlieghere        self.assertEqual("b", thread.GetStopDescription(len("b") + 1))
13599451b44SJordan Rupprecht
13699451b44SJordan Rupprecht        # Test that we can pass in a much larger size and still get the right output.
1372238dcc3SJonas Devlieghere        self.assertEqual(
1382238dcc3SJonas Devlieghere            "breakpoint 1.1", thread.GetStopDescription(len("breakpoint 1.1") + 100)
1392238dcc3SJonas Devlieghere        )
14099451b44SJordan Rupprecht
14199451b44SJordan Rupprecht    def step_out_of_malloc_into_function_b(self, exe_name):
14299451b44SJordan Rupprecht        """Test Python SBThread.StepOut() API to step out of a malloc call where the call site is at function b()."""
14399451b44SJordan Rupprecht        exe = self.getBuildArtifact(exe_name)
14499451b44SJordan Rupprecht
14599451b44SJordan Rupprecht        target = self.dbg.CreateTarget(exe)
14699451b44SJordan Rupprecht        self.assertTrue(target, VALID_TARGET)
14799451b44SJordan Rupprecht
1482238dcc3SJonas Devlieghere        breakpoint = target.BreakpointCreateByName("malloc")
14999451b44SJordan Rupprecht        self.assertTrue(breakpoint, VALID_BREAKPOINT)
15099451b44SJordan Rupprecht
15199451b44SJordan Rupprecht        # Launch the process, and do not stop at the entry point.
1522238dcc3SJonas Devlieghere        process = target.LaunchSimple(None, None, self.get_process_working_directory())
15399451b44SJordan Rupprecht
15499451b44SJordan Rupprecht        while True:
15599451b44SJordan Rupprecht            thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
15699451b44SJordan Rupprecht            self.assertTrue(
1572238dcc3SJonas Devlieghere                thread.IsValid(), "There should be a thread stopped due to breakpoint"
1582238dcc3SJonas Devlieghere            )
15999451b44SJordan Rupprecht            caller_symbol = get_caller_symbol(thread)
16099451b44SJordan Rupprecht            if not caller_symbol:
1612238dcc3SJonas Devlieghere                self.fail("Test failed: could not locate the caller symbol of malloc")
16299451b44SJordan Rupprecht
16399451b44SJordan Rupprecht            # Our top frame may be an inlined function in malloc() (e.g., on
16499451b44SJordan Rupprecht            # FreeBSD).  Apply a simple heuristic of stepping out until we find
16599451b44SJordan Rupprecht            # a non-malloc caller
16699451b44SJordan Rupprecht            while caller_symbol.startswith("malloc"):
16799451b44SJordan Rupprecht                thread.StepOut()
1682238dcc3SJonas Devlieghere                self.assertTrue(
1692238dcc3SJonas Devlieghere                    thread.IsValid(), "Thread valid after stepping to outer malloc"
1702238dcc3SJonas Devlieghere                )
17199451b44SJordan Rupprecht                caller_symbol = get_caller_symbol(thread)
17299451b44SJordan Rupprecht
17399451b44SJordan Rupprecht            if caller_symbol == "b(int)":
17499451b44SJordan Rupprecht                break
17599451b44SJordan Rupprecht            process.Continue()
17699451b44SJordan Rupprecht
17799451b44SJordan Rupprecht        # On Linux malloc calls itself in some case. Remove the breakpoint because we don't want
17899451b44SJordan Rupprecht        # to hit it during step-out.
17999451b44SJordan Rupprecht        target.BreakpointDelete(breakpoint.GetID())
18099451b44SJordan Rupprecht
18199451b44SJordan Rupprecht        thread.StepOut()
18299451b44SJordan Rupprecht        self.runCmd("thread backtrace")
1830ed758b2SDave Lee        self.assertEqual(
1842238dcc3SJonas Devlieghere            thread.GetFrameAtIndex(0).GetLineEntry().GetLine(),
1852238dcc3SJonas Devlieghere            self.step_out_of_malloc,
1862238dcc3SJonas Devlieghere            "step out of malloc into function b is successful",
1872238dcc3SJonas Devlieghere        )
18899451b44SJordan Rupprecht
18999451b44SJordan Rupprecht    def step_over_3_times(self, exe_name):
19099451b44SJordan Rupprecht        """Test Python SBThread.StepOver() API."""
19199451b44SJordan Rupprecht        exe = self.getBuildArtifact(exe_name)
19299451b44SJordan Rupprecht
19399451b44SJordan Rupprecht        target = self.dbg.CreateTarget(exe)
19499451b44SJordan Rupprecht        self.assertTrue(target, VALID_TARGET)
19599451b44SJordan Rupprecht
19699451b44SJordan Rupprecht        breakpoint = target.BreakpointCreateByLocation(
1972238dcc3SJonas Devlieghere            "main2.cpp", self.step_out_of_malloc
1982238dcc3SJonas Devlieghere        )
19999451b44SJordan Rupprecht        self.assertTrue(breakpoint, VALID_BREAKPOINT)
20099451b44SJordan Rupprecht        self.runCmd("breakpoint list")
20199451b44SJordan Rupprecht
20299451b44SJordan Rupprecht        # Launch the process, and do not stop at the entry point.
2032238dcc3SJonas Devlieghere        process = target.LaunchSimple(None, None, self.get_process_working_directory())
20499451b44SJordan Rupprecht
20599451b44SJordan Rupprecht        self.assertTrue(process, PROCESS_IS_VALID)
20699451b44SJordan Rupprecht
20799451b44SJordan Rupprecht        # Frame #0 should be on self.step_out_of_malloc.
20847c4c6a7SDave Lee        self.assertState(process.GetState(), lldb.eStateStopped)
20999451b44SJordan Rupprecht        thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
21099451b44SJordan Rupprecht        self.assertTrue(
21199451b44SJordan Rupprecht            thread.IsValid(),
2122238dcc3SJonas Devlieghere            "There should be a thread stopped due to breakpoint condition",
2132238dcc3SJonas Devlieghere        )
21499451b44SJordan Rupprecht        self.runCmd("thread backtrace")
21599451b44SJordan Rupprecht        frame0 = thread.GetFrameAtIndex(0)
21699451b44SJordan Rupprecht        lineEntry = frame0.GetLineEntry()
217619e2e09SDave Lee        self.assertEqual(lineEntry.GetLine(), self.step_out_of_malloc)
21899451b44SJordan Rupprecht
21999451b44SJordan Rupprecht        thread.StepOver()
22099451b44SJordan Rupprecht        thread.StepOver()
22199451b44SJordan Rupprecht        thread.StepOver()
22299451b44SJordan Rupprecht        self.runCmd("thread backtrace")
22399451b44SJordan Rupprecht
22499451b44SJordan Rupprecht        # Verify that we are stopped at the correct source line number in
22599451b44SJordan Rupprecht        # main2.cpp.
22699451b44SJordan Rupprecht        frame0 = thread.GetFrameAtIndex(0)
22799451b44SJordan Rupprecht        lineEntry = frame0.GetLineEntry()
2280f821339SJonas Devlieghere        self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonPlanComplete)
22999451b44SJordan Rupprecht        # Expected failure with clang as the compiler.
23099451b44SJordan Rupprecht        # rdar://problem/9223880
23199451b44SJordan Rupprecht        #
23299451b44SJordan Rupprecht        # Which has been fixed on the lldb by compensating for inaccurate line
23399451b44SJordan Rupprecht        # table information with r140416.
234619e2e09SDave Lee        self.assertEqual(lineEntry.GetLine(), self.after_3_step_overs)
23599451b44SJordan Rupprecht
23699451b44SJordan Rupprecht    def run_to_address(self, exe_name):
23799451b44SJordan Rupprecht        """Test Python SBThread.RunToAddress() API."""
23899451b44SJordan Rupprecht        exe = self.getBuildArtifact(exe_name)
23999451b44SJordan Rupprecht
24099451b44SJordan Rupprecht        target = self.dbg.CreateTarget(exe)
24199451b44SJordan Rupprecht        self.assertTrue(target, VALID_TARGET)
24299451b44SJordan Rupprecht
24399451b44SJordan Rupprecht        breakpoint = target.BreakpointCreateByLocation(
2442238dcc3SJonas Devlieghere            "main2.cpp", self.step_out_of_malloc
2452238dcc3SJonas Devlieghere        )
24699451b44SJordan Rupprecht        self.assertTrue(breakpoint, VALID_BREAKPOINT)
24799451b44SJordan Rupprecht        self.runCmd("breakpoint list")
24899451b44SJordan Rupprecht
24999451b44SJordan Rupprecht        # Launch the process, and do not stop at the entry point.
2502238dcc3SJonas Devlieghere        process = target.LaunchSimple(None, None, self.get_process_working_directory())
25199451b44SJordan Rupprecht
25299451b44SJordan Rupprecht        self.assertTrue(process, PROCESS_IS_VALID)
25399451b44SJordan Rupprecht
25499451b44SJordan Rupprecht        # Frame #0 should be on self.step_out_of_malloc.
25547c4c6a7SDave Lee        self.assertState(process.GetState(), lldb.eStateStopped)
25699451b44SJordan Rupprecht        thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
25799451b44SJordan Rupprecht        self.assertTrue(
25899451b44SJordan Rupprecht            thread.IsValid(),
2592238dcc3SJonas Devlieghere            "There should be a thread stopped due to breakpoint condition",
2602238dcc3SJonas Devlieghere        )
26199451b44SJordan Rupprecht        self.runCmd("thread backtrace")
26299451b44SJordan Rupprecht        frame0 = thread.GetFrameAtIndex(0)
26399451b44SJordan Rupprecht        lineEntry = frame0.GetLineEntry()
264619e2e09SDave Lee        self.assertEqual(lineEntry.GetLine(), self.step_out_of_malloc)
26599451b44SJordan Rupprecht
26699451b44SJordan Rupprecht        # Get the start/end addresses for this line entry.
26799451b44SJordan Rupprecht        start_addr = lineEntry.GetStartAddress().GetLoadAddress(target)
26899451b44SJordan Rupprecht        end_addr = lineEntry.GetEndAddress().GetLoadAddress(target)
26999451b44SJordan Rupprecht        if self.TraceOn():
27099451b44SJordan Rupprecht            print("start addr:", hex(start_addr))
27199451b44SJordan Rupprecht            print("end addr:", hex(end_addr))
27299451b44SJordan Rupprecht
27399451b44SJordan Rupprecht        # Disable the breakpoint.
27499451b44SJordan Rupprecht        self.assertTrue(target.DisableAllBreakpoints())
27599451b44SJordan Rupprecht        self.runCmd("breakpoint list")
27699451b44SJordan Rupprecht
27799451b44SJordan Rupprecht        thread.StepOver()
27899451b44SJordan Rupprecht        thread.StepOver()
27999451b44SJordan Rupprecht        thread.StepOver()
28099451b44SJordan Rupprecht        self.runCmd("thread backtrace")
28199451b44SJordan Rupprecht
28299451b44SJordan Rupprecht        # Now ask SBThread to run to the address 'start_addr' we got earlier, which
28399451b44SJordan Rupprecht        # corresponds to self.step_out_of_malloc line entry's start address.
28499451b44SJordan Rupprecht        thread.RunToAddress(start_addr)
28599451b44SJordan Rupprecht        self.runCmd("process status")
28699451b44SJordan Rupprecht        # self.runCmd("thread backtrace")
2873ff63672SDave Lee
2883ff63672SDave Lee    def validate_negative_indexing(self):
2893ff63672SDave Lee        exe = self.getBuildArtifact("a.out")
2903ff63672SDave Lee
2913ff63672SDave Lee        target = self.dbg.CreateTarget(exe)
2923ff63672SDave Lee        self.assertTrue(target, VALID_TARGET)
2933ff63672SDave Lee
2942238dcc3SJonas Devlieghere        breakpoint = target.BreakpointCreateByLocation("main.cpp", self.break_line)
2953ff63672SDave Lee        self.assertTrue(breakpoint, VALID_BREAKPOINT)
2963ff63672SDave Lee        self.runCmd("breakpoint list")
2973ff63672SDave Lee
2983ff63672SDave Lee        # Launch the process, and do not stop at the entry point.
2992238dcc3SJonas Devlieghere        process = target.LaunchSimple(None, None, self.get_process_working_directory())
3003ff63672SDave Lee
3013ff63672SDave Lee        thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
3023ff63672SDave Lee        self.assertTrue(
3032238dcc3SJonas Devlieghere            thread.IsValid(), "There should be a thread stopped due to breakpoint"
3042238dcc3SJonas Devlieghere        )
3053ff63672SDave Lee        self.runCmd("process status")
3063ff63672SDave Lee
3073ff63672SDave Lee        pos_range = range(thread.num_frames)
3083ff63672SDave Lee        neg_range = range(thread.num_frames, 0, -1)
3093ff63672SDave Lee        for pos, neg in zip(pos_range, neg_range):
3103ff63672SDave Lee            self.assertEqual(thread.frame[pos].idx, thread.frame[-neg].idx)
311845dee36Sjimingham
312845dee36Sjimingham    def step_instruction_in_called_function(self):
313845dee36Sjimingham        main_file_spec = lldb.SBFileSpec("main.cpp")
314845dee36Sjimingham        target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
315845dee36Sjimingham            self, "Set break point at this line", main_file_spec
316845dee36Sjimingham        )
317845dee36Sjimingham        options = lldb.SBExpressionOptions()
318845dee36Sjimingham        options.SetIgnoreBreakpoints(False)
319845dee36Sjimingham
320845dee36Sjimingham        call_me_bkpt = target.BreakpointCreateBySourceRegex(
321845dee36Sjimingham            "Set a breakpoint in call_me", main_file_spec
322845dee36Sjimingham        )
323845dee36Sjimingham        self.assertGreater(
324845dee36Sjimingham            call_me_bkpt.GetNumLocations(), 0, "Got at least one location in call_me"
325845dee36Sjimingham        )
326*3e06392cSDavid Spickett
327*3e06392cSDavid Spickett        # On Windows this may be the full name "void __cdecl call_me(bool)",
328*3e06392cSDavid Spickett        # elsewhere it's just "call_me(bool)".
329*3e06392cSDavid Spickett        expected_name = r".*call_me\(bool\)$"
330*3e06392cSDavid Spickett
331845dee36Sjimingham        # Now run the expression, this will fail because we stopped at a breakpoint:
332845dee36Sjimingham        self.runCmd("expr -i 0 -- call_me(true)", check=False)
333845dee36Sjimingham        # Now we should be stopped in call_me:
334*3e06392cSDavid Spickett        self.assertRegex(
335*3e06392cSDavid Spickett            thread.frames[0].name, expected_name, "Stopped in call_me(bool)"
336845dee36Sjimingham        )
337*3e06392cSDavid Spickett
338845dee36Sjimingham        # Now do a various API steps.  These should not cause the expression context to get unshipped:
339845dee36Sjimingham        thread.StepInstruction(False)
340*3e06392cSDavid Spickett        self.assertRegex(
341845dee36Sjimingham            thread.frames[0].name,
342*3e06392cSDavid Spickett            expected_name,
343845dee36Sjimingham            "Still in call_me(bool) after StepInstruction",
344845dee36Sjimingham        )
345845dee36Sjimingham        thread.StepInstruction(True)
346*3e06392cSDavid Spickett        self.assertRegex(
347845dee36Sjimingham            thread.frames[0].name,
348*3e06392cSDavid Spickett            expected_name,
349845dee36Sjimingham            "Still in call_me(bool) after NextInstruction",
350845dee36Sjimingham        )
351845dee36Sjimingham        thread.StepInto()
352*3e06392cSDavid Spickett        self.assertRegex(
353845dee36Sjimingham            thread.frames[0].name,
354*3e06392cSDavid Spickett            expected_name,
355845dee36Sjimingham            "Still in call_me(bool) after StepInto",
356845dee36Sjimingham        )
357845dee36Sjimingham        thread.StepOver(False)
358*3e06392cSDavid Spickett        self.assertRegex(
359845dee36Sjimingham            thread.frames[0].name,
360*3e06392cSDavid Spickett            expected_name,
361845dee36Sjimingham            "Still in call_me(bool) after StepOver",
362845dee36Sjimingham        )
363