]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - packages/Python/lldbsuite/test/lldbinline.py
Vendor import of lldb trunk r256945:
[FreeBSD/FreeBSD.git] / packages / Python / lldbsuite / test / lldbinline.py
1 from __future__ import print_function
2 from __future__ import absolute_import
3
4 # System modules
5 import os
6 import sys
7
8 # Third-party modules
9
10 # LLDB modules
11 import lldb
12 from .lldbtest import *
13 from . import lldbutil
14
15 def source_type(filename):
16     _, extension = os.path.splitext(filename)
17     return {
18         '.c' : 'C_SOURCES',
19         '.cpp' : 'CXX_SOURCES',
20         '.cxx' : 'CXX_SOURCES',
21         '.cc' : 'CXX_SOURCES',
22         '.m' : 'OBJC_SOURCES',
23         '.mm' : 'OBJCXX_SOURCES'
24     }.get(extension, None)
25
26 class CommandParser:
27     def __init__(self):
28         self.breakpoints = []
29
30     def parse_one_command(self, line):
31         parts = line.split('//%')
32
33         command = None
34         new_breakpoint = True
35
36         if len(parts) == 2:
37             command = parts[1].strip() # take off whitespace
38             new_breakpoint = parts[0].strip() != ""
39
40         return (command, new_breakpoint)
41
42     def parse_source_files(self, source_files):
43         for source_file in source_files:
44             file_handle = open(source_file)
45             lines = file_handle.readlines()
46             line_number = 0
47             current_breakpoint = None # non-NULL means we're looking through whitespace to find additional commands
48             for line in lines:
49                 line_number = line_number + 1 # 1-based, so we do this first
50                 (command, new_breakpoint) = self.parse_one_command(line)
51
52                 if new_breakpoint:
53                     current_breakpoint = None
54
55                 if command != None:
56                     if current_breakpoint == None:
57                         current_breakpoint = {}
58                         current_breakpoint['file_name'] = source_file
59                         current_breakpoint['line_number'] = line_number
60                         current_breakpoint['command'] = command
61                         self.breakpoints.append(current_breakpoint)
62                     else:
63                         current_breakpoint['command'] = current_breakpoint['command'] + "\n" + command
64
65     def set_breakpoints(self, target):
66         for breakpoint in self.breakpoints:
67             breakpoint['breakpoint'] = target.BreakpointCreateByLocation(breakpoint['file_name'], breakpoint['line_number'])
68
69     def handle_breakpoint(self, test, breakpoint_id):
70         for breakpoint in self.breakpoints:
71             if breakpoint['breakpoint'].GetID() == breakpoint_id:
72                 test.execute_user_command(breakpoint['command'])
73                 return
74
75 class InlineTest(TestBase):
76     # Internal implementation
77
78     def getRerunArgs(self):
79         # The -N option says to NOT run a if it matches the option argument, so
80         # if we are using dSYM we say to NOT run dwarf (-N dwarf) and vice versa.
81         if self.using_dsym is None:
82             # The test was skipped altogether.
83             return ""
84         elif self.using_dsym:
85             return "-N dwarf %s" % (self.mydir)
86         else:
87             return "-N dsym %s" % (self.mydir)
88         
89     def BuildMakefile(self):
90         if os.path.exists("Makefile"):
91             return
92
93         categories = {}
94
95         for f in os.listdir(os.getcwd()):
96             t = source_type(f)
97             if t:
98                 if t in list(categories.keys()):
99                     categories[t].append(f)
100                 else:
101                     categories[t] = [f]
102
103         makefile = open("Makefile", 'w+')
104
105         level = os.sep.join([".."] * len(self.mydir.split(os.sep))) + os.sep + "make"
106
107         makefile.write("LEVEL = " + level + "\n")
108
109         for t in list(categories.keys()):
110             line = t + " := " + " ".join(categories[t])
111             makefile.write(line + "\n")
112
113         if ('OBJCXX_SOURCES' in list(categories.keys())) or ('OBJC_SOURCES' in list(categories.keys())):
114             makefile.write("LDFLAGS = $(CFLAGS) -lobjc -framework Foundation\n")
115
116         if ('CXX_SOURCES' in list(categories.keys())):
117             makefile.write("CXXFLAGS += -std=c++11\n")
118
119         makefile.write("include $(LEVEL)/Makefile.rules\n")
120         makefile.flush()
121         makefile.close()
122
123
124     @skipUnlessDarwin
125     def __test_with_dsym(self):
126         self.using_dsym = True
127         self.BuildMakefile()
128         self.buildDsym()
129         self.do_test()
130
131     def __test_with_dwarf(self):
132         self.using_dsym = False
133         self.BuildMakefile()
134         self.buildDwarf()
135         self.do_test()
136
137     def __test_with_dwo(self):
138         self.using_dsym = False
139         self.BuildMakefile()
140         self.buildDwo()
141         self.do_test()
142
143     def execute_user_command(self, __command):
144         exec(__command, globals(), locals())
145
146     def do_test(self):
147         exe_name = "a.out"
148         exe = os.path.join(os.getcwd(), exe_name)
149         source_files = [ f for f in os.listdir(os.getcwd()) if source_type(f) ]
150         target = self.dbg.CreateTarget(exe)
151
152         parser = CommandParser()
153         parser.parse_source_files(source_files)
154         parser.set_breakpoints(target)
155
156         process = target.LaunchSimple(None, None, os.getcwd())
157
158         while lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint):
159             thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)
160             breakpoint_id = thread.GetStopReasonDataAtIndex (0)
161             parser.handle_breakpoint(self, breakpoint_id)
162             process.Continue()
163
164
165     # Utilities for testcases
166
167     def check_expression (self, expression, expected_result, use_summary = True):
168         value = self.frame().EvaluateExpression (expression)
169         self.assertTrue(value.IsValid(), expression+"returned a valid value")
170         if self.TraceOn():
171             print(value.GetSummary())
172             print(value.GetValue())
173         if use_summary:
174             answer = value.GetSummary()
175         else:
176             answer = value.GetValue()
177         report_str = "%s expected: %s got: %s"%(expression, expected_result, answer)
178         self.assertTrue(answer == expected_result, report_str)
179
180 def ApplyDecoratorsToFunction(func, decorators):
181     tmp = func
182     if type(decorators) == list:
183         for decorator in decorators:
184             tmp = decorator(tmp)
185     elif hasattr(decorators, '__call__'):
186         tmp = decorators(tmp)
187     return tmp
188     
189
190 def MakeInlineTest(__file, __globals, decorators=None):
191     # Derive the test name from the current file name
192     file_basename = os.path.basename(__file)
193     InlineTest.mydir = TestBase.compute_mydir(__file)
194
195     test_name, _ = os.path.splitext(file_basename)
196     # Build the test case 
197     test = type(test_name, (InlineTest,), {'using_dsym': None})
198     test.name = test_name
199
200     test.test_with_dsym = ApplyDecoratorsToFunction(test._InlineTest__test_with_dsym, decorators)
201     test.test_with_dwarf = ApplyDecoratorsToFunction(test._InlineTest__test_with_dwarf, decorators)
202     test.test_with_dwo = ApplyDecoratorsToFunction(test._InlineTest__test_with_dwo, decorators)
203
204     # Add the test case to the globals, and hide InlineTest
205     __globals.update({test_name : test})
206
207     # Store the name of the originating file.o
208     test.test_filename = __file
209     return test
210