1 from __future__ import print_function
2 from __future__ import absolute_import
11 from .lldbtest import *
12 from . import configuration
13 from . import lldbutil
14 from .decorators import *
17 def source_type(filename):
18 _, extension = os.path.splitext(filename)
21 '.cpp': 'CXX_SOURCES',
22 '.cxx': 'CXX_SOURCES',
25 '.mm': 'OBJCXX_SOURCES'
26 }.get(extension, None)
34 def parse_one_command(self, line):
35 parts = line.split('//%')
41 command = parts[1].strip() # take off whitespace
42 new_breakpoint = parts[0].strip() != ""
44 return (command, new_breakpoint)
46 def parse_source_files(self, source_files):
47 for source_file in source_files:
48 file_handle = open(source_file)
49 lines = file_handle.readlines()
51 # non-NULL means we're looking through whitespace to find
53 current_breakpoint = None
55 line_number = line_number + 1 # 1-based, so we do this first
56 (command, new_breakpoint) = self.parse_one_command(line)
59 current_breakpoint = None
61 if command is not None:
62 if current_breakpoint is None:
63 current_breakpoint = {}
64 current_breakpoint['file_name'] = source_file
65 current_breakpoint['line_number'] = line_number
66 current_breakpoint['command'] = command
67 self.breakpoints.append(current_breakpoint)
69 current_breakpoint['command'] = current_breakpoint[
70 'command'] + "\n" + command
72 def set_breakpoints(self, target):
73 for breakpoint in self.breakpoints:
74 breakpoint['breakpoint'] = target.BreakpointCreateByLocation(
75 breakpoint['file_name'], breakpoint['line_number'])
77 def handle_breakpoint(self, test, breakpoint_id):
78 for breakpoint in self.breakpoints:
79 if breakpoint['breakpoint'].GetID() == breakpoint_id:
80 test.execute_user_command(breakpoint['command'])
84 class InlineTest(TestBase):
85 # Internal implementation
87 def getRerunArgs(self):
88 # The -N option says to NOT run a if it matches the option argument, so
89 # if we are using dSYM we say to NOT run dwarf (-N dwarf) and vice
91 if self.using_dsym is None:
92 # The test was skipped altogether.
95 return "-N dwarf %s" % (self.mydir)
97 return "-N dsym %s" % (self.mydir)
99 def BuildMakefile(self):
100 if os.path.exists("Makefile"):
105 for f in os.listdir(os.getcwd()):
108 if t in list(categories.keys()):
109 categories[t].append(f)
113 makefile = open("Makefile", 'w+')
116 [".."] * len(self.mydir.split(os.sep))) + os.sep + "make"
118 makefile.write("LEVEL = " + level + "\n")
120 for t in list(categories.keys()):
121 line = t + " := " + " ".join(categories[t])
122 makefile.write(line + "\n")
124 if ('OBJCXX_SOURCES' in list(categories.keys())) or (
125 'OBJC_SOURCES' in list(categories.keys())):
127 "LDFLAGS = $(CFLAGS) -lobjc -framework Foundation\n")
129 if ('CXX_SOURCES' in list(categories.keys())):
130 makefile.write("CXXFLAGS += -std=c++11\n")
132 makefile.write("include $(LEVEL)/Makefile.rules\n")
133 makefile.write("\ncleanup:\n\trm -f Makefile *.d\n\n")
138 def __test_with_dsym(self):
139 self.using_dsym = True
144 def __test_with_dwarf(self):
145 self.using_dsym = False
150 def __test_with_dwo(self):
151 self.using_dsym = False
156 def __test_with_gmodules(self):
157 self.using_dsym = False
162 def execute_user_command(self, __command):
163 exec(__command, globals(), locals())
167 exe = os.path.join(os.getcwd(), exe_name)
168 source_files = [f for f in os.listdir(os.getcwd()) if source_type(f)]
169 target = self.dbg.CreateTarget(exe)
171 parser = CommandParser()
172 parser.parse_source_files(source_files)
173 parser.set_breakpoints(target)
175 process = target.LaunchSimple(None, None, os.getcwd())
177 while lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint):
178 thread = lldbutil.get_stopped_thread(
179 process, lldb.eStopReasonBreakpoint)
180 breakpoint_id = thread.GetStopReasonDataAtIndex(0)
181 parser.handle_breakpoint(self, breakpoint_id)
184 # Utilities for testcases
186 def check_expression(self, expression, expected_result, use_summary=True):
187 value = self.frame().EvaluateExpression(expression)
188 self.assertTrue(value.IsValid(), expression + "returned a valid value")
190 print(value.GetSummary())
191 print(value.GetValue())
193 answer = value.GetSummary()
195 answer = value.GetValue()
196 report_str = "%s expected: %s got: %s" % (
197 expression, expected_result, answer)
198 self.assertTrue(answer == expected_result, report_str)
201 def ApplyDecoratorsToFunction(func, decorators):
203 if isinstance(decorators, list):
204 for decorator in decorators:
206 elif hasattr(decorators, '__call__'):
207 tmp = decorators(tmp)
211 def MakeInlineTest(__file, __globals, decorators=None):
212 # Adjust the filename if it ends in .pyc. We want filenames to
213 # reflect the source python file, not the compiled variant.
214 if __file is not None and __file.endswith(".pyc"):
215 # Strip the trailing "c"
216 __file = __file[0:-1]
218 # Derive the test name from the current file name
219 file_basename = os.path.basename(__file)
220 InlineTest.mydir = TestBase.compute_mydir(__file)
222 test_name, _ = os.path.splitext(file_basename)
223 # Build the test case
224 test = type(test_name, (InlineTest,), {'using_dsym': None})
225 test.name = test_name
227 target_platform = lldb.DBG.GetSelectedPlatform().GetTriple().split('-')[2]
228 if test_categories.is_supported_on_platform(
229 "dsym", target_platform, configuration.compilers):
230 test.test_with_dsym = ApplyDecoratorsToFunction(
231 test._InlineTest__test_with_dsym, decorators)
232 if test_categories.is_supported_on_platform(
233 "dwarf", target_platform, configuration.compilers):
234 test.test_with_dwarf = ApplyDecoratorsToFunction(
235 test._InlineTest__test_with_dwarf, decorators)
236 if test_categories.is_supported_on_platform(
237 "dwo", target_platform, configuration.compilers):
238 test.test_with_dwo = ApplyDecoratorsToFunction(
239 test._InlineTest__test_with_dwo, decorators)
240 if test_categories.is_supported_on_platform(
241 "gmodules", target_platform, configuration.compilers):
242 test.test_with_gmodules = ApplyDecoratorsToFunction(
243 test._InlineTest__test_with_gmodules, decorators)
245 # Add the test case to the globals, and hide InlineTest
246 __globals.update({test_name: test})
248 # Keep track of the original test filename so we report it
249 # correctly in test results.
250 test.test_filename = __file