• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"""
2Test thread states.
3"""
4
5import os, time
6import unittest2
7import lldb
8from lldbtest import *
9import lldbutil
10
11class ThreadStateTestCase(TestBase):
12
13    mydir = os.path.join("functionalities", "thread", "state")
14
15    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
16    @dsym_test
17    def test_state_after_breakpoint_with_dsym(self):
18        """Test thread state after breakpoint."""
19        self.buildDsym(dictionary=self.getBuildFlags(use_cpp11=False))
20        self.thread_state_after_breakpoint_test()
21
22    @dwarf_test
23    def test_state_after_breakpoint_with_dwarf(self):
24        """Test thread state after breakpoint."""
25        self.buildDwarf(dictionary=self.getBuildFlags(use_cpp11=False))
26        self.thread_state_after_breakpoint_test()
27
28    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
29    @dsym_test
30    def test_state_after_continue_with_dsym(self):
31        """Test thread state after continue."""
32        self.buildDsym(dictionary=self.getBuildFlags(use_cpp11=False))
33        self.thread_state_after_continue_test()
34
35    @dwarf_test
36    def test_state_after_continue_with_dwarf(self):
37        """Test thread state after continue."""
38        self.buildDwarf(dictionary=self.getBuildFlags(use_cpp11=False))
39        self.thread_state_after_continue_test()
40
41    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
42    @dsym_test
43    def test_state_after_expression_with_dsym(self):
44        """Test thread state after expression."""
45        self.buildDsym(dictionary=self.getBuildFlags(use_cpp11=False))
46        self.thread_state_after_continue_test()
47
48    @dwarf_test
49    def test_state_after_expression_with_dwarf(self):
50        """Test thread state after expression."""
51        self.buildDwarf(dictionary=self.getBuildFlags(use_cpp11=False))
52        self.thread_state_after_continue_test()
53
54    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
55    @dsym_test
56    @unittest2.expectedFailure("llvm.org/pr16172") # thread states not properly maintained
57    def test_process_interrupt_with_dsym(self):
58        """Test process interrupt."""
59        self.buildDsym(dictionary=self.getBuildFlags(use_cpp11=False))
60        self.process_interrupt_test()
61
62    @dwarf_test
63    @unittest2.expectedFailure("llvm.org/pr16712") # thread states not properly maintained
64    def test_process_interrupt_with_dwarf(self):
65        """Test process interrupt."""
66        self.buildDwarf(dictionary=self.getBuildFlags(use_cpp11=False))
67        self.process_interrupt_test()
68
69    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
70    @dsym_test
71    @unittest2.expectedFailure("llvm.org/pr15824") # thread states not properly maintained
72    def test_process_state_with_dsym(self):
73        """Test thread states (comprehensive)."""
74        self.buildDsym(dictionary=self.getBuildFlags(use_cpp11=False))
75        self.thread_states_test()
76
77    @dwarf_test
78    @unittest2.expectedFailure("llvm.org/pr15824") # thread states not properly maintained
79    def test_process_state_with_dwarf(self):
80        """Test thread states (comprehensive)."""
81        self.buildDwarf(dictionary=self.getBuildFlags(use_cpp11=False))
82        self.thread_states_test()
83
84    def setUp(self):
85        # Call super's setUp().
86        TestBase.setUp(self)
87        # Find the line numbers for our breakpoints.
88        self.break_1 = line_number('main.c', '// Set first breakpoint here')
89        self.break_2 = line_number('main.c', '// Set second breakpoint here')
90
91    def thread_state_after_breakpoint_test(self):
92        """Test thread state after breakpoint."""
93        exe = os.path.join(os.getcwd(), "a.out")
94        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
95
96        # This should create a breakpoint in the main thread.
97        lldbutil.run_break_set_by_file_and_line (self, "main.c", self.break_1, num_expected_locations=1)
98
99        # The breakpoint list should show 1 breakpoint with 1 location.
100        self.expect("breakpoint list -f", "Breakpoint location shown correctly",
101            substrs = ["1: file = 'main.c', line = %d, locations = 1" % self.break_1])
102
103        # Run the program.
104        self.runCmd("run", RUN_SUCCEEDED)
105
106        # The stop reason of the thread should be breakpoint.
107        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
108            substrs = ['stopped',
109                       '* thread #1',
110                       'stop reason = breakpoint'])
111
112        # Get the target process
113        target = self.dbg.GetSelectedTarget()
114        process = target.GetProcess()
115
116        # Get the number of threads
117        num_threads = process.GetNumThreads()
118
119        self.assertTrue(num_threads == 1, 'Number of expected threads and actual threads do not match.')
120
121        # Get the thread object
122        thread = process.GetThreadAtIndex(0)
123
124        # Make sure the thread is in the stopped state.
125        self.assertTrue(thread.IsStopped(), "Thread state isn't \'stopped\' during breakpoint 1.")
126        self.assertFalse(thread.IsSuspended(), "Thread state is \'suspended\' during breakpoint 1.")
127
128        # Kill the process
129        self.runCmd("process kill")
130
131    def thread_state_after_continue_test(self):
132        """Test thread state after continue."""
133        exe = os.path.join(os.getcwd(), "a.out")
134        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
135
136        # This should create a breakpoint in the main thread.
137        lldbutil.run_break_set_by_file_and_line (self, "main.c", self.break_1, num_expected_locations=1)
138        lldbutil.run_break_set_by_file_and_line (self, "main.c", self.break_2, num_expected_locations=1)
139
140        # The breakpoint list should show 1 breakpoints with 1 location.
141        self.expect("breakpoint list -f", "Breakpoint location shown correctly",
142            substrs = ["1: file = 'main.c', line = %d, locations = 1" % self.break_1])
143
144        # Run the program.
145        self.runCmd("run", RUN_SUCCEEDED)
146
147        # The stop reason of the thread should be breakpoint.
148        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
149            substrs = ['stopped',
150                       '* thread #1',
151                       'stop reason = breakpoint'])
152
153        # Get the target process
154        target = self.dbg.GetSelectedTarget()
155        process = target.GetProcess()
156
157        # Get the number of threads
158        num_threads = process.GetNumThreads()
159
160        self.assertTrue(num_threads == 1, 'Number of expected threads and actual threads do not match.')
161
162        # Get the thread object
163        thread = process.GetThreadAtIndex(0)
164
165        # Continue, the inferior will go into an infinite loop waiting for 'g_test' to change.
166        self.dbg.SetAsync(True)
167        self.runCmd("continue")
168        time.sleep(1)
169
170        # Check the thread state. It should be running.
171        self.assertFalse(thread.IsStopped(), "Thread state is \'stopped\' when it should be running.")
172        self.assertFalse(thread.IsSuspended(), "Thread state is \'suspended\' when it should be running.")
173
174        # Go back to synchronous interactions
175        self.dbg.SetAsync(False)
176
177        # Kill the process
178        self.runCmd("process kill")
179
180    def thread_state_after_expression_test(self):
181        """Test thread state after expression."""
182        exe = os.path.join(os.getcwd(), "a.out")
183        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
184
185        # This should create a breakpoint in the main thread.
186        lldbutil.run_break_set_by_file_and_line (self, "main.c", self.break_1, num_expected_locations=1)
187        lldbutil.run_break_set_by_file_and_line (self, "main.c", self.break_2, num_expected_locations=1)
188
189        # The breakpoint list should show 1 breakpoints with 1 location.
190        self.expect("breakpoint list -f", "Breakpoint location shown correctly",
191            substrs = ["1: file = 'main.c', line = %d, locations = 1" % self.break_1])
192
193        # Run the program.
194        self.runCmd("run", RUN_SUCCEEDED)
195
196        # The stop reason of the thread should be breakpoint.
197        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
198            substrs = ['stopped',
199                       '* thread #1',
200                       'stop reason = breakpoint'])
201
202        # Get the target process
203        target = self.dbg.GetSelectedTarget()
204        process = target.GetProcess()
205
206        # Get the number of threads
207        num_threads = process.GetNumThreads()
208
209        self.assertTrue(num_threads == 1, 'Number of expected threads and actual threads do not match.')
210
211        # Get the thread object
212        thread = process.GetThreadAtIndex(0)
213
214        # Get the inferior out of its loop
215        self.runCmd("expression g_test = 1")
216
217        # Check the thread state
218        self.assertTrue(thread.IsStopped(), "Thread state isn't \'stopped\' after expression evaluation.")
219        self.assertFalse(thread.IsSuspended(), "Thread state is \'suspended\' after expression evaluation.")
220
221        # Let the process run to completion
222        self.runCmd("process continue")
223
224
225    def process_interrupt_test(self):
226        """Test process interrupt and continue."""
227        exe = os.path.join(os.getcwd(), "a.out")
228        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
229
230        # This should create a breakpoint in the main thread.
231        lldbutil.run_break_set_by_file_and_line (self, "main.c", self.break_1, num_expected_locations=1)
232
233        # The breakpoint list should show 1 breakpoints with 1 location.
234        self.expect("breakpoint list -f", "Breakpoint location shown correctly",
235            substrs = ["1: file = 'main.c', line = %d, locations = 1" % self.break_1])
236
237        # Run the program.
238        self.runCmd("run", RUN_SUCCEEDED)
239
240        # The stop reason of the thread should be breakpoint.
241        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
242            substrs = ['stopped',
243                       '* thread #1',
244                       'stop reason = breakpoint'])
245
246        # Get the target process
247        target = self.dbg.GetSelectedTarget()
248        process = target.GetProcess()
249
250        # Get the number of threads
251        num_threads = process.GetNumThreads()
252
253        self.assertTrue(num_threads == 1, 'Number of expected threads and actual threads do not match.')
254
255        # Continue, the inferior will go into an infinite loop waiting for 'g_test' to change.
256        self.dbg.SetAsync(True)
257        self.runCmd("continue")
258        time.sleep(1)
259
260        # Go back to synchronous interactions
261        self.dbg.SetAsync(False)
262
263        # Stop the process
264        self.runCmd("process interrupt")
265
266        # The stop reason of the thread should be signal.
267        self.expect("process status", STOPPED_DUE_TO_SIGNAL,
268            substrs = ['stopped',
269                       '* thread #1',
270                       'stop reason = signal'])
271
272        # Get the inferior out of its loop
273        self.runCmd("expression g_test = 1")
274
275        # Run to completion
276        self.runCmd("continue")
277
278    def thread_states_test(self):
279        """Test thread states (comprehensive)."""
280        exe = os.path.join(os.getcwd(), "a.out")
281        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
282
283        # This should create a breakpoint in the main thread.
284        lldbutil.run_break_set_by_file_and_line (self, "main.c", self.break_1, num_expected_locations=1)
285        lldbutil.run_break_set_by_file_and_line (self, "main.c", self.break_2, num_expected_locations=1)
286
287        # The breakpoint list should show 2 breakpoints with 1 location each.
288        self.expect("breakpoint list -f", "Breakpoint location shown correctly",
289            substrs = ["1: file = 'main.c', line = %d, locations = 1" % self.break_1,
290                       "2: file = 'main.c', line = %d, locations = 1" % self.break_2])
291
292        # Run the program.
293        self.runCmd("run", RUN_SUCCEEDED)
294
295        # The stop reason of the thread should be breakpoint.
296        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
297            substrs = ['stopped',
298                       '* thread #1',
299                       'stop reason = breakpoint'])
300
301        # Get the target process
302        target = self.dbg.GetSelectedTarget()
303        process = target.GetProcess()
304
305        # Get the number of threads
306        num_threads = process.GetNumThreads()
307
308        self.assertTrue(num_threads == 1, 'Number of expected threads and actual threads do not match.')
309
310        # Get the thread object
311        thread = process.GetThreadAtIndex(0)
312
313        # Make sure the thread is in the stopped state.
314        self.assertTrue(thread.IsStopped(), "Thread state isn't \'stopped\' during breakpoint 1.")
315        self.assertFalse(thread.IsSuspended(), "Thread state is \'suspended\' during breakpoint 1.")
316
317        # Continue, the inferior will go into an infinite loop waiting for 'g_test' to change.
318        self.dbg.SetAsync(True)
319        self.runCmd("continue")
320        time.sleep(1)
321
322        # Check the thread state. It should be running.
323        self.assertFalse(thread.IsStopped(), "Thread state is \'stopped\' when it should be running.")
324        self.assertFalse(thread.IsSuspended(), "Thread state is \'suspended\' when it should be running.")
325
326        # Go back to synchronous interactions
327        self.dbg.SetAsync(False)
328
329        # Stop the process
330        self.runCmd("process interrupt")
331
332        # The stop reason of the thread should be signal.
333        self.expect("process status", STOPPED_DUE_TO_SIGNAL,
334            substrs = ['stopped',
335                       '* thread #1',
336                       'stop reason = signal'])
337
338        # Check the thread state
339        self.assertTrue(thread.IsStopped(), "Thread state isn't \'stopped\' after process stop.")
340        self.assertFalse(thread.IsSuspended(), "Thread state is \'suspended\' after process stop.")
341
342        # Get the inferior out of its loop
343        self.runCmd("expression g_test = 1")
344
345        # Check the thread state
346        self.assertTrue(thread.IsStopped(), "Thread state isn't \'stopped\' after expression evaluation.")
347        self.assertFalse(thread.IsSuspended(), "Thread state is \'suspended\' after expression evaluation.")
348
349        # The stop reason of the thread should be signal.
350        self.expect("process status", STOPPED_DUE_TO_SIGNAL,
351            substrs = ['stopped',
352                       '* thread #1',
353                       'stop reason = signal'])
354
355        # Run to breakpoint 2
356        self.runCmd("continue")
357
358        # The stop reason of the thread should be breakpoint.
359        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
360            substrs = ['stopped',
361                       '* thread #1',
362                       'stop reason = breakpoint'])
363
364        # Make sure both threads are stopped
365        self.assertTrue(thread.IsStopped(), "Thread state isn't \'stopped\' during breakpoint 2.")
366        self.assertFalse(thread.IsSuspended(), "Thread state is \'suspended\' during breakpoint 2.")
367
368        # Run to completion
369        self.runCmd("continue")
370
371        # At this point, the inferior process should have exited.
372        self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED)
373
374if __name__ == '__main__':
375    import atexit
376    lldb.SBDebugger.Initialize()
377    atexit.register(lambda: lldb.SBDebugger.Terminate())
378    unittest2.main()
379