blob: 494b650fc4d0e47a725b3a95188dce957b4805e2 [file] [log] [blame]
'''
lldbCheckExpect.py
This is a driver script for testing lldb expression evaluation. It installs a
breakpoint command which executes tests inserted by the instrumentation pass,
and launches a target.
To use it, compile a target program with these flags:
-g -Xfrontend -debugger-testing-transform
Make sure the swift standard library is built with debug info. Then, launch
swift-lldb with "-o path/to/this/script -- <program> [<args>]". There is a
utility available in SWIFT_BINARY_DIR/bin/lldb-check-expect which automates
this, e.g:
./bin/lldb-check-expect <program>
...
Evaluating check-expect in closure #2 () -> () in CAPITest.swapTwoValues
Checked variable: a
Expected value : 98
Actual value : ...
'''
def unwrap(s):
'''
Strip non-essential character sequences from a string.
>>> unwrap('(String) value = "42\\\\n"')
'42'
>>> unwrap('(Int) $R0 = 42')
'42'
>>> unwrap('\\\\"foo\\"')
'foo'
>>> unwrap('foo\\nbar')
'foo\\nbar'
>>> unwrap(' foo ')
'foo'
'''
s = s[s.find('=') + 1:]
s = s.lstrip(' "')
s = s.rstrip('"')
if s.endswith('\\n'):
s = s[:-2]
if s.endswith('\\"'):
s = s[:-2]
if s.startswith('\\"'):
s = s[2:]
s = s.replace('\\n', '\n')
s = s.strip()
return s
def on_check_expect(frame, bp_loc, session):
parent_frame = frame.get_parent_frame()
parent_name = parent_frame.GetFunctionName()
print "Evaluating check-expect in", parent_name
# Note: If we fail to stringify the arguments in the check-expect frame,
# the standard library has probably not been compiled with debug info.
wrapped_var_name, wrapped_expected_value = map(str, frame.arguments)
var_name = unwrap(wrapped_var_name)
expected_value = unwrap(wrapped_expected_value)
# Evaluate the variable in the parent frame of the check-expect.
frame.thread.SetSelectedFrame(1)
expr_result = parent_frame.FindVariable(var_name).GetObjectDescription()
eval_result = unwrap(str(expr_result))
print " Checked variable:", var_name
print " Expected value :", expected_value
print " Actual value :", eval_result
if eval_result == expected_value:
# Do not stop execution.
return False
print "Found a possible expression evaluation failure."
for i, (c1, c2) in enumerate(zip(expected_value, eval_result)):
if c1 == c2:
continue
print " -> Character difference at index", i
print " -> Expected", c1, "but found", c2
break
else:
print " -> Expected string has length", len(expected_value)
print " -> Actual string has length", len(eval_result)
return True
def __lldb_init_module(debugger, internal_dict):
debugger.HandleCommand('breakpoint set -n _debuggerTestingCheckExpect '
'--breakpoint-name check_expect_bkpt')
debugger.HandleCommand('breakpoint command add --python-function '
'lldbCheckExpect.on_check_expect '
'--stop-on-error true check_expect_bkpt')
debugger.HandleCommand('run')