blob: 52925a0c94d163707405beeddcbd77219d415c63 [file] [log] [blame]
Sean Callanan816cb3e2014-10-16 23:15:22 +00001import lldb
2from lldbtest import *
3import lldbutil
4import os
5import new
6
7def source_type(filename):
8 _, extension = os.path.splitext(filename)
9 return {
10 '.c' : 'C_SOURCES',
11 '.cpp' : 'CXX_SOURCES',
12 '.cxx' : 'CXX_SOURCES',
13 '.cc' : 'CXX_SOURCES',
14 '.m' : 'OBJC_SOURCES',
15 '.mm' : 'OBJCXX_SOURCES'
16 }.get(extension, None)
17
18class CommandParser:
19 def __init__(self):
20 self.breakpoints = []
21
22 def parse_one_command(self, line):
23 parts = line.split('//%')
Sean Callanand950fa72014-10-17 00:39:37 +000024
25 command = None
26 new_breakpoint = True
27
28 if len(parts) == 2:
29 command = parts[1].strip() # take off whitespace
30 new_breakpoint = parts[0].strip() != ""
31
32 return (command, new_breakpoint)
Sean Callanan816cb3e2014-10-16 23:15:22 +000033
34 def parse_source_files(self, source_files):
35 for source_file in source_files:
36 file_handle = open(source_file)
37 lines = file_handle.readlines()
38 line_number = 0
Sean Callanand950fa72014-10-17 00:39:37 +000039 current_breakpoint = None # non-NULL means we're looking through whitespace to find additional commands
Sean Callanan816cb3e2014-10-16 23:15:22 +000040 for line in lines:
41 line_number = line_number + 1 # 1-based, so we do this first
Sean Callanand950fa72014-10-17 00:39:37 +000042 (command, new_breakpoint) = self.parse_one_command(line)
43
44 if new_breakpoint:
45 current_breakpoint = None
46
Sean Callanan816cb3e2014-10-16 23:15:22 +000047 if command != None:
Sean Callanand950fa72014-10-17 00:39:37 +000048 if current_breakpoint == None:
49 current_breakpoint = {}
50 current_breakpoint['file_name'] = source_file
51 current_breakpoint['line_number'] = line_number
52 current_breakpoint['command'] = command
53 self.breakpoints.append(current_breakpoint)
54 else:
55 current_breakpoint['command'] = current_breakpoint['command'] + "\n" + command
56 print self.breakpoints
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
68def BuildMakefile(mydir):
69 categories = {}
70
71 for f in os.listdir(os.getcwd()):
72 t = source_type(f)
73 if t:
74 if t in categories.keys():
75 categories[t].append(f)
76 else:
77 categories[t] = [f]
78
79 makefile = open("Makefile", 'w+')
80
81 level = os.sep.join([".."] * len(mydir.split(os.sep))) + os.sep + "make"
82
83 makefile.write("LEVEL = " + level + "\n")
84
85 for t in categories.keys():
86 line = t + " := " + " ".join(categories[t])
87 makefile.write(line + "\n")
88
89 if ('OBJCXX_SOURCES' in categories.keys()) or ('OBJC_SOURCES' in categories.keys()):
90 makefile.write("LDFLAGS = $(CFLAGS) -lobjc -framework Foundation\n")
91
92 if ('CXX_SOURCES' in categories.keys()):
Enrico Granata4bd54a12014-10-22 20:33:34 +000093 makefile.write("CXXFLAGS += -std=c++11\n")
Sean Callanan816cb3e2014-10-16 23:15:22 +000094
95 makefile.write("include $(LEVEL)/Makefile.rules\n")
96 makefile.flush()
97 makefile.close()
98
99def CleanMakefile():
100 if (os.path.isfile("Makefile")):
101 os.unlink("Makefile")
102
103class InlineTest(TestBase):
104 # Internal implementation
105
Ed Mastee1b25362014-10-23 15:21:45 +0000106 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
Sean Callanan816cb3e2014-10-16 23:15:22 +0000107 def buildDsymWithImplicitMakefile(self):
108 BuildMakefile(self.mydir)
109 self.buildDsym()
110
111 def buildDwarfWithImplicitMakefile(self):
112 BuildMakefile(self.mydir)
113 self.buildDwarf()
114
Ed Mastee1b25362014-10-23 15:21:45 +0000115 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
Sean Callanan816cb3e2014-10-16 23:15:22 +0000116 def test_with_dsym(self):
117 self.buildDsymWithImplicitMakefile()
118 self.do_test()
119
120 def test_with_dwarf(self):
121 self.buildDwarfWithImplicitMakefile()
122 self.do_test()
123
124 def execute_user_command(self, __command):
125 exec __command in globals(), locals()
126
127 def do_test(self):
128 exe_name = "a.out"
129 exe = os.path.join(os.getcwd(), exe_name)
130 source_files = [ f for f in os.listdir(os.getcwd()) if source_type(f) ]
131 target = self.dbg.CreateTarget(exe)
132
133 parser = CommandParser()
134 parser.parse_source_files(source_files)
135 parser.set_breakpoints(target)
136
137 process = target.LaunchSimple(None, None, os.getcwd())
138
139 while lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint):
140 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)
141 breakpoint_id = thread.GetStopReasonDataAtIndex (0)
142 parser.handle_breakpoint(self, breakpoint_id)
143 process.Continue()
144
145 @classmethod
146 def classCleanup(cls):
147 CleanMakefile()
148
149 # Utilities for testcases
150
151 def check_expression (self, expression, expected_result, use_summary = True):
152 value = self.frame().EvaluateExpression (expression)
153 self.assertTrue(value.IsValid(), expression+"returned a valid value")
154 if self.TraceOn():
155 print value.GetSummary()
156 print value.GetValue()
157 if use_summary:
158 answer = value.GetSummary()
159 else:
160 answer = value.GetValue()
161 report_str = "%s expected: %s got: %s"%(expression, expected_result, answer)
162 self.assertTrue(answer == expected_result, report_str)
163
164def MakeInlineTest(__file, __globals):
165 # Derive the test name from the current file name
166 file_basename = os.path.basename(__file)
167 InlineTest.mydir = TestBase.compute_mydir(__file)
168
169 test_name, _ = os.path.splitext(file_basename)
170 # Build the test case
171 test = new.classobj(test_name, (InlineTest,), {})
172 test.name = test_name
173 # Add the test case to the globals, and hide InlineTest
174 __globals.update({test_name : test})
Sean Callanan816cb3e2014-10-16 23:15:22 +0000175
176