blob: f0ce453be49f135a2a7971e2fa5c6f5f2b1984b3 [file] [log] [blame]
Sean Callanan816cb3e2014-10-16 23:15:22 +00001import lldb
2from lldbtest import *
3import lldbutil
4import os
Sean Callanane17428a2014-10-28 20:23:20 +00005import unittest2
6import sys
Sean Callanan816cb3e2014-10-16 23:15:22 +00007
8def source_type(filename):
9 _, extension = os.path.splitext(filename)
10 return {
11 '.c' : 'C_SOURCES',
12 '.cpp' : 'CXX_SOURCES',
13 '.cxx' : 'CXX_SOURCES',
14 '.cc' : 'CXX_SOURCES',
15 '.m' : 'OBJC_SOURCES',
16 '.mm' : 'OBJCXX_SOURCES'
17 }.get(extension, None)
18
19class CommandParser:
20 def __init__(self):
21 self.breakpoints = []
22
23 def parse_one_command(self, line):
24 parts = line.split('//%')
Sean Callanand950fa72014-10-17 00:39:37 +000025
26 command = None
27 new_breakpoint = True
28
29 if len(parts) == 2:
30 command = parts[1].strip() # take off whitespace
31 new_breakpoint = parts[0].strip() != ""
32
33 return (command, new_breakpoint)
Sean Callanan816cb3e2014-10-16 23:15:22 +000034
35 def parse_source_files(self, source_files):
36 for source_file in source_files:
37 file_handle = open(source_file)
38 lines = file_handle.readlines()
39 line_number = 0
Sean Callanand950fa72014-10-17 00:39:37 +000040 current_breakpoint = None # non-NULL means we're looking through whitespace to find additional commands
Sean Callanan816cb3e2014-10-16 23:15:22 +000041 for line in lines:
42 line_number = line_number + 1 # 1-based, so we do this first
Sean Callanand950fa72014-10-17 00:39:37 +000043 (command, new_breakpoint) = self.parse_one_command(line)
44
45 if new_breakpoint:
46 current_breakpoint = None
47
Sean Callanan816cb3e2014-10-16 23:15:22 +000048 if command != None:
Sean Callanand950fa72014-10-17 00:39:37 +000049 if current_breakpoint == None:
50 current_breakpoint = {}
51 current_breakpoint['file_name'] = source_file
52 current_breakpoint['line_number'] = line_number
53 current_breakpoint['command'] = command
54 self.breakpoints.append(current_breakpoint)
55 else:
56 current_breakpoint['command'] = current_breakpoint['command'] + "\n" + command
Sean Callanan816cb3e2014-10-16 23:15:22 +000057
58 def set_breakpoints(self, target):
59 for breakpoint in self.breakpoints:
60 breakpoint['breakpoint'] = target.BreakpointCreateByLocation(breakpoint['file_name'], breakpoint['line_number'])
61
62 def handle_breakpoint(self, test, breakpoint_id):
63 for breakpoint in self.breakpoints:
64 if breakpoint['breakpoint'].GetID() == breakpoint_id:
65 test.execute_user_command(breakpoint['command'])
66 return
67
Sean Callanan816cb3e2014-10-16 23:15:22 +000068class InlineTest(TestBase):
69 # Internal implementation
70
Greg Clayton70995582015-01-07 22:25:50 +000071 def getRerunArgs(self):
72 # The -N option says to NOT run a if it matches the option argument, so
73 # if we are using dSYM we say to NOT run dwarf (-N dwarf) and vice versa.
Siva Chandra311c7db2015-01-09 01:54:44 +000074 if self.using_dsym is None:
75 # The test was skipped altogether.
76 return ""
77 elif self.using_dsym:
Greg Clayton70995582015-01-07 22:25:50 +000078 return "-N dwarf %s" % (self.mydir)
79 else:
80 return "-N dsym %s" % (self.mydir)
81
82 def BuildMakefile(self):
83 if os.path.exists("Makefile"):
84 return
Sean Callanan816cb3e2014-10-16 23:15:22 +000085
Greg Clayton70995582015-01-07 22:25:50 +000086 categories = {}
87
88 for f in os.listdir(os.getcwd()):
89 t = source_type(f)
90 if t:
91 if t in categories.keys():
92 categories[t].append(f)
93 else:
94 categories[t] = [f]
95
96 makefile = open("Makefile", 'w+')
97
98 level = os.sep.join([".."] * len(self.mydir.split(os.sep))) + os.sep + "make"
99
100 makefile.write("LEVEL = " + level + "\n")
101
102 for t in categories.keys():
103 line = t + " := " + " ".join(categories[t])
104 makefile.write(line + "\n")
105
106 if ('OBJCXX_SOURCES' in categories.keys()) or ('OBJC_SOURCES' in categories.keys()):
107 makefile.write("LDFLAGS = $(CFLAGS) -lobjc -framework Foundation\n")
108
109 if ('CXX_SOURCES' in categories.keys()):
110 makefile.write("CXXFLAGS += -std=c++11\n")
111
112 makefile.write("include $(LEVEL)/Makefile.rules\n")
113 makefile.flush()
114 makefile.close()
115
Sean Callanan816cb3e2014-10-16 23:15:22 +0000116
Robert Flack13c7ad92015-03-30 14:12:17 +0000117 @skipUnlessDarwin
Sean Callanane17428a2014-10-28 20:23:20 +0000118 def __test_with_dsym(self):
Greg Clayton70995582015-01-07 22:25:50 +0000119 self.using_dsym = True
120 self.BuildMakefile()
121 self.buildDsym()
Sean Callanan816cb3e2014-10-16 23:15:22 +0000122 self.do_test()
123
Sean Callanane17428a2014-10-28 20:23:20 +0000124 def __test_with_dwarf(self):
Greg Clayton70995582015-01-07 22:25:50 +0000125 self.using_dsym = False
126 self.BuildMakefile()
127 self.buildDwarf()
Sean Callanan816cb3e2014-10-16 23:15:22 +0000128 self.do_test()
129
Enrico Granata238de512015-10-19 20:40:50 +0000130 def __test_with_dwo(self):
131 self.using_dsym = False
132 self.BuildMakefile()
133 self.buildDwo()
134 self.do_test()
135
Sean Callanan816cb3e2014-10-16 23:15:22 +0000136 def execute_user_command(self, __command):
137 exec __command in globals(), locals()
138
139 def do_test(self):
140 exe_name = "a.out"
141 exe = os.path.join(os.getcwd(), exe_name)
142 source_files = [ f for f in os.listdir(os.getcwd()) if source_type(f) ]
143 target = self.dbg.CreateTarget(exe)
144
145 parser = CommandParser()
146 parser.parse_source_files(source_files)
147 parser.set_breakpoints(target)
148
149 process = target.LaunchSimple(None, None, os.getcwd())
150
151 while lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint):
152 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)
153 breakpoint_id = thread.GetStopReasonDataAtIndex (0)
154 parser.handle_breakpoint(self, breakpoint_id)
155 process.Continue()
156
Sean Callanan816cb3e2014-10-16 23:15:22 +0000157
158 # Utilities for testcases
159
160 def check_expression (self, expression, expected_result, use_summary = True):
161 value = self.frame().EvaluateExpression (expression)
162 self.assertTrue(value.IsValid(), expression+"returned a valid value")
163 if self.TraceOn():
164 print value.GetSummary()
165 print value.GetValue()
166 if use_summary:
167 answer = value.GetSummary()
168 else:
169 answer = value.GetValue()
170 report_str = "%s expected: %s got: %s"%(expression, expected_result, answer)
171 self.assertTrue(answer == expected_result, report_str)
172
Sean Callanane17428a2014-10-28 20:23:20 +0000173def ApplyDecoratorsToFunction(func, decorators):
174 tmp = func
175 if type(decorators) == list:
176 for decorator in decorators:
177 tmp = decorator(tmp)
178 elif hasattr(decorators, '__call__'):
179 tmp = decorators(tmp)
180 return tmp
181
182
183def MakeInlineTest(__file, __globals, decorators=None):
Sean Callanan816cb3e2014-10-16 23:15:22 +0000184 # Derive the test name from the current file name
185 file_basename = os.path.basename(__file)
186 InlineTest.mydir = TestBase.compute_mydir(__file)
187
188 test_name, _ = os.path.splitext(file_basename)
189 # Build the test case
Siva Chandra311c7db2015-01-09 01:54:44 +0000190 test = type(test_name, (InlineTest,), {'using_dsym': None})
Sean Callanan816cb3e2014-10-16 23:15:22 +0000191 test.name = test_name
Sean Callanane17428a2014-10-28 20:23:20 +0000192
193 test.test_with_dsym = ApplyDecoratorsToFunction(test._InlineTest__test_with_dsym, decorators)
194 test.test_with_dwarf = ApplyDecoratorsToFunction(test._InlineTest__test_with_dwarf, decorators)
Enrico Granata238de512015-10-19 20:40:50 +0000195 test.test_with_dwo = ApplyDecoratorsToFunction(test._InlineTest__test_with_dwo, decorators)
Sean Callanane17428a2014-10-28 20:23:20 +0000196
Sean Callanan816cb3e2014-10-16 23:15:22 +0000197 # Add the test case to the globals, and hide InlineTest
198 __globals.update({test_name : test})
Enrico Granataab0e8312014-11-05 21:31:57 +0000199
200 return test
Sean Callanan816cb3e2014-10-16 23:15:22 +0000201