Files
swift-mirror/utils/lldb/lldbCheckExpect.py
Daniel Duan 3dfc40898c [NFC] Remove Python 2 imports from __future__ (#42086)
The `__future__` we relied on is now,  where the 3 specific things are
all included [since Python 3.0](https://docs.python.org/3/library/__future__.html):

* absolute_import
* print_function
* unicode_literals
* division

These import statements are no-ops and are no longer necessary.
2022-04-13 14:01:30 -07:00

101 lines
3.1 KiB
Python

'''
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')