Index: debuginfo-tests/dexter/Commands.md =================================================================== --- debuginfo-tests/dexter/Commands.md +++ debuginfo-tests/dexter/Commands.md @@ -178,7 +178,7 @@ ---- ## DexLimitSteps DexLimitSteps([expr, *values][, **from_line=1][,**to_line=Max] - [,**on_line]) + [,**on_line][,**is_one_shot=False]) Args: expr (str): variable or value to compare. @@ -191,12 +191,14 @@ to_line (int): Define the end of the limited step range. on_line (int): Define a range with length 1 starting and ending on the same line. + is_one_shot (bool): If set to True the command only triggers once. ### Description Define a limited stepping range that may be predicated on a condition. When the leading line is stepped on and any condition '(expr) == (values[n])' is true or there are no conditions, set a range of temporary breakpoints within the test -file defined by the range 'from_line' and 'to_line' or 'on_line'. +file defined by the range 'from_line' and 'to_line' or 'on_line'. If +is_one_shot is true this only ever happens once. The condition is only evaluated on the line 'from_line' or 'on_line'. If the condition is not true at the start of the range, or that line is never stepped Index: debuginfo-tests/dexter/dex/command/commands/DexLimitSteps.py =================================================================== --- debuginfo-tests/dexter/dex/command/commands/DexLimitSteps.py +++ debuginfo-tests/dexter/dex/command/commands/DexLimitSteps.py @@ -27,6 +27,7 @@ except KeyError: self.from_line = kwargs.pop('from_line', 1) self.to_line = kwargs.pop('to_line', 999999) + self.is_one_shot = kwargs.pop('is_one_shot', False) if kwargs: raise TypeError('unexpected named args: {}'.format( ', '.join(kwargs))) Index: debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ConditionalController.py =================================================================== --- debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ConditionalController.py +++ debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ConditionalController.py @@ -33,12 +33,14 @@ against `values`. """ - def __init__(self, expression: str, path: str, range_from: int, range_to: int, values: list): + def __init__(self, expression: str, path: str, range_from: int, range_to: int, + values: list, is_one_shot: bool): self.expression = expression self.path = path self.range_from = range_from self.range_to = range_to self.conditional_values = values + self.is_one_shot = is_one_shot def has_conditions(self): return self.expression != None @@ -76,8 +78,10 @@ lc.path, lc.from_line, lc.to_line, - lc.values) + lc.values, + lc.is_one_shot) self._bp_ranges.append(bpr) + except KeyError: raise DebuggerException('Missing DexLimitSteps commands, cannot conditionally step.') @@ -129,6 +133,9 @@ # This is a trailing bp. Mark it for removal. bp_to_delete.append(bp_id) continue + if bpr.is_one_shot: + bp_to_delete.append(bp_id) + del self._leading_bp_handles[bp_id] # Add a range of trailing breakpoints covering the lines # requested in the DexLimitSteps command. Ignore first line as # that's covered by the leading bp we just hit and include the @@ -136,7 +143,7 @@ for line in range(bpr.range_from + 1, bpr.range_to + 1): self.debugger.add_breakpoint(bpr.path, line) - # Remove any trailing breakpoints we just hit. + # Remove any trailing or one shot breakpoints we just hit. for bp_id in bp_to_delete: self.debugger.delete_breakpoint(bp_id) Index: debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/one_shot.cpp =================================================================== --- /dev/null +++ debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/one_shot.cpp @@ -0,0 +1,21 @@ +// Purpose: +// Test that \DexLimitSteps keyword argument is_one_shot prevents the +// breakpoints being set more than once. +// +// REQUIRES: system-linux +// +// RUN: %dexter_regression_test -- %s | FileCheck %s +// CHECK: one_shot.cpp + +int a; +int main() { + for (int i = 0; i < 2; i++) { + a = i; // DexLabel('check') + } + return 0; +} + +//// Unconditionally limit dexter's view of the program to 'on_line' and check +//// for i=0. The test will fail if dexter sees any other value for test. +// DexLimitSteps(is_one_shot=True, on_line='check') +// DexExpectWatchValue('i', '0')