1 from __future__
import print_function
2 from __future__
import absolute_import
12 from .lldbtest
import *
13 from . import configuration
14 from . import lldbutil
15 from .decorators
import *
17 def source_type(filename
):
18 _
, extension
= os
.path
.splitext(filename
)
21 '.cpp': 'CXX_SOURCES',
22 '.cxx': 'CXX_SOURCES',
25 '.mm': 'OBJCXX_SOURCES'
26 }.get(extension
, None)
34 def parse_one_command(self
, line
):
35 parts
= line
.split('//%')
41 command
= parts
[1].strip() # take off whitespace
42 new_breakpoint
= parts
[0].strip() != ""
44 return (command
, new_breakpoint
)
46 def parse_source_files(self
, source_files
):
47 for source_file
in source_files
:
48 file_handle
= io
.open(source_file
, encoding
='utf-8')
49 lines
= file_handle
.readlines()
51 # non-NULL means we're looking through whitespace to find
53 current_breakpoint
= None
55 line_number
= line_number
+ 1 # 1-based, so we do this first
56 (command
, new_breakpoint
) = self
.parse_one_command(line
)
59 current_breakpoint
= None
61 if command
is not None:
62 if current_breakpoint
is None:
63 current_breakpoint
= {}
64 current_breakpoint
['file_name'] = source_file
65 current_breakpoint
['line_number'] = line_number
66 current_breakpoint
['command'] = command
67 self
.breakpoints
.append(current_breakpoint
)
69 current_breakpoint
['command'] = current_breakpoint
[
70 'command'] + "\n" + command
72 def set_breakpoints(self
, target
):
73 for breakpoint
in self
.breakpoints
:
74 breakpoint
['breakpoint'] = target
.BreakpointCreateByLocation(
75 breakpoint
['file_name'], breakpoint
['line_number'])
77 def handle_breakpoint(self
, test
, breakpoint_id
):
78 for breakpoint
in self
.breakpoints
:
79 if breakpoint
['breakpoint'].GetID() == breakpoint_id
:
80 test
.execute_user_command(breakpoint
['command'])
84 class InlineTest(TestBase
):
85 # Internal implementation
87 def BuildMakefile(self
):
88 makefilePath
= self
.getBuildArtifact("Makefile")
89 if os
.path
.exists(makefilePath
):
94 for f
in os
.listdir(self
.getSourceDir()):
97 if t
in list(categories
.keys()):
98 categories
[t
].append(f
)
102 makefile
= open(makefilePath
, 'w+')
104 for t
in list(categories
.keys()):
105 line
= t
+ " := " + " ".join(categories
[t
])
106 makefile
.write(line
+ "\n")
108 if ('OBJCXX_SOURCES' in list(categories
.keys())) or (
109 'OBJC_SOURCES' in list(categories
.keys())):
111 "LDFLAGS = $(CFLAGS) -lobjc -framework Foundation\n")
113 if ('CXX_SOURCES' in list(categories
.keys())):
114 makefile
.write("CXXFLAGS += -std=c++11\n")
116 makefile
.write("include Makefile.rules\n")
117 makefile
.write("\ncleanup:\n\trm -f Makefile *.d\n\n")
126 def execute_user_command(self
, __command
):
127 exec(__command
, globals(), locals())
130 exe
= self
.getBuildArtifact("a.out")
131 source_files
= [f
for f
in os
.listdir(self
.getSourceDir())
133 target
= self
.dbg
.CreateTarget(exe
)
135 parser
= CommandParser()
136 parser
.parse_source_files(source_files
)
137 parser
.set_breakpoints(target
)
139 process
= target
.LaunchSimple(None, None, self
.get_process_working_directory())
142 while lldbutil
.get_stopped_thread(process
, lldb
.eStopReasonBreakpoint
):
144 thread
= lldbutil
.get_stopped_thread(
145 process
, lldb
.eStopReasonBreakpoint
)
146 breakpoint_id
= thread
.GetStopReasonDataAtIndex(0)
147 parser
.handle_breakpoint(self
, breakpoint_id
)
150 self
.assertTrue(hit_breakpoints
> 0,
151 "inline test did not hit a single breakpoint")
152 # Either the process exited or the stepping plan is complete.
153 self
.assertTrue(process
.GetState() in [lldb
.eStateStopped
,
157 # Utilities for testcases
159 def check_expression(self
, expression
, expected_result
, use_summary
=True):
160 value
= self
.frame().EvaluateExpression(expression
)
161 self
.assertTrue(value
.IsValid(), expression
+ "returned a valid value")
163 print(value
.GetSummary())
164 print(value
.GetValue())
166 answer
= value
.GetSummary()
168 answer
= value
.GetValue()
169 report_str
= "%s expected: %s got: %s" % (
170 expression
, expected_result
, answer
)
171 self
.assertTrue(answer
== expected_result
, report_str
)
174 def ApplyDecoratorsToFunction(func
, decorators
):
176 if isinstance(decorators
, list):
177 for decorator
in decorators
:
179 elif hasattr(decorators
, '__call__'):
180 tmp
= decorators(tmp
)
184 def MakeInlineTest(__file
, __globals
, decorators
=None):
185 # Adjust the filename if it ends in .pyc. We want filenames to
186 # reflect the source python file, not the compiled variant.
187 if __file
is not None and __file
.endswith(".pyc"):
188 # Strip the trailing "c"
189 __file
= __file
[0:-1]
191 # Derive the test name from the current file name
192 file_basename
= os
.path
.basename(__file
)
194 test_name
, _
= os
.path
.splitext(file_basename
)
196 test_func
= ApplyDecoratorsToFunction(InlineTest
._test
, decorators
)
197 # Build the test case
198 test_class
= type(test_name
, (InlineTest
,), dict(test
=test_func
, name
=test_name
))
200 # Add the test case to the globals, and hide InlineTest
201 __globals
.update({test_name
: test_class
})
203 # Keep track of the original test filename so we report it
204 # correctly in test results.
205 test_class
.test_filename
= __file
206 test_class
.mydir
= TestBase
.compute_mydir(__file
)