Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / lldb / packages / Python / lldbsuite / test / lldbinline.py
blobae38ab9d8c9d7267ad2a0088abfa7971dc340a8d
1 # System modules
2 import os
3 import textwrap
5 # Third-party modules
6 import io
8 # LLDB modules
9 import lldb
10 from .lldbtest import *
11 from . import configuration
12 from . import lldbutil
13 from .decorators import *
16 def source_type(filename):
17 _, extension = os.path.splitext(filename)
18 return {
19 ".c": "C_SOURCES",
20 ".cpp": "CXX_SOURCES",
21 ".cxx": "CXX_SOURCES",
22 ".cc": "CXX_SOURCES",
23 ".m": "OBJC_SOURCES",
24 ".mm": "OBJCXX_SOURCES",
25 }.get(extension, None)
28 class CommandParser:
29 def __init__(self):
30 self.breakpoints = []
32 def parse_one_command(self, line):
33 parts = line.split("//%")
35 command = None
36 new_breakpoint = True
38 if len(parts) == 2:
39 command = parts[1].rstrip()
40 new_breakpoint = parts[0].strip() != ""
42 return (command, new_breakpoint)
44 def parse_source_files(self, source_files):
45 for source_file in source_files:
46 file_handle = io.open(source_file, encoding="utf-8")
47 lines = file_handle.readlines()
48 line_number = 0
49 # non-NULL means we're looking through whitespace to find
50 # additional commands
51 current_breakpoint = None
52 for line in lines:
53 line_number = line_number + 1 # 1-based, so we do this first
54 (command, new_breakpoint) = self.parse_one_command(line)
56 if new_breakpoint:
57 current_breakpoint = None
59 if command is not None:
60 if current_breakpoint is None:
61 current_breakpoint = {}
62 current_breakpoint["file_name"] = source_file
63 current_breakpoint["line_number"] = line_number
64 current_breakpoint["command"] = command
65 self.breakpoints.append(current_breakpoint)
66 else:
67 current_breakpoint["command"] = (
68 current_breakpoint["command"] + "\n" + command
70 for bkpt in self.breakpoints:
71 bkpt["command"] = textwrap.dedent(bkpt["command"])
73 def set_breakpoints(self, target):
74 for breakpoint in self.breakpoints:
75 breakpoint["breakpoint"] = target.BreakpointCreateByLocation(
76 breakpoint["file_name"], breakpoint["line_number"]
79 def handle_breakpoint(self, test, breakpoint_id):
80 for breakpoint in self.breakpoints:
81 if breakpoint["breakpoint"].GetID() == breakpoint_id:
82 test.execute_user_command(breakpoint["command"])
83 return
86 class InlineTest(TestBase):
87 def getBuildDirBasename(self):
88 return self.__class__.__name__ + "." + self.testMethodName
90 def BuildMakefile(self):
91 makefilePath = self.getBuildArtifact("Makefile")
92 if os.path.exists(makefilePath):
93 return
95 categories = {}
96 for f in os.listdir(self.getSourceDir()):
97 t = source_type(f)
98 if t:
99 if t in list(categories.keys()):
100 categories[t].append(f)
101 else:
102 categories[t] = [f]
104 with open(makefilePath, "w+") as makefile:
105 for t in list(categories.keys()):
106 line = t + " := " + " ".join(categories[t])
107 makefile.write(line + "\n")
109 if ("OBJCXX_SOURCES" in list(categories.keys())) or (
110 "OBJC_SOURCES" in list(categories.keys())
112 makefile.write("LDFLAGS = $(CFLAGS) -lobjc -framework Foundation\n")
114 if "CXX_SOURCES" in list(categories.keys()):
115 makefile.write("CXXFLAGS += -std=c++11\n")
117 makefile.write("include Makefile.rules\n")
119 def _test(self):
120 self.BuildMakefile()
121 self.build(dictionary=self._build_dict)
122 self.do_test()
124 def execute_user_command(self, __command):
125 exec(__command, globals(), locals())
127 def _get_breakpoint_ids(self, thread):
128 ids = set()
129 for i in range(0, thread.GetStopReasonDataCount(), 2):
130 ids.add(thread.GetStopReasonDataAtIndex(i))
131 self.assertGreater(len(ids), 0)
132 return sorted(ids)
134 def do_test(self):
135 exe = self.getBuildArtifact("a.out")
136 source_files = [f for f in os.listdir(self.getSourceDir()) if source_type(f)]
137 target = self.dbg.CreateTarget(exe)
139 parser = CommandParser()
140 parser.parse_source_files(source_files)
141 parser.set_breakpoints(target)
143 process = target.LaunchSimple(None, None, self.get_process_working_directory())
144 self.assertIsNotNone(process, PROCESS_IS_VALID)
146 hit_breakpoints = 0
148 while lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint):
149 hit_breakpoints += 1
150 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)
151 for bp_id in self._get_breakpoint_ids(thread):
152 parser.handle_breakpoint(self, bp_id)
153 process.Continue()
155 self.assertTrue(
156 hit_breakpoints > 0, "inline test did not hit a single breakpoint"
158 # Either the process exited or the stepping plan is complete.
159 self.assertTrue(
160 process.GetState() in [lldb.eStateStopped, lldb.eStateExited],
161 PROCESS_EXITED,
164 def check_expression(self, expression, expected_result, use_summary=True):
165 value = self.frame().EvaluateExpression(expression)
166 self.assertTrue(value.IsValid(), expression + "returned a valid value")
167 if self.TraceOn():
168 print(value.GetSummary())
169 print(value.GetValue())
170 if use_summary:
171 answer = value.GetSummary()
172 else:
173 answer = value.GetValue()
174 report_str = "%s expected: %s got: %s" % (expression, expected_result, answer)
175 self.assertTrue(answer == expected_result, report_str)
178 def ApplyDecoratorsToFunction(func, decorators):
179 tmp = func
180 if isinstance(decorators, list):
181 for decorator in decorators:
182 tmp = decorator(tmp)
183 elif hasattr(decorators, "__call__"):
184 tmp = decorators(tmp)
185 return tmp
188 def MakeInlineTest(__file, __globals, decorators=None, name=None, build_dict=None):
189 # Adjust the filename if it ends in .pyc. We want filenames to
190 # reflect the source python file, not the compiled variant.
191 if __file is not None and __file.endswith(".pyc"):
192 # Strip the trailing "c"
193 __file = __file[0:-1]
195 if name is None:
196 # Derive the test name from the current file name
197 file_basename = os.path.basename(__file)
198 name, _ = os.path.splitext(file_basename)
200 test_func = ApplyDecoratorsToFunction(InlineTest._test, decorators)
201 # Build the test case
202 test_class = type(
203 name, (InlineTest,), dict(test=test_func, name=name, _build_dict=build_dict)
206 # Add the test case to the globals, and hide InlineTest
207 __globals.update({name: test_class})
209 # Keep track of the original test filename so we report it
210 # correctly in test results.
211 test_class.test_filename = __file
212 test_class.mydir = TestBase.compute_mydir(__file)
213 return test_class