1"""
2Test thread states.
3"""
4
5
6
7import unittest2
8import lldb
9from lldbsuite.test.decorators import *
10from lldbsuite.test.lldbtest import *
11from lldbsuite.test import lldbutil
12
13
14class ThreadStateTestCase(TestBase):
15
16    mydir = TestBase.compute_mydir(__file__)
17
18    @expectedFailureAll(
19        oslist=["linux"],
20        bugnumber="llvm.org/pr15824 thread states not properly maintained")
21    @skipIfDarwin # llvm.org/pr15824 thread states not properly maintained and <rdar://problem/28557237>
22    @expectedFailureAll(
23        oslist=["freebsd"],
24        bugnumber="llvm.org/pr18190 thread states not properly maintained")
25    @expectedFailureNetBSD
26    def test_state_after_breakpoint(self):
27        """Test thread state after breakpoint."""
28        self.build(dictionary=self.getBuildFlags(use_cpp11=False))
29        self.thread_state_after_breakpoint_test()
30
31    @skipIfDarwin  # 'llvm.org/pr23669', cause Python crash randomly
32    @expectedFailureAll(
33        oslist=lldbplatformutil.getDarwinOSTriples(),
34        bugnumber="llvm.org/pr23669")
35    @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr15824")
36    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24660")
37    def test_state_after_continue(self):
38        """Test thread state after continue."""
39        self.build(dictionary=self.getBuildFlags(use_cpp11=False))
40        self.thread_state_after_continue_test()
41
42    @skipIfDarwin  # 'llvm.org/pr23669', cause Python crash randomly
43    @expectedFailureDarwin('llvm.org/pr23669')
44    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24660")
45    @expectedFailureNetBSD
46    # thread states not properly maintained
47    @expectedFailure("llvm.org/pr16712")
48    def test_state_after_expression(self):
49        """Test thread state after expression."""
50        self.build(dictionary=self.getBuildFlags(use_cpp11=False))
51        self.thread_state_after_expression_test()
52
53    # thread states not properly maintained
54    @expectedFailure("llvm.org/pr15824 and <rdar://problem/28557237>")
55    @expectedFailureAll(
56        oslist=["windows"],
57        bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly")
58    @skipIfDarwin # llvm.org/pr15824 thread states not properly maintained and <rdar://problem/28557237>
59    @expectedFailureNetBSD
60    def test_process_state(self):
61        """Test thread states (comprehensive)."""
62        self.build(dictionary=self.getBuildFlags(use_cpp11=False))
63        self.thread_states_test()
64
65    def setUp(self):
66        # Call super's setUp().
67        TestBase.setUp(self)
68        # Find the line numbers for our breakpoints.
69        self.break_1 = line_number('main.cpp', '// Set first breakpoint here')
70        self.break_2 = line_number('main.cpp', '// Set second breakpoint here')
71
72    def thread_state_after_breakpoint_test(self):
73        """Test thread state after breakpoint."""
74        exe = self.getBuildArtifact("a.out")
75        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
76
77        # This should create a breakpoint in the main thread.
78        bp = lldbutil.run_break_set_by_file_and_line(
79            self, "main.cpp", self.break_1, num_expected_locations=1)
80
81        # Run the program.
82        self.runCmd("run", RUN_SUCCEEDED)
83
84        # Get the target process
85        target = self.dbg.GetSelectedTarget()
86        process = target.GetProcess()
87
88        thread = lldbutil.get_stopped_thread(
89            process, lldb.eStopReasonBreakpoint)
90        self.assertIsNotNone(thread)
91
92        # Make sure the thread is in the stopped state.
93        self.assertTrue(
94            thread.IsStopped(),
95            "Thread state isn't \'stopped\' during breakpoint 1.")
96        self.assertFalse(thread.IsSuspended(),
97                         "Thread state is \'suspended\' during breakpoint 1.")
98
99        # Kill the process
100        self.runCmd("process kill")
101
102    def wait_for_running_event(self, process):
103        listener = self.dbg.GetListener()
104        if lldb.remote_platform:
105            lldbutil.expect_state_changes(
106                self, listener, process, [
107                    lldb.eStateConnected])
108        lldbutil.expect_state_changes(
109            self, listener, process, [
110                lldb.eStateRunning])
111
112    def thread_state_after_continue_test(self):
113        """Test thread state after continue."""
114        exe = self.getBuildArtifact("a.out")
115        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
116
117        # This should create a breakpoint in the main thread.
118        lldbutil.run_break_set_by_file_and_line(
119            self, "main.cpp", self.break_1, num_expected_locations=1)
120        lldbutil.run_break_set_by_file_and_line(
121            self, "main.cpp", self.break_2, num_expected_locations=1)
122
123        # Run the program.
124        self.runCmd("run", RUN_SUCCEEDED)
125
126        # Get the target process
127        target = self.dbg.GetSelectedTarget()
128        process = target.GetProcess()
129
130        thread = lldbutil.get_stopped_thread(
131            process, lldb.eStopReasonBreakpoint)
132        self.assertIsNotNone(thread)
133
134        # Continue, the inferior will go into an infinite loop waiting for
135        # 'g_test' to change.
136        self.dbg.SetAsync(True)
137        self.runCmd("continue")
138        self.wait_for_running_event(process)
139
140        # Check the thread state. It should be running.
141        self.assertFalse(
142            thread.IsStopped(),
143            "Thread state is \'stopped\' when it should be running.")
144        self.assertFalse(
145            thread.IsSuspended(),
146            "Thread state is \'suspended\' when it should be running.")
147
148        # Go back to synchronous interactions
149        self.dbg.SetAsync(False)
150
151        # Kill the process
152        self.runCmd("process kill")
153
154    def thread_state_after_expression_test(self):
155        """Test thread state after expression."""
156        exe = self.getBuildArtifact("a.out")
157        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
158
159        # This should create a breakpoint in the main thread.
160        lldbutil.run_break_set_by_file_and_line(
161            self, "main.cpp", self.break_1, num_expected_locations=1)
162        lldbutil.run_break_set_by_file_and_line(
163            self, "main.cpp", self.break_2, num_expected_locations=1)
164
165        # Run the program.
166        self.runCmd("run", RUN_SUCCEEDED)
167
168        # Get the target process
169        target = self.dbg.GetSelectedTarget()
170        process = target.GetProcess()
171
172        thread = lldbutil.get_stopped_thread(
173            process, lldb.eStopReasonBreakpoint)
174        self.assertIsNotNone(thread)
175
176        # Get the inferior out of its loop
177        self.runCmd("expression g_test = 1")
178
179        # Check the thread state
180        self.assertTrue(
181            thread.IsStopped(),
182            "Thread state isn't \'stopped\' after expression evaluation.")
183        self.assertFalse(
184            thread.IsSuspended(),
185            "Thread state is \'suspended\' after expression evaluation.")
186
187        # Let the process run to completion
188        self.runCmd("process continue")
189
190    @expectedFailureAll(
191        oslist=["windows"],
192        bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly")
193    @skipIfDarwin # llvm.org/pr15824 thread states not properly maintained and <rdar://problem/28557237>
194    @no_debug_info_test
195    def test_process_interrupt(self):
196        """Test process interrupt and continue."""
197        self.build(dictionary=self.getBuildFlags(use_cpp11=False))
198        exe = self.getBuildArtifact("a.out")
199        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
200
201        # This should create a breakpoint in the main thread.
202        bpno = lldbutil.run_break_set_by_file_and_line(
203            self, "main.cpp", self.break_1, num_expected_locations=1)
204
205        # Run the program.
206        self.runCmd("run", RUN_SUCCEEDED)
207
208        # Get the target process
209        target = self.dbg.GetSelectedTarget()
210        process = target.GetProcess()
211
212        thread = lldbutil.get_stopped_thread(
213            process, lldb.eStopReasonBreakpoint)
214        self.assertIsNotNone(thread)
215
216        # Remove the breakpoint to avoid the single-step-over-bkpt dance in the
217        # "continue" below
218        self.assertTrue(target.BreakpointDelete(bpno))
219
220        # Continue, the inferior will go into an infinite loop waiting for
221        # 'g_test' to change.
222        self.dbg.SetAsync(True)
223        self.runCmd("continue")
224        self.wait_for_running_event(process)
225
226        # Go back to synchronous interactions
227        self.dbg.SetAsync(False)
228
229        # Stop the process
230        self.runCmd("process interrupt")
231
232        self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal)
233
234        # Get the inferior out of its loop
235        self.runCmd("expression g_test = 1")
236
237        # Run to completion
238        self.runCmd("continue")
239
240    def thread_states_test(self):
241        """Test thread states (comprehensive)."""
242        exe = self.getBuildArtifact("a.out")
243        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
244
245        # This should create a breakpoint in the main thread.
246        lldbutil.run_break_set_by_file_and_line(
247            self, "main.cpp", self.break_1, num_expected_locations=1)
248        lldbutil.run_break_set_by_file_and_line(
249            self, "main.cpp", self.break_2, num_expected_locations=1)
250
251        # Run the program.
252        self.runCmd("run", RUN_SUCCEEDED)
253
254        # Get the target process
255        target = self.dbg.GetSelectedTarget()
256        process = target.GetProcess()
257        thread = lldbutil.get_stopped_thread(
258            process, lldb.eStopReasonBreakpoint)
259        self.assertIsNotNone(thread)
260
261        # Make sure the thread is in the stopped state.
262        self.assertTrue(
263            thread.IsStopped(),
264            "Thread state isn't \'stopped\' during breakpoint 1.")
265        self.assertFalse(thread.IsSuspended(),
266                         "Thread state is \'suspended\' during breakpoint 1.")
267
268        # Continue, the inferior will go into an infinite loop waiting for
269        # 'g_test' to change.
270        self.dbg.SetAsync(True)
271        self.runCmd("continue")
272        self.wait_for_running_event(process)
273
274        # Check the thread state. It should be running.
275        self.assertFalse(
276            thread.IsStopped(),
277            "Thread state is \'stopped\' when it should be running.")
278        self.assertFalse(
279            thread.IsSuspended(),
280            "Thread state is \'suspended\' when it should be running.")
281
282        # Go back to synchronous interactions
283        self.dbg.SetAsync(False)
284
285        # Stop the process
286        self.runCmd("process interrupt")
287
288        self.assertEqual(thread.GetState(), lldb.eStopReasonSignal)
289
290        # Check the thread state
291        self.assertTrue(
292            thread.IsStopped(),
293            "Thread state isn't \'stopped\' after process stop.")
294        self.assertFalse(thread.IsSuspended(),
295                         "Thread state is \'suspended\' after process stop.")
296
297        # Get the inferior out of its loop
298        self.runCmd("expression g_test = 1")
299
300        # Check the thread state
301        self.assertTrue(
302            thread.IsStopped(),
303            "Thread state isn't \'stopped\' after expression evaluation.")
304        self.assertFalse(
305            thread.IsSuspended(),
306            "Thread state is \'suspended\' after expression evaluation.")
307
308        self.assertEqual(thread.GetState(), lldb.eStopReasonSignal)
309
310        # Run to breakpoint 2
311        self.runCmd("continue")
312
313        self.assertEqual(thread.GetState(), lldb.eStopReasonBreakpoint)
314
315        # Make sure both threads are stopped
316        self.assertTrue(
317            thread.IsStopped(),
318            "Thread state isn't \'stopped\' during breakpoint 2.")
319        self.assertFalse(thread.IsSuspended(),
320                         "Thread state is \'suspended\' during breakpoint 2.")
321
322        # Run to completion
323        self.runCmd("continue")
324
325        # At this point, the inferior process should have exited.
326        self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED)
327