1"""
2This tests that we do not lose control of the inferior, while doing an instruction-level step
3over a thread creation instruction.
4"""
5
6
7import lldb
8from lldbsuite.test.decorators import *
9from lldbsuite.test.lldbtest import *
10from lldbsuite.test import lldbutil
11
12
13class CreateDuringInstructionStepTestCase(TestBase):
14
15    mydir = TestBase.compute_mydir(__file__)
16    NO_DEBUG_INFO_TESTCASE = True
17
18    @skipUnlessPlatform(['linux'])
19    @expectedFailureAndroid('llvm.org/pr24737', archs=['arm'])
20    @skipIf(oslist=["linux"], archs=["arm", "aarch64"], bugnumber="llvm.org/pr24737")
21    def test_step_inst(self):
22        self.build(dictionary=self.getBuildFlags())
23        exe = self.getBuildArtifact("a.out")
24        target = self.dbg.CreateTarget(exe)
25        self.assertTrue(target and target.IsValid(), "Target is valid")
26
27        # This should create a breakpoint in the stepping thread.
28        breakpoint = target.BreakpointCreateByName("main")
29        self.assertTrue(
30            breakpoint and breakpoint.IsValid(),
31            "Breakpoint is valid")
32
33        # Run the program.
34        process = target.LaunchSimple(
35            None, None, self.get_process_working_directory())
36        self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID)
37
38        # The stop reason of the thread should be breakpoint.
39        self.assertEqual(
40            process.GetState(),
41            lldb.eStateStopped,
42            PROCESS_STOPPED)
43
44        threads = lldbutil.get_threads_stopped_at_breakpoint(
45            process, breakpoint)
46        self.assertEqual(len(threads), 1, STOPPED_DUE_TO_BREAKPOINT)
47
48        thread = threads[0]
49        self.assertTrue(thread and thread.IsValid(), "Thread is valid")
50
51        # Make sure we see only one threads
52        self.assertEqual(
53            process.GetNumThreads(),
54            1,
55            'Number of expected threads and actual threads do not match.')
56
57        # Keep stepping until we see the thread creation
58        while process.GetNumThreads() < 2:
59            thread.StepInstruction(False)
60            self.assertEqual(
61                process.GetState(),
62                lldb.eStateStopped,
63                PROCESS_STOPPED)
64            self.assertEqual(
65                thread.GetStopReason(),
66                lldb.eStopReasonPlanComplete,
67                "Step operation succeeded")
68            if self.TraceOn():
69                self.runCmd("disassemble --pc")
70
71        if self.TraceOn():
72            self.runCmd("thread list")
73
74        # We have successfully caught thread creation. Now just run to
75        # completion
76        process.Continue()
77
78        # At this point, the inferior process should have exited.
79        self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED)
80