1"""
2Test number of threads.
3"""
4
5
6
7import lldb
8from lldbsuite.test.decorators import *
9from lldbsuite.test.lldbtest import *
10from lldbsuite.test import lldbutil
11
12
13class BreakpointAfterJoinTestCase(TestBase):
14
15    def setUp(self):
16        # Call super's setUp().
17        TestBase.setUp(self)
18        # Find the line number for our breakpoint.
19        self.breakpoint = line_number('main.cpp', '// Set breakpoint here')
20
21    @expectedFailureAll(
22        oslist=["linux"],
23        bugnumber="llvm.org/pr15824 thread states not properly maintained")
24    @expectedFailureAll(
25        oslist=lldbplatformutil.getDarwinOSTriples(),
26        bugnumber="llvm.org/pr15824 thread states not properly maintained and <rdar://problem/28557237>")
27    @expectedFailureAll(
28        oslist=["freebsd"],
29        bugnumber="llvm.org/pr18190 thread states not properly maintained")
30    @expectedFailureNetBSD
31    def test(self):
32        """Test breakpoint handling after a thread join."""
33        self.build()
34
35        exe = self.getBuildArtifact("a.out")
36        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
37
38        # This should create a breakpoint in the main thread.
39        lldbutil.run_break_set_by_file_and_line(
40            self, "main.cpp", self.breakpoint, num_expected_locations=1)
41
42        # The breakpoint list should show 1 location.
43        self.expect(
44            "breakpoint list -f",
45            "Breakpoint location shown correctly",
46            substrs=[
47                "1: file = 'main.cpp', line = %d, exact_match = 0, locations = 1" %
48                self.breakpoint])
49
50        # Run the program.
51        self.runCmd("run", RUN_SUCCEEDED)
52
53        # The stop reason of the thread should be breakpoint.
54        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
55                    substrs=['stopped',
56                             'stop reason = breakpoint'])
57
58        # Get the target process
59        target = self.dbg.GetSelectedTarget()
60        process = target.GetProcess()
61
62        # The exit probably occurred during breakpoint handling, but it isn't
63        # guaranteed.  The main thing we're testing here is that the debugger
64        # handles this cleanly is some way.
65
66        # Get the number of threads
67        num_threads = process.GetNumThreads()
68
69        # Make sure we see at least six threads
70        self.assertTrue(
71            num_threads >= 6,
72            'Number of expected threads and actual threads do not match.')
73
74        # Make sure all threads are stopped
75        for i in range(0, num_threads):
76            self.assertTrue(
77                process.GetThreadAtIndex(i).IsStopped(),
78                "Thread {0} didn't stop during breakpoint.".format(i))
79
80        # Run to completion
81        self.runCmd("continue")
82
83        # If the process hasn't exited, collect some information
84        if process.GetState() != lldb.eStateExited:
85            self.runCmd("thread list")
86            self.runCmd("process status")
87
88        # At this point, the inferior process should have exited.
89        self.assertEqual(
90            process.GetState(), lldb.eStateExited,
91            PROCESS_EXITED)
92