blob: 0051c75b320b2567cf1975f432b42130cbae0f1a [file] [log] [blame]
Zachary Turnerff890da2015-10-19 23:45:41 +00001from __future__ import print_function
2
Sean Callanan816cb3e2014-10-16 23:15:22 +00003import lldb
4from lldbtest import *
5import lldbutil
6import os
Sean Callanane17428a2014-10-28 20:23:20 +00007import unittest2
8import sys
Sean Callanan816cb3e2014-10-16 23:15:22 +00009
10def source_type(filename):
11 _, extension = os.path.splitext(filename)
12 return {
13 '.c' : 'C_SOURCES',
14 '.cpp' : 'CXX_SOURCES',
15 '.cxx' : 'CXX_SOURCES',
16 '.cc' : 'CXX_SOURCES',
17 '.m' : 'OBJC_SOURCES',
18 '.mm' : 'OBJCXX_SOURCES'
19 }.get(extension, None)
20
21class CommandParser:
22 def __init__(self):
23 self.breakpoints = []
24
25 def parse_one_command(self, line):
26 parts = line.split('//%')
Sean Callanand950fa72014-10-17 00:39:37 +000027
28 command = None
29 new_breakpoint = True
30
31 if len(parts) == 2:
32 command = parts[1].strip() # take off whitespace
33 new_breakpoint = parts[0].strip() != ""
34
35 return (command, new_breakpoint)
Sean Callanan816cb3e2014-10-16 23:15:22 +000036
37 def parse_source_files(self, source_files):
38 for source_file in source_files:
39 file_handle = open(source_file)
40 lines = file_handle.readlines()
41 line_number = 0
Sean Callanand950fa72014-10-17 00:39:37 +000042 current_breakpoint = None # non-NULL means we're looking through whitespace to find additional commands
Sean Callanan816cb3e2014-10-16 23:15:22 +000043 for line in lines:
44 line_number = line_number + 1 # 1-based, so we do this first
Sean Callanand950fa72014-10-17 00:39:37 +000045 (command, new_breakpoint) = self.parse_one_command(line)
46
47 if new_breakpoint:
48 current_breakpoint = None
49
Sean Callanan816cb3e2014-10-16 23:15:22 +000050 if command != None:
Sean Callanand950fa72014-10-17 00:39:37 +000051 if current_breakpoint == None:
52 current_breakpoint = {}
53 current_breakpoint['file_name'] = source_file
54 current_breakpoint['line_number'] = line_number
55 current_breakpoint['command'] = command
56 self.breakpoints.append(current_breakpoint)
57 else:
58 current_breakpoint['command'] = current_breakpoint['command'] + "\n" + command
Sean Callanan816cb3e2014-10-16 23:15:22 +000059
60 def set_breakpoints(self, target):
61 for breakpoint in self.breakpoints:
62 breakpoint['breakpoint'] = target.BreakpointCreateByLocation(breakpoint['file_name'], breakpoint['line_number'])
63
64 def handle_breakpoint(self, test, breakpoint_id):
65 for breakpoint in self.breakpoints:
66 if breakpoint['breakpoint'].GetID() == breakpoint_id:
67 test.execute_user_command(breakpoint['command'])
68 return
69
Sean Callanan816cb3e2014-10-16 23:15:22 +000070class InlineTest(TestBase):
71 # Internal implementation
72
Greg Clayton70995582015-01-07 22:25:50 +000073 def getRerunArgs(self):
74 # The -N option says to NOT run a if it matches the option argument, so
75 # if we are using dSYM we say to NOT run dwarf (-N dwarf) and vice versa.
Siva Chandra311c7db2015-01-09 01:54:44 +000076 if self.using_dsym is None:
77 # The test was skipped altogether.
78 return ""
79 elif self.using_dsym:
Greg Clayton70995582015-01-07 22:25:50 +000080 return "-N dwarf %s" % (self.mydir)
81 else:
82 return "-N dsym %s" % (self.mydir)
83
84 def BuildMakefile(self):
85 if os.path.exists("Makefile"):
86 return
Sean Callanan816cb3e2014-10-16 23:15:22 +000087
Greg Clayton70995582015-01-07 22:25:50 +000088 categories = {}
89
90 for f in os.listdir(os.getcwd()):
91 t = source_type(f)
92 if t:
93 if t in categories.keys():
94 categories[t].append(f)
95 else:
96 categories[t] = [f]
97
98 makefile = open("Makefile", 'w+')
99
100 level = os.sep.join([".."] * len(self.mydir.split(os.sep))) + os.sep + "make"
101
102 makefile.write("LEVEL = " + level + "\n")
103
104 for t in categories.keys():
105 line = t + " := " + " ".join(categories[t])
106 makefile.write(line + "\n")
107
108 if ('OBJCXX_SOURCES' in categories.keys()) or ('OBJC_SOURCES' in categories.keys()):
109 makefile.write("LDFLAGS = $(CFLAGS) -lobjc -framework Foundation\n")
110
111 if ('CXX_SOURCES' in categories.keys()):
112 makefile.write("CXXFLAGS += -std=c++11\n")
113
114 makefile.write("include $(LEVEL)/Makefile.rules\n")
115 makefile.flush()
116 makefile.close()
117
Sean Callanan816cb3e2014-10-16 23:15:22 +0000118
Robert Flack13c7ad92015-03-30 14:12:17 +0000119 @skipUnlessDarwin
Sean Callanane17428a2014-10-28 20:23:20 +0000120 def __test_with_dsym(self):
Greg Clayton70995582015-01-07 22:25:50 +0000121 self.using_dsym = True
122 self.BuildMakefile()
123 self.buildDsym()
Sean Callanan816cb3e2014-10-16 23:15:22 +0000124 self.do_test()
125
Sean Callanane17428a2014-10-28 20:23:20 +0000126 def __test_with_dwarf(self):
Greg Clayton70995582015-01-07 22:25:50 +0000127 self.using_dsym = False
128 self.BuildMakefile()
129 self.buildDwarf()
Sean Callanan816cb3e2014-10-16 23:15:22 +0000130 self.do_test()
131
Enrico Granata238de512015-10-19 20:40:50 +0000132 def __test_with_dwo(self):
133 self.using_dsym = False
134 self.BuildMakefile()
135 self.buildDwo()
136 self.do_test()
137
Sean Callanan816cb3e2014-10-16 23:15:22 +0000138 def execute_user_command(self, __command):
139 exec __command in globals(), locals()
140
141 def do_test(self):
142 exe_name = "a.out"
143 exe = os.path.join(os.getcwd(), exe_name)
144 source_files = [ f for f in os.listdir(os.getcwd()) if source_type(f) ]
145 target = self.dbg.CreateTarget(exe)
146
147 parser = CommandParser()
148 parser.parse_source_files(source_files)
149 parser.set_breakpoints(target)
150
151 process = target.LaunchSimple(None, None, os.getcwd())
152
153 while lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint):
154 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)
155 breakpoint_id = thread.GetStopReasonDataAtIndex (0)
156 parser.handle_breakpoint(self, breakpoint_id)
157 process.Continue()
158
Sean Callanan816cb3e2014-10-16 23:15:22 +0000159
160 # Utilities for testcases
161
162 def check_expression (self, expression, expected_result, use_summary = True):
163 value = self.frame().EvaluateExpression (expression)
164 self.assertTrue(value.IsValid(), expression+"returned a valid value")
165 if self.TraceOn():
Zachary Turnerff890da2015-10-19 23:45:41 +0000166 print(value.GetSummary())
167 print(value.GetValue())
Sean Callanan816cb3e2014-10-16 23:15:22 +0000168 if use_summary:
169 answer = value.GetSummary()
170 else:
171 answer = value.GetValue()
172 report_str = "%s expected: %s got: %s"%(expression, expected_result, answer)
173 self.assertTrue(answer == expected_result, report_str)
174
Sean Callanane17428a2014-10-28 20:23:20 +0000175def ApplyDecoratorsToFunction(func, decorators):
176 tmp = func
177 if type(decorators) == list:
178 for decorator in decorators:
179 tmp = decorator(tmp)
180 elif hasattr(decorators, '__call__'):
181 tmp = decorators(tmp)
182 return tmp
183
184
185def MakeInlineTest(__file, __globals, decorators=None):
Sean Callanan816cb3e2014-10-16 23:15:22 +0000186 # Derive the test name from the current file name
187 file_basename = os.path.basename(__file)
188 InlineTest.mydir = TestBase.compute_mydir(__file)
189
190 test_name, _ = os.path.splitext(file_basename)
191 # Build the test case
Siva Chandra311c7db2015-01-09 01:54:44 +0000192 test = type(test_name, (InlineTest,), {'using_dsym': None})
Sean Callanan816cb3e2014-10-16 23:15:22 +0000193 test.name = test_name
Sean Callanane17428a2014-10-28 20:23:20 +0000194
195 test.test_with_dsym = ApplyDecoratorsToFunction(test._InlineTest__test_with_dsym, decorators)
196 test.test_with_dwarf = ApplyDecoratorsToFunction(test._InlineTest__test_with_dwarf, decorators)
Enrico Granata238de512015-10-19 20:40:50 +0000197 test.test_with_dwo = ApplyDecoratorsToFunction(test._InlineTest__test_with_dwo, decorators)
Sean Callanane17428a2014-10-28 20:23:20 +0000198
Sean Callanan816cb3e2014-10-16 23:15:22 +0000199 # Add the test case to the globals, and hide InlineTest
200 __globals.update({test_name : test})
Enrico Granataab0e8312014-11-05 21:31:57 +0000201
202 return test
Sean Callanan816cb3e2014-10-16 23:15:22 +0000203