1"""
2Test number of threads.
3"""
4
5
6
7import lldb
8from lldbsuite.test.decorators import *
9from lldbsuite.test.lldbtest import *
10from lldbsuite.test import lldbutil
11
12
13class CreateDuringStepTestCase(TestBase):
14
15    @expectedFailureAll(
16        oslist=["linux"],
17        bugnumber="llvm.org/pr15824 thread states not properly maintained")
18    @expectedFailureAll(
19        oslist=lldbplatformutil.getDarwinOSTriples(),
20        bugnumber="llvm.org/pr15824 thread states not properly maintained, <rdar://problem/28557237>")
21    @expectedFailureAll(
22        oslist=["freebsd"],
23        bugnumber="llvm.org/pr18190 thread states not properly maintained")
24    @expectedFailureAll(
25        oslist=["windows"],
26        bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly")
27    @expectedFailureNetBSD
28    def test_step_inst(self):
29        """Test thread creation during step-inst handling."""
30        self.build()
31        self.create_during_step_base(
32            "thread step-inst -m all-threads",
33            'stop reason = instruction step')
34
35    @expectedFailureAll(
36        oslist=["linux"],
37        bugnumber="llvm.org/pr15824 thread states not properly maintained")
38    @expectedFailureAll(
39        oslist=lldbplatformutil.getDarwinOSTriples(),
40        bugnumber="llvm.org/pr15824 thread states not properly maintained, <rdar://problem/28557237>")
41    @expectedFailureAll(
42        oslist=["freebsd"],
43        bugnumber="llvm.org/pr18190 thread states not properly maintained")
44    @expectedFailureAll(
45        oslist=["windows"],
46        bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly")
47    @expectedFailureNetBSD
48    def test_step_over(self):
49        """Test thread creation during step-over handling."""
50        self.build()
51        self.create_during_step_base(
52            "thread step-over -m all-threads",
53            'stop reason = step over')
54
55    @expectedFailureAll(
56        oslist=["linux"],
57        bugnumber="llvm.org/pr15824 thread states not properly maintained")
58    @expectedFailureAll(
59        oslist=lldbplatformutil.getDarwinOSTriples(),
60        bugnumber="<rdar://problem/28574077>")
61    @expectedFailureAll(
62        oslist=["freebsd"],
63        bugnumber="llvm.org/pr18190 thread states not properly maintained")
64    @expectedFailureAll(
65        oslist=["windows"],
66        bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly")
67    @expectedFailureNetBSD
68    def test_step_in(self):
69        """Test thread creation during step-in handling."""
70        self.build()
71        self.create_during_step_base(
72            "thread step-in -m all-threads",
73            'stop reason = step in')
74
75    def setUp(self):
76        # Call super's setUp().
77        TestBase.setUp(self)
78        # Find the line numbers to break and continue.
79        self.breakpoint = line_number('main.cpp', '// Set breakpoint here')
80        self.continuepoint = line_number('main.cpp', '// Continue from here')
81
82    def create_during_step_base(self, step_cmd, step_stop_reason):
83        """Test thread creation while using step-in."""
84        exe = self.getBuildArtifact("a.out")
85        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
86
87        # Get the target process
88        target = self.dbg.GetSelectedTarget()
89
90        # This should create a breakpoint in the stepping thread.
91        self.bkpt = target.BreakpointCreateByLocation("main.cpp", self.breakpoint)
92
93        # Run the program.
94        self.runCmd("run", RUN_SUCCEEDED)
95
96        process = target.GetProcess()
97
98        # The stop reason of the thread should be breakpoint.
99        stepping_thread = lldbutil.get_one_thread_stopped_at_breakpoint(process, self.bkpt)
100        self.assertTrue(stepping_thread.IsValid(), "We stopped at the right breakpoint")
101
102        # Get the number of threads
103        num_threads = process.GetNumThreads()
104
105        # Make sure we see only two threads
106        self.assertEqual(
107            num_threads, 2,
108            'Number of expected threads and actual threads do not match.')
109
110        # Get the thread objects
111        thread1 = process.GetThreadAtIndex(0)
112        thread2 = process.GetThreadAtIndex(1)
113
114        current_line = self.breakpoint
115        # Keep stepping until we've reached our designated continue point
116        while current_line != self.continuepoint:
117            if stepping_thread != process.GetSelectedThread():
118                process.SetSelectedThread(stepping_thread)
119
120            self.runCmd(step_cmd)
121
122            frame = stepping_thread.GetFrameAtIndex(0)
123            current_line = frame.GetLineEntry().GetLine()
124
125            # Make sure we're still where we thought we were
126            self.assertTrue(
127                current_line >= self.breakpoint,
128                "Stepped to unexpected line, " +
129                str(current_line))
130            self.assertTrue(
131                current_line <= self.continuepoint,
132                "Stepped to unexpected line, " +
133                str(current_line))
134
135        # Update the number of threads
136        num_threads = process.GetNumThreads()
137
138        # Check to see that we increased the number of threads as expected
139        self.assertEqual(
140            num_threads, 3,
141            'Number of expected threads and actual threads do not match after thread exit.')
142
143        stop_reason = stepping_thread.GetStopReason()
144        self.assertEqual(stop_reason, lldb.eStopReasonPlanComplete, "Stopped for plan completion")
145
146        # Run to completion
147        self.runCmd("process continue")
148
149        # At this point, the inferior process should have exited.
150        self.assertEqual(
151            process.GetState(), lldb.eStateExited,
152            PROCESS_EXITED)
153