xref: /llvm-project/lldb/test/API/functionalities/thread/thread_exit/TestThreadExit.py (revision 2238dcc39358353cac21df75c3c3286ab20b8f53)
1"""
2Test number of threads.
3"""
4
5
6import lldb
7from lldbsuite.test.decorators import *
8from lldbsuite.test.lldbtest import *
9import lldbsuite.test.lldbutil as lldbutil
10
11
12class ThreadExitTestCase(TestBase):
13    def setUp(self):
14        # Call super's setUp().
15        TestBase.setUp(self)
16        # Find the line numbers for our breakpoints.
17        self.break_1 = line_number("main.cpp", "// Set first breakpoint here")
18        self.break_2 = line_number("main.cpp", "// Set second breakpoint here")
19        self.break_3 = line_number("main.cpp", "// Set third breakpoint here")
20        self.break_4 = line_number("main.cpp", "// Set fourth breakpoint here")
21
22    @skipIfWindows  # This is flakey on Windows: llvm.org/pr38373
23    def test(self):
24        """Test thread exit handling."""
25        self.build()
26        exe = self.getBuildArtifact("a.out")
27        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
28
29        # This should create a breakpoint with 1 location.
30        bp1_id = lldbutil.run_break_set_by_file_and_line(
31            self, "main.cpp", self.break_1, num_expected_locations=1
32        )
33        bp2_id = lldbutil.run_break_set_by_file_and_line(
34            self, "main.cpp", self.break_2, num_expected_locations=1
35        )
36        bp3_id = lldbutil.run_break_set_by_file_and_line(
37            self, "main.cpp", self.break_3, num_expected_locations=1
38        )
39        bp4_id = lldbutil.run_break_set_by_file_and_line(
40            self, "main.cpp", self.break_4, num_expected_locations=1
41        )
42
43        # The breakpoint list should show 1 locations.
44        self.expect(
45            "breakpoint list -f",
46            "Breakpoint location shown correctly",
47            substrs=[
48                "1: file = 'main.cpp', line = %d, exact_match = 0, locations = 1"
49                % self.break_1,
50                "2: file = 'main.cpp', line = %d, exact_match = 0, locations = 1"
51                % self.break_2,
52                "3: file = 'main.cpp', line = %d, exact_match = 0, locations = 1"
53                % self.break_3,
54                "4: file = 'main.cpp', line = %d, exact_match = 0, locations = 1"
55                % self.break_4,
56            ],
57        )
58
59        # Run the program.
60        self.runCmd("run", RUN_SUCCEEDED)
61        # Get the target process
62        target = self.dbg.GetSelectedTarget()
63        process = target.GetProcess()
64
65        stopped_thread = lldbutil.get_one_thread_stopped_at_breakpoint_id(
66            process, bp1_id
67        )
68        self.assertIsNotNone(stopped_thread, "Process is not stopped at breakpoint 1")
69
70        # Get the number of threads
71        num_threads = process.GetNumThreads()
72        self.assertGreaterEqual(
73            num_threads,
74            2,
75            "Number of expected threads and actual threads do not match at breakpoint 1.",
76        )
77
78        # Run to the second breakpoint
79        self.runCmd("continue")
80        stopped_thread = lldbutil.get_one_thread_stopped_at_breakpoint_id(
81            process, bp2_id
82        )
83        self.assertIsNotNone(stopped_thread, "Process is not stopped at breakpoint 2")
84
85        # Update the number of threads
86        new_num_threads = process.GetNumThreads()
87        self.assertEqual(
88            new_num_threads,
89            num_threads + 1,
90            "Number of expected threads did not increase by 1 at bp 2.",
91        )
92
93        # Run to the third breakpoint
94        self.runCmd("continue")
95        stopped_thread = lldbutil.get_one_thread_stopped_at_breakpoint_id(
96            process, bp3_id
97        )
98        self.assertIsNotNone(stopped_thread, "Process is not stopped at breakpoint 3")
99
100        # Update the number of threads
101        new_num_threads = process.GetNumThreads()
102        self.assertEqual(
103            new_num_threads,
104            num_threads,
105            "Number of expected threads is not equal to original number of threads at bp 3.",
106        )
107
108        # Run to the fourth breakpoint
109        self.runCmd("continue")
110        stopped_thread = lldbutil.get_one_thread_stopped_at_breakpoint_id(
111            process, bp4_id
112        )
113        self.assertIsNotNone(stopped_thread, "Process is not stopped at breakpoint 4")
114
115        # Update the number of threads
116        new_num_threads = process.GetNumThreads()
117        self.assertEqual(
118            new_num_threads,
119            num_threads - 1,
120            "Number of expected threads did not decrease by 1 at bp 4.",
121        )
122
123        # Run to completion
124        self.runCmd("continue")
125
126        # At this point, the inferior process should have exited.
127        self.assertState(process.GetState(), lldb.eStateExited, PROCESS_EXITED)
128