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