[Dexter] Allow DexUnreachable in supplementary .dex files

DexUnreachable is a useful tool for specifying that lines shouldn't be
stepped on. Right now they have to be placed in the source file; lets allow
them to be placed instead in a detached .dex file, by adding on_line and
line-range keyword arguments to the command.

Differential Revision: https://reviews.llvm.org/D115449
This commit is contained in:
Jeremy Morse 2022-01-10 12:11:15 +00:00
parent c22fb4b521
commit 0f92c113a3
7 changed files with 98 additions and 4 deletions

View File

@ -170,10 +170,12 @@ sequentially.
---
## DexUnreachable
DexUnreachable()
DexUnreachable([, **from_line=1][,**to_line=Max][,**on_line])
### Description
Expect the source line this is found on will never be stepped on to.
Expect the source line this is found on will never be stepped on to. If either
'on_line' or both 'from_line' and 'to_line' are specified, checks that the
specified line(s) are not stepped on.
### Heuristic
[TODO]

View File

@ -18,7 +18,21 @@ class DexUnreachable(CommandBase):
See Commands.md for more info.
"""
def __init(self):
def __init__(self, *args, **kwargs):
if len(args) != 0:
raise TypeError("DexUnreachable takes no positional arguments")
if 'on_line' in kwargs:
on_line = kwargs.pop('on_line')
self._from_line = on_line
self._to_line = on_line
elif 'from_line' in kwargs and 'to_line' in kwargs:
self._from_line = kwargs.pop('from_line')
self._to_line = kwargs.pop('to_line')
elif 'from_line' in kwargs or 'to_line' in kwargs:
raise TypeError("Must provide both from_line and to_line to DexUnreachable")
if len(kwargs) > 0:
raise TypeError("Unexpected kwargs {}".format(kwargs.keys()))
super(DexUnreachable, self).__init__()
pass

View File

@ -18,6 +18,15 @@ def in_source_file(source_files, step_info):
return any(os.path.samefile(step_info.current_location.path, f) \
for f in source_files)
def have_hit_line(watch, loc):
if hasattr(watch, '_on_line'):
return watch._on_line == loc.lineno
elif hasattr(watch, '_from_line'):
return watch._from_line <= loc.lineno and watch._to_line >= loc.lineno
elif watch.lineno == loc.lineno:
return True
return False
def update_step_watches(step_info, watches, commands):
watch_cmds = ['DexUnreachable', 'DexExpectStepOrder']
towatch = chain.from_iterable(commands[x]
@ -30,7 +39,7 @@ def update_step_watches(step_info, watches, commands):
if (loc.path != None
and os.path.exists(loc.path)
and os.path.samefile(watch.path, loc.path)
and watch.lineno == loc.lineno):
and have_hit_line(watch, loc)):
result = watch.eval(step_info)
step_info.watches.update(result)
break

View File

@ -0,0 +1,17 @@
// Purpose:
// Check that \DexUnreachable correctly applies a penalty if the command
// line is stepped on.
//
// UNSUPPORTED: system-darwin
//
//
// RUN: not %dexter_regression_test -- %s | FileCheck %s
// CHECK: unreachable_line_range.cpp:
int
main()
{ // DexLabel('begin')
return 1;
} // DexLabel('end')
// DexUnreachable(from_line=ref('begin'), to_line=ref('end'))

View File

@ -0,0 +1,17 @@
// Purpose:
// Check that \DexUnreachable correctly applies a penalty if the command
// line is stepped on.
//
// UNSUPPORTED: system-darwin
//
//
// RUN: not %dexter_regression_test -- %s | FileCheck %s
// CHECK: unreachable_on_line.cpp:
int
main()
{
return 1; // DexLabel('this_one')
}
// DexUnreachable(on_line=ref('this_one'))

View File

@ -0,0 +1,17 @@
// Purpose:
// Check that \DexUnreachable doesn't trigger on the line it's specified
// on, if it has a specifier indicating which lines should be unreachable.
//
// UNSUPPORTED: system-darwin
//
// RUN: %dexter_regression_test -- %s | FileCheck %s
// CHECK: unreachable_not_cmd_lineno.cpp:
int main(int argc, char **argv)
{
if (argc != 1)
return 1; // DexLabel('this_one')
else
return 0; // DexUnreachable(on_line=ref('this_one')) DexUnreachable(from_line=ref('this_one'), to_line=ref('this_one'))
}

View File

@ -0,0 +1,18 @@
// Purpose:
// Check that \DexUnreachable has no effect if the command line is never
// stepped on.
//
// UNSUPPORTED: system-darwin
//
// RUN: %dexter_regression_test -- %s | FileCheck %s
// CHECK: unreachable_on_line.cpp:
int main()
{
return 0;
return 1; // DexLabel('this_one')
}
// DexUnreachable(on_line=ref('this_one'))
// DexUnreachable(from_line=ref('this_one'), to_line=ref('this_one'))