blob: 6a61b2eaf557ab3c0e04eed392dec43f4f0ce54c [file] [log] [blame]
Zachary Turnerff890da2015-10-19 23:45:41 +00001from __future__ import print_function
Zachary Turnerc1b7cd72015-11-05 19:22:28 +00002from __future__ import absolute_import
Zachary Turnerff890da2015-10-19 23:45:41 +00003
Zachary Turnerc1b7cd72015-11-05 19:22:28 +00004# System modules
Sean Callanan816cb3e2014-10-16 23:15:22 +00005import os
Sean Callanan816cb3e2014-10-16 23:15:22 +00006
Zachary Turnerc1b7cd72015-11-05 19:22:28 +00007# Third-party modules
8
9# LLDB modules
10import lldb
11from .lldbtest import *
Todd Fiala94eb0102016-05-26 13:57:03 +000012from . import configuration
Zachary Turnerc1b7cd72015-11-05 19:22:28 +000013from . import lldbutil
Zachary Turner9a1a2942016-02-04 23:04:17 +000014from .decorators import *
Zachary Turnerc1b7cd72015-11-05 19:22:28 +000015
Sean Callanan816cb3e2014-10-16 23:15:22 +000016def 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)
26
Todd Fialad9be7532016-01-06 19:16:45 +000027
Sean Callanan816cb3e2014-10-16 23:15:22 +000028class CommandParser:
29 def __init__(self):
30 self.breakpoints = []
31
32 def parse_one_command(self, line):
33 parts = line.split('//%')
Sean Callanand950fa72014-10-17 00:39:37 +000034
35 command = None
36 new_breakpoint = True
37
38 if len(parts) == 2:
Todd Fialad9be7532016-01-06 19:16:45 +000039 command = parts[1].strip() # take off whitespace
Sean Callanand950fa72014-10-17 00:39:37 +000040 new_breakpoint = parts[0].strip() != ""
41
42 return (command, new_breakpoint)
Sean Callanan816cb3e2014-10-16 23:15:22 +000043
44 def parse_source_files(self, source_files):
45 for source_file in source_files:
46 file_handle = open(source_file)
47 lines = file_handle.readlines()
48 line_number = 0
Sean Callanand950fa72014-10-17 00:39:37 +000049 current_breakpoint = None # non-NULL means we're looking through whitespace to find additional commands
Sean Callanan816cb3e2014-10-16 23:15:22 +000050 for line in lines:
51 line_number = line_number + 1 # 1-based, so we do this first
Sean Callanand950fa72014-10-17 00:39:37 +000052 (command, new_breakpoint) = self.parse_one_command(line)
53
54 if new_breakpoint:
55 current_breakpoint = None
56
Sean Callanan816cb3e2014-10-16 23:15:22 +000057 if command != None:
Sean Callanand950fa72014-10-17 00:39:37 +000058 if current_breakpoint == None:
59 current_breakpoint = {}
60 current_breakpoint['file_name'] = source_file
61 current_breakpoint['line_number'] = line_number
62 current_breakpoint['command'] = command
63 self.breakpoints.append(current_breakpoint)
64 else:
65 current_breakpoint['command'] = current_breakpoint['command'] + "\n" + command
Sean Callanan816cb3e2014-10-16 23:15:22 +000066
67 def set_breakpoints(self, target):
68 for breakpoint in self.breakpoints:
69 breakpoint['breakpoint'] = target.BreakpointCreateByLocation(breakpoint['file_name'], breakpoint['line_number'])
70
71 def handle_breakpoint(self, test, breakpoint_id):
72 for breakpoint in self.breakpoints:
73 if breakpoint['breakpoint'].GetID() == breakpoint_id:
74 test.execute_user_command(breakpoint['command'])
75 return
76
Sean Callanan816cb3e2014-10-16 23:15:22 +000077class InlineTest(TestBase):
78 # Internal implementation
79
Greg Clayton70995582015-01-07 22:25:50 +000080 def getRerunArgs(self):
81 # The -N option says to NOT run a if it matches the option argument, so
82 # if we are using dSYM we say to NOT run dwarf (-N dwarf) and vice versa.
Siva Chandra311c7db2015-01-09 01:54:44 +000083 if self.using_dsym is None:
84 # The test was skipped altogether.
85 return ""
86 elif self.using_dsym:
Greg Clayton70995582015-01-07 22:25:50 +000087 return "-N dwarf %s" % (self.mydir)
88 else:
89 return "-N dsym %s" % (self.mydir)
Todd Fialad9be7532016-01-06 19:16:45 +000090
Greg Clayton70995582015-01-07 22:25:50 +000091 def BuildMakefile(self):
92 if os.path.exists("Makefile"):
93 return
Sean Callanan816cb3e2014-10-16 23:15:22 +000094
Greg Clayton70995582015-01-07 22:25:50 +000095 categories = {}
96
97 for f in os.listdir(os.getcwd()):
98 t = source_type(f)
99 if t:
Zachary Turner606e1e32015-10-23 17:53:51 +0000100 if t in list(categories.keys()):
Greg Clayton70995582015-01-07 22:25:50 +0000101 categories[t].append(f)
102 else:
103 categories[t] = [f]
104
105 makefile = open("Makefile", 'w+')
106
107 level = os.sep.join([".."] * len(self.mydir.split(os.sep))) + os.sep + "make"
108
109 makefile.write("LEVEL = " + level + "\n")
110
Zachary Turner606e1e32015-10-23 17:53:51 +0000111 for t in list(categories.keys()):
Greg Clayton70995582015-01-07 22:25:50 +0000112 line = t + " := " + " ".join(categories[t])
113 makefile.write(line + "\n")
114
Zachary Turner606e1e32015-10-23 17:53:51 +0000115 if ('OBJCXX_SOURCES' in list(categories.keys())) or ('OBJC_SOURCES' in list(categories.keys())):
Greg Clayton70995582015-01-07 22:25:50 +0000116 makefile.write("LDFLAGS = $(CFLAGS) -lobjc -framework Foundation\n")
117
Zachary Turner606e1e32015-10-23 17:53:51 +0000118 if ('CXX_SOURCES' in list(categories.keys())):
Greg Clayton70995582015-01-07 22:25:50 +0000119 makefile.write("CXXFLAGS += -std=c++11\n")
120
121 makefile.write("include $(LEVEL)/Makefile.rules\n")
Sean Callananbca81c52016-01-26 01:15:57 +0000122 makefile.write("\ncleanup:\n\trm -f Makefile *.d\n\n")
Greg Clayton70995582015-01-07 22:25:50 +0000123 makefile.flush()
124 makefile.close()
125
Robert Flack13c7ad92015-03-30 14:12:17 +0000126 @skipUnlessDarwin
Sean Callanane17428a2014-10-28 20:23:20 +0000127 def __test_with_dsym(self):
Greg Clayton70995582015-01-07 22:25:50 +0000128 self.using_dsym = True
129 self.BuildMakefile()
130 self.buildDsym()
Sean Callanan816cb3e2014-10-16 23:15:22 +0000131 self.do_test()
132
Sean Callanane17428a2014-10-28 20:23:20 +0000133 def __test_with_dwarf(self):
Greg Clayton70995582015-01-07 22:25:50 +0000134 self.using_dsym = False
135 self.BuildMakefile()
136 self.buildDwarf()
Sean Callanan816cb3e2014-10-16 23:15:22 +0000137 self.do_test()
138
Enrico Granata238de512015-10-19 20:40:50 +0000139 def __test_with_dwo(self):
140 self.using_dsym = False
141 self.BuildMakefile()
142 self.buildDwo()
143 self.do_test()
144
Todd Fiala94eb0102016-05-26 13:57:03 +0000145 def __test_with_gmodules(self):
146 self.using_dsym = False
147 self.BuildMakefile()
148 self.buildGModules()
149 self.do_test()
150
Sean Callanan816cb3e2014-10-16 23:15:22 +0000151 def execute_user_command(self, __command):
Zachary Turner5821f792015-11-06 21:37:21 +0000152 exec(__command, globals(), locals())
Sean Callanan816cb3e2014-10-16 23:15:22 +0000153
154 def do_test(self):
155 exe_name = "a.out"
156 exe = os.path.join(os.getcwd(), exe_name)
157 source_files = [ f for f in os.listdir(os.getcwd()) if source_type(f) ]
158 target = self.dbg.CreateTarget(exe)
159
160 parser = CommandParser()
161 parser.parse_source_files(source_files)
162 parser.set_breakpoints(target)
163
164 process = target.LaunchSimple(None, None, os.getcwd())
165
166 while lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint):
167 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)
168 breakpoint_id = thread.GetStopReasonDataAtIndex (0)
169 parser.handle_breakpoint(self, breakpoint_id)
170 process.Continue()
171
Sean Callanan816cb3e2014-10-16 23:15:22 +0000172
173 # Utilities for testcases
174
175 def check_expression (self, expression, expected_result, use_summary = True):
176 value = self.frame().EvaluateExpression (expression)
177 self.assertTrue(value.IsValid(), expression+"returned a valid value")
178 if self.TraceOn():
Zachary Turnerff890da2015-10-19 23:45:41 +0000179 print(value.GetSummary())
180 print(value.GetValue())
Sean Callanan816cb3e2014-10-16 23:15:22 +0000181 if use_summary:
182 answer = value.GetSummary()
183 else:
184 answer = value.GetValue()
185 report_str = "%s expected: %s got: %s"%(expression, expected_result, answer)
186 self.assertTrue(answer == expected_result, report_str)
187
Sean Callanane17428a2014-10-28 20:23:20 +0000188def ApplyDecoratorsToFunction(func, decorators):
189 tmp = func
190 if type(decorators) == list:
191 for decorator in decorators:
192 tmp = decorator(tmp)
193 elif hasattr(decorators, '__call__'):
194 tmp = decorators(tmp)
195 return tmp
Adrian McCarthy3f998102016-05-04 23:32:35 +0000196
Sean Callanane17428a2014-10-28 20:23:20 +0000197
198def MakeInlineTest(__file, __globals, decorators=None):
Todd Fialadad52ce2016-04-18 20:26:56 +0000199 # Adjust the filename if it ends in .pyc. We want filenames to
200 # reflect the source python file, not the compiled variant.
201 if __file is not None and __file.endswith(".pyc"):
202 # Strip the trailing "c"
203 __file = __file[0:-1]
204
Sean Callanan816cb3e2014-10-16 23:15:22 +0000205 # Derive the test name from the current file name
206 file_basename = os.path.basename(__file)
207 InlineTest.mydir = TestBase.compute_mydir(__file)
208
209 test_name, _ = os.path.splitext(file_basename)
Adrian McCarthy3f998102016-05-04 23:32:35 +0000210 # Build the test case
Siva Chandra311c7db2015-01-09 01:54:44 +0000211 test = type(test_name, (InlineTest,), {'using_dsym': None})
Sean Callanan816cb3e2014-10-16 23:15:22 +0000212 test.name = test_name
Sean Callanane17428a2014-10-28 20:23:20 +0000213
Adrian McCarthy3f998102016-05-04 23:32:35 +0000214 target_platform = lldb.DBG.GetSelectedPlatform().GetTriple().split('-')[2]
Todd Fiala94eb0102016-05-26 13:57:03 +0000215 if test_categories.is_supported_on_platform("dsym", target_platform, configuration.compilers):
Adrian McCarthy3f998102016-05-04 23:32:35 +0000216 test.test_with_dsym = ApplyDecoratorsToFunction(test._InlineTest__test_with_dsym, decorators)
Todd Fiala94eb0102016-05-26 13:57:03 +0000217 if test_categories.is_supported_on_platform("dwarf", target_platform, configuration.compilers):
Adrian McCarthy3f998102016-05-04 23:32:35 +0000218 test.test_with_dwarf = ApplyDecoratorsToFunction(test._InlineTest__test_with_dwarf, decorators)
Todd Fiala94eb0102016-05-26 13:57:03 +0000219 if test_categories.is_supported_on_platform("dwo", target_platform, configuration.compilers):
Adrian McCarthy3f998102016-05-04 23:32:35 +0000220 test.test_with_dwo = ApplyDecoratorsToFunction(test._InlineTest__test_with_dwo, decorators)
Todd Fiala94eb0102016-05-26 13:57:03 +0000221 if test_categories.is_supported_on_platform("gmodules", target_platform, configuration.compilers):
222 test.test_with_gmodules = ApplyDecoratorsToFunction(test._InlineTest__test_with_gmodules, decorators)
Sean Callanane17428a2014-10-28 20:23:20 +0000223
Sean Callanan816cb3e2014-10-16 23:15:22 +0000224 # Add the test case to the globals, and hide InlineTest
225 __globals.update({test_name : test})
Todd Fiala5bdbef642015-12-22 17:14:47 +0000226
Todd Fialadad52ce2016-04-18 20:26:56 +0000227 # Keep track of the original test filename so we report it
228 # correctly in test results.
Todd Fiala5bdbef642015-12-22 17:14:47 +0000229 test.test_filename = __file
Enrico Granataab0e8312014-11-05 21:31:57 +0000230 return test
Sean Callanan816cb3e2014-10-16 23:15:22 +0000231