aboutsummaryrefslogtreecommitdiff
path: root/test/functionalities/thread/thread_exit/TestThreadExit.py
blob: bb8e2842f6769da2516341904a07dfdc64498766 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
"""
Test number of threads.
"""

import os, time
import unittest2
import lldb
from lldbtest import *
import lldbutil

class ThreadExitTestCase(TestBase):

    mydir = os.path.join("functionalities", "thread", "thread_exit")

    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
    @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
    @dsym_test
    def test_with_dsym(self):
        """Test thread exit handling."""
        self.buildDsym(dictionary=self.getBuildFlags())
        self.thread_exit_test()

    @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
    @dwarf_test
    def test_with_dwarf(self):
        """Test thread exit handling."""
        self.buildDwarf(dictionary=self.getBuildFlags())
        self.thread_exit_test()

    def setUp(self):
        # Call super's setUp().
        TestBase.setUp(self)
        # Find the line numbers for our breakpoints.
        self.break_1 = line_number('main.cpp', '// Set first breakpoint here')
        self.break_2 = line_number('main.cpp', '// Set second breakpoint here')
        self.break_3 = line_number('main.cpp', '// Set third breakpoint here')
        self.break_4 = line_number('main.cpp', '// Set fourth breakpoint here')

    def thread_exit_test(self):
        """Test thread exit handling."""
        exe = os.path.join(os.getcwd(), "a.out")
        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)

        # This should create a breakpoint with 1 location.
        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_1, num_expected_locations=1)
        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_2, num_expected_locations=1)
        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_3, num_expected_locations=1)
        lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_4, num_expected_locations=1)

        # The breakpoint list should show 1 locations.
        self.expect("breakpoint list -f", "Breakpoint location shown correctly",
            substrs = ["1: file = 'main.cpp', line = %d, locations = 1" % self.break_1,
                       "2: file = 'main.cpp', line = %d, locations = 1" % self.break_2,
                       "3: file = 'main.cpp', line = %d, locations = 1" % self.break_3,
                       "4: file = 'main.cpp', line = %d, locations = 1" % self.break_4])

        # Run the program.
        self.runCmd("run", RUN_SUCCEEDED)

        # The stop reason of the thread should be breakpoint 1.
        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT + " 1",
            substrs = ['stopped',
                       '* thread #1',
                       'stop reason = breakpoint 1',
                       'thread #2'])

        # Get the target process
        target = self.dbg.GetSelectedTarget()
        process = target.GetProcess()

        # Get the number of threads
        num_threads = process.GetNumThreads()

        self.assertTrue(num_threads == 2, 'Number of expected threads and actual threads do not match at breakpoint 1.')

        # Run to the second breakpoint
        self.runCmd("continue")

        # The stop reason of the thread should be breakpoint 1.
        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT + " 2",
            substrs = ['stopped',
                       'thread #1',
                       '* thread #2',
                       'stop reason = breakpoint 2',
                       'thread #3'])

        # Update the number of threads
        num_threads = process.GetNumThreads()

        self.assertTrue(num_threads == 3, 'Number of expected threads and actual threads do not match at breakpoint 2.')

        # Run to the third breakpoint
        self.runCmd("continue")

        # The stop reason of the thread should be breakpoint 3.
        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT + " 3",
            substrs = ['stopped',
                       '* thread #1',
                       'stop reason = breakpoint 3',
                       'thread #3',
                       ])

        # Update the number of threads
        num_threads = process.GetNumThreads()

        self.assertTrue(num_threads == 2, 'Number of expected threads and actual threads do not match at breakpoint 3.')

        # Run to the fourth breakpoint
        self.runCmd("continue")

        # The stop reason of the thread should be breakpoint 4.
        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT + " 4",
            substrs = ['stopped',
                       '* thread #1',
                       'stop reason = breakpoint 4'])

        # Update the number of threads
        num_threads = process.GetNumThreads()

        self.assertTrue(num_threads == 1, 'Number of expected threads and actual threads do not match at breakpoint 4.')

        # Run to completion
        self.runCmd("continue")

        # At this point, the inferior process should have exited.
        self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED)

if __name__ == '__main__':
    import atexit
    lldb.SBDebugger.Initialize()
    atexit.register(lambda: lldb.SBDebugger.Terminate())
    unittest2.main()