File: TestThreadStepOut.py

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (156 lines) | stat: -rw-r--r-- 6,141 bytes parent folder | download | duplicates (10)
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
"""
Test stepping out from a function in a multi-threaded program.
"""


import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil


class ThreadStepOutTestCase(TestBase):
    @skipIfWindows  # This test will hang on windows llvm.org/pr21753
    @expectedFailureAll(oslist=["windows"])
    @expectedFailureNetBSD
    def test_step_single_thread(self):
        """Test thread step out on one thread via command interpreter."""
        self.build()
        self.step_out_test(self.step_out_single_thread_with_cmd)

    @skipIfWindows  # This test will hang on windows llvm.org/pr21753
    @expectedFailureAll(oslist=["windows"])
    @expectedFailureAll(
        oslist=["watchos"], archs=["armv7k"], bugnumber="rdar://problem/34674488"
    )  # stop reason is trace when it should be step-out
    @expectedFailureNetBSD
    def test_step_all_threads(self):
        """Test thread step out on all threads via command interpreter."""
        self.build()
        self.step_out_test(self.step_out_all_threads_with_cmd)

    @skipIfWindows  # This test will hang on windows llvm.org/pr21753
    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24681")
    @expectedFailureNetBSD
    def test_python(self):
        """Test thread step out on one thread via Python API (dwarf)."""
        self.build()
        self.step_out_test(self.step_out_with_python)

    def setUp(self):
        # Call super's setUp().
        TestBase.setUp(self)
        # Find the line number for our breakpoint.
        self.bkpt_string = "// Set breakpoint here"
        self.breakpoint = line_number("main.cpp", self.bkpt_string)
        self.step_in_line = line_number("main.cpp", "// But we might still be here")
        self.step_out_dest = line_number(
            "main.cpp", "// Expect to stop here after step-out."
        )

    def check_stepping_thread(self):
        zeroth_frame = self.step_out_thread.frames[0]
        line_entry = zeroth_frame.line_entry
        self.assertTrue(line_entry.IsValid(), "Stopped at a valid line entry")
        self.assertEqual("main.cpp", line_entry.file.basename, "Still in main.cpp")
        # We can't really tell whether we stay on our line
        # or get to the next line, it depends on whether there are any
        # instructions between the call and the return.
        line = line_entry.line
        self.assertTrue(
            line == self.step_out_dest or line == self.step_in_line,
            "Stepped to the wrong line: {0}".format(line),
        )

    def step_out_single_thread_with_cmd(self):
        other_threads = {}
        for thread in self.process.threads:
            if thread.GetIndexID() == self.step_out_thread.GetIndexID():
                continue
            other_threads[thread.GetIndexID()] = thread.frames[0].line_entry

        # There should be other threads...
        self.assertNotEqual(len(other_threads), 0)
        self.step_out_with_cmd("this-thread")
        # The other threads should not have made progress:
        for thread in self.process.threads:
            index_id = thread.GetIndexID()
            line_entry = other_threads.get(index_id)
            if line_entry:
                self.assertEqual(
                    thread.frames[0].line_entry.file.basename,
                    line_entry.file.basename,
                    "Thread {0} moved by file".format(index_id),
                )
                self.assertEqual(
                    thread.frames[0].line_entry.line,
                    line_entry.line,
                    "Thread {0} moved by line".format(index_id),
                )

    def step_out_all_threads_with_cmd(self):
        self.step_out_with_cmd("all-threads")

    def step_out_with_cmd(self, run_mode):
        self.runCmd("thread select %d" % self.step_out_thread.GetIndexID())
        self.runCmd("thread step-out -m %s" % run_mode)
        self.expect(
            "process status",
            "Expected stop reason to be step-out",
            substrs=["stop reason = step out"],
        )

        selected_thread = self.process.GetSelectedThread()
        self.assertEqual(
            selected_thread.GetIndexID(),
            self.step_out_thread.GetIndexID(),
            "Step out changed selected thread.",
        )
        self.check_stepping_thread()

    def step_out_with_python(self):
        self.step_out_thread.StepOut()

        reason = self.step_out_thread.GetStopReason()
        self.assertEqual(
            lldb.eStopReasonPlanComplete,
            reason,
            "Expected thread stop reason 'plancomplete', but got '%s'"
            % lldbutil.stop_reason_to_str(reason),
        )
        self.check_stepping_thread()

    def step_out_test(self, step_out_func):
        """Test single thread step out of a function."""
        (
            self.inferior_target,
            self.process,
            thread,
            bkpt,
        ) = lldbutil.run_to_source_breakpoint(
            self, self.bkpt_string, lldb.SBFileSpec("main.cpp"), only_one_thread=False
        )

        # We hit the breakpoint on at least one thread.  If we hit it on both threads
        # simultaneously, we can try the step out.  Otherwise, suspend the thread
        # that hit the breakpoint, and continue till the second thread hits
        # the breakpoint:

        (breakpoint_threads, other_threads) = ([], [])
        lldbutil.sort_stopped_threads(
            self.process,
            breakpoint_threads=breakpoint_threads,
            other_threads=other_threads,
        )
        if len(breakpoint_threads) == 1:
            success = thread.Suspend()
            self.assertTrue(success, "Couldn't suspend a thread")
            breakpoint_threads = lldbutil.continue_to_breakpoint(self.process, bkpt)
            self.assertEqual(len(breakpoint_threads), 2, "Second thread stopped")
            success = thread.Resume()
            self.assertTrue(success, "Couldn't resume a thread")

        self.step_out_thread = breakpoint_threads[0]

        # Step out of thread stopped at breakpoint
        step_out_func()