Revert "[Dexter] Add DexLimitSteps command and ConditionalController"
authorTom Weaver <Tom.Weaver@Sony.com>
Wed, 3 Jun 2020 11:28:26 +0000 (12:28 +0100)
committerTom Weaver <Tom.Weaver@Sony.com>
Wed, 3 Jun 2020 11:28:26 +0000 (12:28 +0100)
This reverts commit 81e836a5a675f6a3d9d35560fddbbb87fdf66201.

Accidentally committed a diff file.

18 files changed:
d.diff [deleted file]
debuginfo-tests/dexter/Commands.md
debuginfo-tests/dexter/dex/command/ParseCommand.py
debuginfo-tests/dexter/dex/command/commands/DexLimitSteps.py [deleted file]
debuginfo-tests/dexter/dex/debugger/DebuggerBase.py
debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ConditionalController.py [deleted file]
debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ControllerHelpers.py [deleted file]
debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DebuggerControllerBase.py
debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DefaultController.py
debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py
debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py
debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py
debuginfo-tests/dexter/dex/tools/test/Tool.py
debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_check_json_step_count.cpp [deleted file]
debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_expect_loop.cpp [deleted file]
debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_expect_value.cpp [deleted file]
debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_overlapping_ranges.cpp [deleted file]
debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_same_line_conditional.cpp [deleted file]

diff --git a/d.diff b/d.diff
deleted file mode 100644 (file)
index ffa4caa..0000000
--- a/d.diff
+++ /dev/null
@@ -1,712 +0,0 @@
-diff --git a/debuginfo-tests/dexter/Commands.md b/debuginfo-tests/dexter/Commands.md
-index c30a0d7214c..2e2fecfed92 100644
---- a/debuginfo-tests/dexter/Commands.md
-+++ b/debuginfo-tests/dexter/Commands.md
-@@ -173,6 +173,34 @@ Expect the source line this is found on will never be stepped on to.
- [TODO]
-+----
-+## DexLimitSteps
-+    DexLimitSteps(expr, *values [, **from_line=1],[,**to_line=Max]
-+                  [,**on_line])
-+
-+    Args:
-+        expr (str): variable or value to compare.
-+
-+    Arg list:
-+        values (str): At least one potential value the expr may evaluate to.
-+
-+    Keyword args:
-+        from_line (int): Define the start of the limited step range.
-+        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.
-+
-+### Description
-+Define a limited stepping range that is predicated on a condition. When
-+'(expr) == (values[n])', set a range of temporary, unconditional break points within
-+the test file defined by the range from_line and to_line or on_line.
-+
-+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, the whole range is ignored.
-+
-+DexLimitSteps commands are useful for reducing the amount of steps gathered in
-+large test cases that would normally take much longer to complete.
-+
- ----
- ## DexLabel
-     DexLabel(name)
-diff --git a/debuginfo-tests/dexter/dex/command/ParseCommand.py b/debuginfo-tests/dexter/dex/command/ParseCommand.py
-index 4cc9ae12592..8246ea9e3cf 100644
---- a/debuginfo-tests/dexter/dex/command/ParseCommand.py
-+++ b/debuginfo-tests/dexter/dex/command/ParseCommand.py
-@@ -24,6 +24,7 @@ from dex.command.commands.DexExpectStepOrder import DexExpectStepOrder
- from dex.command.commands.DexExpectWatchType import DexExpectWatchType
- from dex.command.commands.DexExpectWatchValue import DexExpectWatchValue
- from dex.command.commands.DexLabel import DexLabel
-+from dex.command.commands.DexLimitSteps import DexLimitSteps
- from dex.command.commands.DexUnreachable import DexUnreachable
- from dex.command.commands.DexWatch import DexWatch
- from dex.utils import Timer
-@@ -42,6 +43,7 @@ def _get_valid_commands():
-       DexExpectWatchType.get_name() : DexExpectWatchType,
-       DexExpectWatchValue.get_name() : DexExpectWatchValue,
-       DexLabel.get_name() : DexLabel,
-+      DexLimitSteps.get_name() : DexLimitSteps,
-       DexUnreachable.get_name() : DexUnreachable,
-       DexWatch.get_name() : DexWatch
-     }
-diff --git a/debuginfo-tests/dexter/dex/command/commands/DexLimitSteps.py b/debuginfo-tests/dexter/dex/command/commands/DexLimitSteps.py
-new file mode 100644
-index 00000000000..d66401b5599
---- /dev/null
-+++ b/debuginfo-tests/dexter/dex/command/commands/DexLimitSteps.py
-@@ -0,0 +1,54 @@
-+# DExTer : Debugging Experience Tester
-+# ~~~~~~   ~         ~~         ~   ~~
-+#
-+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-+# See https://llvm.org/LICENSE.txt for license information.
-+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-+"""A Command that enables test writers to specify a limited number of break
-+points using an start condition and range.
-+"""
-+
-+from dex.command.CommandBase import CommandBase
-+
-+class DexLimitSteps(CommandBase):
-+    def __init__(self, *args, **kwargs):
-+        self.expression = args[0]
-+        self.values = [str(arg) for arg in args[1:]]
-+        try:
-+            on_line = kwargs.pop('on_line')
-+            self.from_line = on_line
-+            self.to_line = on_line
-+        except KeyError:
-+            self.from_line = kwargs.pop('from_line', 1)
-+            self.to_line = kwargs.pop('to_line', 999999)
-+        if kwargs:
-+            raise TypeError('unexpected named args: {}'.format(
-+                ', '.join(kwargs)))
-+        super(DexLimitSteps, self).__init__()
-+
-+    def resolve_label(self, label_line_pair):
-+        label, lineno = label_line_pair
-+        if isinstance(self.from_line, str):
-+            if self.from_line == label:
-+                self.from_line = lineno
-+        if isinstance(self.to_line, str):
-+            if self.to_line == label:
-+                self.to_line = lineno
-+
-+    def has_labels(self):
-+        return len(self.get_label_args()) > 0
-+
-+    def get_label_args(self):
-+        return [label for label in (self.from_line, self.to_line)
-+                      if isinstance(label, str)]
-+
-+    def eval(self):
-+        raise NotImplementedError('DexLimitSteps commands cannot be evaled.')
-+
-+    @staticmethod
-+    def get_name():
-+        return __class__.__name__
-+
-+    @staticmethod
-+    def get_subcommands() -> dict:
-+        return None
-diff --git a/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py b/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py
-index 2261396b94b..12f4f4ab7a0 100644
---- a/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py
-+++ b/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py
-@@ -120,6 +120,14 @@ class DebuggerBase(object, metaclass=abc.ABCMeta):
-     def add_breakpoint(self, file_, line):
-         pass
-+    @abc.abstractmethod
-+    def add_conditional_breakpoint(self, file_, line, condition):
-+        pass
-+
-+    @abc.abstractmethod
-+    def delete_conditional_breakpoint(self, file_, line, condition):
-+        pass
-+
-     @abc.abstractmethod
-     def launch(self):
-         pass
-diff --git a/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ConditionalController.py b/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ConditionalController.py
-new file mode 100644
-index 00000000000..4e4327b53f8
---- /dev/null
-+++ b/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ConditionalController.py
-@@ -0,0 +1,127 @@
-+# DExTer : Debugging Experience Tester
-+# ~~~~~~   ~         ~~         ~   ~~
-+#
-+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-+# See https://llvm.org/LICENSE.txt for license information.
-+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-+"""Conditional Controller Class for DExTer.-"""
-+
-+
-+import os
-+import time
-+from collections import defaultdict
-+from itertools import chain
-+
-+from dex.debugger.DebuggerControllers.ControllerHelpers import in_source_file, update_step_watches
-+from dex.debugger.DebuggerControllers.DebuggerControllerBase import DebuggerControllerBase
-+from dex.debugger.DebuggerBase import DebuggerBase
-+from dex.utils.Exceptions import DebuggerException
-+
-+
-+class ConditionalBpRange:
-+    """Represents a conditional range of breakpoints within a source file descending from
-+    one line to another."""
-+
-+    def __init__(self, expression: str, path: str, range_from: int, range_to: int, values: list):
-+        self.expression = expression
-+        self.path = path
-+        self.range_from = range_from
-+        self.range_to = range_to
-+        self.conditional_values = values
-+
-+    def get_conditional_expression_list(self):
-+        conditional_list = []
-+        for value in self.conditional_values:
-+            # (<expression>) == (<value>)
-+            conditional_expression = '({}) == ({})'.format(self.expression, value)
-+            conditional_list.append(conditional_expression)
-+        return conditional_list
-+
-+
-+class ConditionalController(DebuggerControllerBase):
-+    def __init__(self, context, step_collection):
-+      self.context = context
-+      self.step_collection = step_collection
-+      self._conditional_bps = None
-+      self._watches = set()
-+      self._step_index = 0
-+      self._build_conditional_bps()
-+      self._path_and_line_to_conditional_bp = defaultdict(list)
-+      self._pause_between_steps = context.options.pause_between_steps
-+      self._max_steps = context.options.max_steps
-+
-+    def _build_conditional_bps(self):
-+        commands = self.step_collection.commands
-+        self._conditional_bps = []
-+        try:
-+            limit_commands = commands['DexLimitSteps']
-+            for lc in limit_commands:
-+                conditional_bp = ConditionalBpRange(
-+                  lc.expression,
-+                  lc.path,
-+                  lc.from_line,
-+                  lc.to_line,
-+                  lc.values)
-+                self._conditional_bps.append(conditional_bp)
-+        except KeyError:
-+            raise DebuggerException('Missing DexLimitSteps commands, cannot conditionally step.')
-+
-+    def _set_conditional_bps(self):
-+        # When we break in the debugger we need a quick and easy way to look up
-+        # which conditional bp we've breaked on.
-+        for cbp in self._conditional_bps:
-+            conditional_bp_list = self._path_and_line_to_conditional_bp[(cbp.path, cbp.range_from)]
-+            conditional_bp_list.append(cbp)
-+
-+        # Set break points only on the first line of any conditional range, we'll set
-+        # more break points for a range when the condition is satisfied.
-+        for cbp in self._conditional_bps:
-+            for cond_expr in cbp.get_conditional_expression_list():
-+                self.debugger.add_conditional_breakpoint(cbp.path, cbp.range_from, cond_expr)
-+
-+    def _conditional_met(self, cbp):
-+        for cond_expr in cbp.get_conditional_expression_list():
-+            valueIR = self.debugger.evaluate_expression(cond_expr)
-+            if valueIR.type_name == 'bool' and valueIR.value == 'true':
-+                return True
-+        return False
-+
-+    def _run_debugger_custom(self):
-+        # TODO: Add conditional and unconditional breakpoint support to dbgeng.
-+        if self.debugger.get_name() == 'dbgeng':
-+            raise DebuggerException('DexLimitSteps commands are not supported by dbgeng')
-+
-+        self.step_collection.clear_steps()
-+        self._set_conditional_bps()
-+
-+        for command_obj in chain.from_iterable(self.step_collection.commands.values()):
-+            self._watches.update(command_obj.get_watches())
-+
-+        self.debugger.launch()
-+        time.sleep(self._pause_between_steps) 
-+        while not self.debugger.is_finished:
-+            while self.debugger.is_running:
-+                pass
-+
-+            step_info = self.debugger.get_step_info(self._watches, self._step_index)
-+            if step_info.current_frame:
-+                self._step_index += 1
-+                update_step_watches(step_info, self._watches, self.step_collection.commands)
-+                self.step_collection.new_step(self.context, step_info)
-+
-+                loc = step_info.current_location
-+                conditional_bp_key = (loc.path, loc.lineno)
-+                if conditional_bp_key in self._path_and_line_to_conditional_bp:
-+
-+                    conditional_bps = self._path_and_line_to_conditional_bp[conditional_bp_key]
-+                    for cbp in conditional_bps:
-+                        if self._conditional_met(cbp):
-+                            # Unconditional range should ignore first line as that's the
-+                            # conditional bp we just hit and should be inclusive of final line
-+                            for line in range(cbp.range_from + 1, cbp.range_to + 1):
-+                                self.debugger.add_conditional_breakpoint(cbp.path, line, condition='')
-+
-+            # Clear any uncondtional break points at this loc.
-+            self.debugger.delete_conditional_breakpoint(file_=loc.path, line=loc.lineno, condition='')
-+            self.debugger.go()
-+            time.sleep(self._pause_between_steps)
-diff --git a/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ControllerHelpers.py b/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ControllerHelpers.py
-new file mode 100644
-index 00000000000..adac7674aff
---- /dev/null
-+++ b/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ControllerHelpers.py
-@@ -0,0 +1,37 @@
-+# DExTer : Debugging Experience Tester
-+# ~~~~~~   ~         ~~         ~   ~~
-+#
-+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-+# See https://llvm.org/LICENSE.txt for license information.
-+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-+
-+import os
-+from itertools import chain
-+
-+def in_source_file(source_files, step_info):
-+    if not step_info.current_frame:
-+        return False
-+    if not step_info.current_location.path:
-+        return False
-+    if not os.path.exists(step_info.current_location.path):
-+        return False
-+    return any(os.path.samefile(step_info.current_location.path, f) \
-+               for f in source_files)
-+
-+def update_step_watches(step_info, watches, commands):
-+    watch_cmds = ['DexUnreachable', 'DexExpectStepOrder']
-+    towatch = chain.from_iterable(commands[x]
-+                                  for x in watch_cmds
-+                                  if x in commands)
-+    try:
-+        # Iterate over all watches of the types named in watch_cmds
-+        for watch in towatch:
-+            loc = step_info.current_location
-+            if (os.path.exists(loc.path)
-+                    and os.path.samefile(watch.path, loc.path)
-+                    and watch.lineno == loc.lineno):
-+                result = watch.eval(step_info)
-+                step_info.watches.update(result)
-+                break
-+    except KeyError:
-+        pass
-diff --git a/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DebuggerControllerBase.py b/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DebuggerControllerBase.py
-index ff98baa2d0e..87b13fc7f3a 100644
---- a/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DebuggerControllerBase.py
-+++ b/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DebuggerControllerBase.py
-@@ -4,7 +4,7 @@
- # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- # See https://llvm.org/LICENSE.txt for license information.
- # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
--"""Default class for controlling debuggers."""
-+"""Abstract Base class for controlling debuggers."""
- import abc
-diff --git a/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DefaultController.py b/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DefaultController.py
-index 0077a19e601..c41a3eff0d3 100644
---- a/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DefaultController.py
-+++ b/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DefaultController.py
-@@ -4,61 +4,37 @@
- # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- # See https://llvm.org/LICENSE.txt for license information.
- # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
--"""Base class for controlling debuggers."""
-+"""Default class for controlling debuggers."""
- from itertools import chain
- import os
- import time
- from dex.debugger.DebuggerControllers.DebuggerControllerBase import DebuggerControllerBase
--from dex.utils.Exceptions import DebuggerException
-+from dex.debugger.DebuggerControllers.ControllerHelpers import in_source_file, update_step_watches
-+from dex.utils.Exceptions import DebuggerException, LoadDebuggerException
- class DefaultController(DebuggerControllerBase):
-     def __init__(self, context, step_collection):
-         self.context = context
-         self.step_collection = step_collection
-+        self.source_files = self.context.options.source_files
-         self.watches = set()
-         self.step_index = 0
--    def _update_step_watches(self, step_info):
--        watch_cmds = ['DexUnreachable', 'DexExpectStepOrder']
--        towatch = chain.from_iterable(self.step_collection.commands[x]
--                                      for x in watch_cmds
--                                      if x in self.step_collection.commands)
--        try:
--            # Iterate over all watches of the types named in watch_cmds
--            for watch in towatch:
--                loc = step_info.current_location
--                if (os.path.exists(loc.path)
--                        and os.path.samefile(watch.path, loc.path)
--                        and watch.lineno == loc.lineno):
--                    result = watch.eval(step_info)
--                    step_info.watches.update(result)
--                    break
--        except KeyError:
--            pass
--
-     def _break_point_all_lines(self):
-         for s in self.context.options.source_files:
-             with open(s, 'r') as fp:
-                 num_lines = len(fp.readlines())
-             for line in range(1, num_lines + 1):
--                self.debugger.add_breakpoint(s, line)
--
--    def _in_source_file(self, step_info):
--        if not step_info.current_frame:
--            return False
--        if not step_info.current_location.path:
--            return False
--        if not os.path.exists(step_info.current_location.path):
--            return False
--        return any(os.path.samefile(step_info.current_location.path, f) \
--                   for f in self.context.options.source_files)
-+                try:
-+                   self.debugger.add_breakpoint(s, line)
-+                except DebuggerException:
-+                   raise LoadDebuggerException(DebuggerException.msg)
-     def _run_debugger_custom(self):
-         self.step_collection.debugger = self.debugger.debugger_info
-         self._break_point_all_lines()
--
-         self.debugger.launch()
-         for command_obj in chain.from_iterable(self.step_collection.commands.values()):
-@@ -76,10 +52,10 @@ class DefaultController(DebuggerControllerBase):
-             step_info = self.debugger.get_step_info(self.watches, self.step_index)
-             if step_info.current_frame:
--                self._update_step_watches(step_info)
-+                update_step_watches(step_info, self.watches, self.step_collection.commands)
-                 self.step_collection.new_step(self.context, step_info)
--            if self._in_source_file(step_info):
-+            if in_source_file(self.source_files, step_info):
-                 self.debugger.step()
-             else:
-                 self.debugger.go()
-diff --git a/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py b/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py
-index 0afc748aecb..d812fd974f7 100644
---- a/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py
-+++ b/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py
-@@ -77,11 +77,21 @@ class DbgEng(DebuggerBase):
-             self.client.Control.RemoveBreakpoint(x)
-     def add_breakpoint(self, file_, line):
--        # This is something to implement in the future -- as it stands, Dexter
--        # doesn't test for such things as "I can set a breakpoint on this line".
--        # This is only called AFAICT right now to ensure we break on every step.
-+        # Breakpoint setting/deleting is not supported by dbgeng at this moment
-+        # but is something that should be considered in the future.
-+        # TODO: this method is called in the DefaultController but has no effect.
-         pass
-+    def add_conditional_breakpoint(self, file_, line, condition):
-+        # breakpoint setting/deleting is not supported by dbgeng at this moment
-+        # but is something that should be considered in the future.
-+        raise NotImplementedError('add_conditional_breakpoint is not yet implemented by dbgeng')
-+
-+    def delete_conditional_breakpoint(self, file_, line, condition):
-+        # breakpoint setting/deleting is not supported by dbgeng at this moment
-+        # but is something that should be considered in the future.
-+        raise NotImplementedError('delete_conditional_breakpoint is not yet implemented by dbgeng')
-+
-     def launch(self):
-         # We are, by this point, already launched.
-         self.step_info = probe_process.probe_state(self.client)
-diff --git a/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py b/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py
-index a943431c888..c7bb74681d9 100644
---- a/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py
-+++ b/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py
-@@ -105,9 +105,48 @@ class LLDB(DebuggerBase):
-     def add_breakpoint(self, file_, line):
-         if not self._target.BreakpointCreateByLocation(file_, line):
--            raise LoadDebuggerException(
-+            raise DebuggerException(
-                 'could not add breakpoint [{}:{}]'.format(file_, line))
-+    def add_conditional_breakpoint(self, file_, line, condition):
-+        bp = self._target.BreakpointCreateByLocation(file_, line)
-+        if bp:
-+            bp.SetCondition(condition)
-+        else:
-+            raise DebuggerException(
-+                  'could not add breakpoint [{}:{}]'.format(file_, line))
-+
-+    def delete_conditional_breakpoint(self, file_, line, condition):
-+        bp_count = self._target.GetNumBreakpoints()
-+        bps = [self._target.GetBreakpointAtIndex(ix) for ix in range(0, bp_count)]
-+
-+        for bp in bps:
-+            bp_cond = bp.GetCondition()
-+            bp_cond = bp_cond if bp_cond is not None else ''
-+
-+            if bp_cond != condition:
-+                continue
-+
-+            # If one of the bound bp locations for this bp is bound to the same
-+            # line in file_ above, then delete the entire parent bp and all
-+            # bp locs.
-+            # https://lldb.llvm.org/python_reference/lldb.SBBreakpoint-class.html
-+            for breakpoint_location in bp:
-+                sb_address = breakpoint_location.GetAddress()
-+
-+                sb_line_entry = sb_address.GetLineEntry()
-+                bl_line = sb_line_entry.GetLine()
-+
-+                sb_file_entry = sb_line_entry.GetFileSpec()
-+                bl_dir = sb_file_entry.GetDirectory()
-+                bl_file_name = sb_file_entry.GetFilename()
-+
-+                bl_file_path = os.path.join(bl_dir, bl_file_name)
-+
-+                if bl_file_path == file_ and bl_line == line:
-+                    self._target.BreakpointDelete(bp.GetID())
-+                    break
-+
-     def launch(self):
-         self._process = self._target.LaunchSimple(None, None, os.getcwd())
-         if not self._process or self._process.GetNumThreads() == 0:
-diff --git a/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py b/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py
-index b9816f84f72..40a902bd205 100644
---- a/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py
-+++ b/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py
-@@ -82,6 +82,9 @@ class VisualStudio(DebuggerBase, metaclass=abc.ABCMeta):  # pylint: disable=abst
-     @property
-     def _location(self):
-+        #TODO: Find a better way of determining path, line and column info
-+        # that doesn't require reading break points. This method requires
-+        # all lines to have a break point on them.
-         bp = self._debugger.BreakpointLastHit
-         return {
-             'path': getattr(bp, 'File', None),
-@@ -111,8 +114,20 @@ class VisualStudio(DebuggerBase, metaclass=abc.ABCMeta):  # pylint: disable=abst
-     def add_breakpoint(self, file_, line):
-         self._debugger.Breakpoints.Add('', file_, line)
-+    def add_conditional_breakpoint(self, file_, line, condition):
-+        column = 1
-+        self._debugger.Breakpoints.Add('', file_, line, column, condition)
-+
-+    def delete_conditional_breakpoint(self, file_, line, condition):
-+        for bp in self._debugger.Breakpoints:
-+            for bound_bp in bp.Children:
-+                if (bound_bp.File == file_ and bound_bp.FileLine == line and
-+                    bound_bp.Condition == condition):
-+                    bp.Delete()
-+                    break
-+
-     def launch(self):
--        self.step()
-+        self._fn_go()
-     def step(self):
-         self._fn_step()
-diff --git a/debuginfo-tests/dexter/dex/tools/test/Tool.py b/debuginfo-tests/dexter/dex/tools/test/Tool.py
-index a615c8cad90..43191fd44bd 100644
---- a/debuginfo-tests/dexter/dex/tools/test/Tool.py
-+++ b/debuginfo-tests/dexter/dex/tools/test/Tool.py
-@@ -16,6 +16,7 @@ from dex.builder import run_external_build_script
- from dex.command.ParseCommand import get_command_infos
- from dex.debugger.Debuggers import run_debugger_subprocess
- from dex.debugger.DebuggerControllers.DefaultController import DefaultController
-+from dex.debugger.DebuggerControllers.ConditionalController import ConditionalController
- from dex.dextIR.DextIR import DextIR
- from dex.heuristic import Heuristic
- from dex.tools import TestToolBase
-@@ -136,9 +137,15 @@ class Tool(TestToolBase):
-             executable_path=self.context.options.executable,
-             source_paths=self.context.options.source_files,
-             dexter_version=self.context.version)
-+
-         step_collection.commands = get_command_infos(
-             self.context.options.source_files)
--        debugger_controller = DefaultController(self.context, step_collection)
-+
-+        if 'DexLimitSteps' in step_collection.commands:
-+            debugger_controller = ConditionalController(self.context, step_collection)
-+        else:
-+            debugger_controller = DefaultController(self.context, step_collection)
-+
-         return debugger_controller
-     def _get_steps(self, builderIR):
-diff --git a/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_check_json_step_count.cpp b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_check_json_step_count.cpp
-new file mode 100644
-index 00000000000..45683fced2d
---- /dev/null
-+++ b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_check_json_step_count.cpp
-@@ -0,0 +1,20 @@
-+// Purpose:
-+//      Check number of step lines are correctly reported in json output.
-+//
-+// REQUIRES: system-linux
-+//
-+// RUN: %dexter_regression_test --verbose -- %s | FileCheck %s
-+// CHECK: limit_steps_check_json_step_count.cpp
-+// CHECK: ## BEGIN ##
-+// CHECK-COUNT-3: json_step_count.cpp",
-+
-+int main() {
-+  int result = 0;
-+  for(int ix = 0; ix != 10; ++ix) {
-+    int index = ix;
-+    result += index; // DexLabel('check')
-+  }
-+}
-+
-+// DexExpectWatchValue('index', 2, 7, 9, on_line='check')
-+// DexLimitSteps('ix', 2, 7, 9, on_line='check')
-diff --git a/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_expect_loop.cpp b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_expect_loop.cpp
-new file mode 100644
-index 00000000000..5946fa6ba46
---- /dev/null
-+++ b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_expect_loop.cpp
-@@ -0,0 +1,20 @@
-+// Purpose:
-+//      Check the DexLimit steps only gathers step info for 2 iterations of a
-+//      for loop.
-+//
-+// REQUIRES: system-linux
-+//
-+// RUN: %dexter_regression_test -- %s | FileCheck %s
-+// CHECK: limit_steps_expect_loop.cpp:
-+
-+int main(const int argc, const char * argv[]) {
-+  unsigned int sum = 1;
-+  for(unsigned int ix = 0; ix != 5; ++ix) {
-+    unsigned thing_to_add = ix + ix - ix;   // DexLabel('start')
-+    sum += ix;                              // DexLabel('end')
-+  }
-+  return sum;
-+}
-+
-+// DexLimitSteps('ix', 0, 3, from_line='start', to_line='end')
-+// DexExpectWatchValue('ix', 0, 3, from_line='start', to_line='end')
-diff --git a/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_expect_value.cpp b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_expect_value.cpp
-new file mode 100644
-index 00000000000..2715e28d66b
---- /dev/null
-+++ b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_expect_value.cpp
-@@ -0,0 +1,18 @@
-+// Purpose:
-+//      Ensure that limited stepping breaks for all expected values.
-+//
-+// REQUIRES: system-linux
-+//
-+// RUN: %dexter_regression_test -- %s | FileCheck %s
-+// CHECK: limit_steps_expect_value.cpp
-+
-+int main() {
-+  int i = 0;
-+  i = 1;    // DexLabel('from')
-+  i = 2;
-+  i = 3;
-+  return 0; // DexLabel('long_range')
-+}
-+
-+// DexLimitSteps('i', '0', from_line='from', to_line='long_range')
-+// DexExpectWatchValue('i', 0, 1, 2, 3, from_line='from', to_line='long_range')
-diff --git a/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_overlapping_ranges.cpp b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_overlapping_ranges.cpp
-new file mode 100644
-index 00000000000..3200fe0979b
---- /dev/null
-+++ b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_overlapping_ranges.cpp
-@@ -0,0 +1,36 @@
-+// Purpose:
-+//      Ensure that multiple overlapping \DexLimitSteps ranges do not interfere.
-+//
-+// REQUIRES: system-linux
-+//
-+// RUN: %dexter_regression_test -- %s | FileCheck %s
-+// CHECK: limit_steps_overlapping_ranges.cpp
-+
-+int main() {
-+  int val1;
-+  int val2;
-+  int placeholder;
-+  for (int ix = 0; ix != 10; ++ix) {
-+    placeholder=val1+val2;   // DexLabel('from')
-+    if (ix == 0) {
-+      val1 = ix;
-+      val2 = ix;             // DexLabel('val1_check')
-+      placeholder=val1+val2; // DexLabel('val1_check_to')
-+    }
-+    else if (ix == 2) {
-+      val2 = ix;
-+      val1 = ix;             // DexLabel('val2_check')
-+      placeholder=val1+val2; // DexLabel('val2_check_to')
-+    }
-+    placeholder=val1+val2;   // DexLabel('to')
-+  }
-+  return val1 + val2;
-+}
-+
-+// DexExpectWatchValue('ix', 0, 2, 5, from_line='from', to_line='to')
-+// DexExpectWatchValue('val1', 0, from_line='val1_check', to_line='val1_check_to')
-+// DexExpectWatchValue('val2', 2, from_line='val2_check', to_line='val2_check_to')
-+
-+// DexLimitSteps('ix', 5, from_line='from', to_line='to')
-+// DexLimitSteps('val1', 0, from_line='val1_check', to_line='val1_check_to')
-+// DexLimitSteps('val2', 2, from_line='val2_check', to_line='val2_check_to')
-diff --git a/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_same_line_conditional.cpp b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_same_line_conditional.cpp
-new file mode 100644
-index 00000000000..060ff0d5fe7
---- /dev/null
-+++ b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_same_line_conditional.cpp
-@@ -0,0 +1,26 @@
-+// Purpose:
-+//      Test that LimitStep commands can exist on the same from line.
-+//
-+// REQUIRES: system-linux
-+//
-+// RUN: %dexter_regression_test -- %s | FileCheck %s
-+// CHECK: limit_steps_same_line_conditional.cpp
-+
-+int main() {
-+  int val1 = 0;
-+
-+  int placeholder;
-+  for(int ix = 0; ix != 4; ++ix) {
-+    val1 = ix;
-+    placeholder = ix;    // DexLabel('from')
-+    placeholder = ix;
-+    val1 += 2;           // DexLabel('to')
-+    placeholder = ix;    // DexLabel('extended_to')
-+  }
-+  return val1 + placeholder;
-+}
-+
-+// DexExpectWatchValue('val1', 0, 1, 3, from_line='from', to_line='extended_to')
-+
-+// DexLimitSteps('ix', 0, from_line='from', to_line='to')
-+// DexLimitSteps('ix', 1, from_line='from', to_line='extended_to')
index 2e2fecf..c30a0d7 100644 (file)
@@ -174,34 +174,6 @@ Expect the source line this is found on will never be stepped on to.
 
 
 ----
-## DexLimitSteps
-    DexLimitSteps(expr, *values [, **from_line=1],[,**to_line=Max]
-                  [,**on_line])
-
-    Args:
-        expr (str): variable or value to compare.
-
-    Arg list:
-        values (str): At least one potential value the expr may evaluate to.
-
-    Keyword args:
-        from_line (int): Define the start of the limited step range.
-        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.
-
-### Description
-Define a limited stepping range that is predicated on a condition. When
-'(expr) == (values[n])', set a range of temporary, unconditional break points within
-the test file defined by the range from_line and to_line or on_line.
-
-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, the whole range is ignored.
-
-DexLimitSteps commands are useful for reducing the amount of steps gathered in
-large test cases that would normally take much longer to complete.
-
-----
 ## DexLabel
     DexLabel(name)
 
index 8246ea9..4cc9ae1 100644 (file)
@@ -24,7 +24,6 @@ from dex.command.commands.DexExpectStepOrder import DexExpectStepOrder
 from dex.command.commands.DexExpectWatchType import DexExpectWatchType
 from dex.command.commands.DexExpectWatchValue import DexExpectWatchValue
 from dex.command.commands.DexLabel import DexLabel
-from dex.command.commands.DexLimitSteps import DexLimitSteps
 from dex.command.commands.DexUnreachable import DexUnreachable
 from dex.command.commands.DexWatch import DexWatch
 from dex.utils import Timer
@@ -43,7 +42,6 @@ def _get_valid_commands():
       DexExpectWatchType.get_name() : DexExpectWatchType,
       DexExpectWatchValue.get_name() : DexExpectWatchValue,
       DexLabel.get_name() : DexLabel,
-      DexLimitSteps.get_name() : DexLimitSteps,
       DexUnreachable.get_name() : DexUnreachable,
       DexWatch.get_name() : DexWatch
     }
diff --git a/debuginfo-tests/dexter/dex/command/commands/DexLimitSteps.py b/debuginfo-tests/dexter/dex/command/commands/DexLimitSteps.py
deleted file mode 100644 (file)
index d66401b..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-# DExTer : Debugging Experience Tester
-# ~~~~~~   ~         ~~         ~   ~~
-#
-# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-# See https://llvm.org/LICENSE.txt for license information.
-# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-"""A Command that enables test writers to specify a limited number of break
-points using an start condition and range.
-"""
-
-from dex.command.CommandBase import CommandBase
-
-class DexLimitSteps(CommandBase):
-    def __init__(self, *args, **kwargs):
-        self.expression = args[0]
-        self.values = [str(arg) for arg in args[1:]]
-        try:
-            on_line = kwargs.pop('on_line')
-            self.from_line = on_line
-            self.to_line = on_line
-        except KeyError:
-            self.from_line = kwargs.pop('from_line', 1)
-            self.to_line = kwargs.pop('to_line', 999999)
-        if kwargs:
-            raise TypeError('unexpected named args: {}'.format(
-                ', '.join(kwargs)))
-        super(DexLimitSteps, self).__init__()
-
-    def resolve_label(self, label_line_pair):
-        label, lineno = label_line_pair
-        if isinstance(self.from_line, str):
-            if self.from_line == label:
-                self.from_line = lineno
-        if isinstance(self.to_line, str):
-            if self.to_line == label:
-                self.to_line = lineno
-
-    def has_labels(self):
-        return len(self.get_label_args()) > 0
-
-    def get_label_args(self):
-        return [label for label in (self.from_line, self.to_line)
-                      if isinstance(label, str)]
-
-    def eval(self):
-        raise NotImplementedError('DexLimitSteps commands cannot be evaled.')
-
-    @staticmethod
-    def get_name():
-        return __class__.__name__
-
-    @staticmethod
-    def get_subcommands() -> dict:
-        return None
index 12f4f4a..2261396 100644 (file)
@@ -121,14 +121,6 @@ class DebuggerBase(object, metaclass=abc.ABCMeta):
         pass
 
     @abc.abstractmethod
-    def add_conditional_breakpoint(self, file_, line, condition):
-        pass
-
-    @abc.abstractmethod
-    def delete_conditional_breakpoint(self, file_, line, condition):
-        pass
-
-    @abc.abstractmethod
     def launch(self):
         pass
 
diff --git a/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ConditionalController.py b/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ConditionalController.py
deleted file mode 100644 (file)
index 4e4327b..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-# DExTer : Debugging Experience Tester
-# ~~~~~~   ~         ~~         ~   ~~
-#
-# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-# See https://llvm.org/LICENSE.txt for license information.
-# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-"""Conditional Controller Class for DExTer.-"""
-
-
-import os
-import time
-from collections import defaultdict
-from itertools import chain
-
-from dex.debugger.DebuggerControllers.ControllerHelpers import in_source_file, update_step_watches
-from dex.debugger.DebuggerControllers.DebuggerControllerBase import DebuggerControllerBase
-from dex.debugger.DebuggerBase import DebuggerBase
-from dex.utils.Exceptions import DebuggerException
-
-
-class ConditionalBpRange:
-    """Represents a conditional range of breakpoints within a source file descending from
-    one line to another."""
-
-    def __init__(self, expression: str, path: str, range_from: int, range_to: int, values: list):
-        self.expression = expression
-        self.path = path
-        self.range_from = range_from
-        self.range_to = range_to
-        self.conditional_values = values
-
-    def get_conditional_expression_list(self):
-        conditional_list = []
-        for value in self.conditional_values:
-            # (<expression>) == (<value>)
-            conditional_expression = '({}) == ({})'.format(self.expression, value)
-            conditional_list.append(conditional_expression)
-        return conditional_list
-
-
-class ConditionalController(DebuggerControllerBase):
-    def __init__(self, context, step_collection):
-      self.context = context
-      self.step_collection = step_collection
-      self._conditional_bps = None
-      self._watches = set()
-      self._step_index = 0
-      self._build_conditional_bps()
-      self._path_and_line_to_conditional_bp = defaultdict(list)
-      self._pause_between_steps = context.options.pause_between_steps
-      self._max_steps = context.options.max_steps
-
-    def _build_conditional_bps(self):
-        commands = self.step_collection.commands
-        self._conditional_bps = []
-        try:
-            limit_commands = commands['DexLimitSteps']
-            for lc in limit_commands:
-                conditional_bp = ConditionalBpRange(
-                  lc.expression,
-                  lc.path,
-                  lc.from_line,
-                  lc.to_line,
-                  lc.values)
-                self._conditional_bps.append(conditional_bp)
-        except KeyError:
-            raise DebuggerException('Missing DexLimitSteps commands, cannot conditionally step.')
-
-    def _set_conditional_bps(self):
-        # When we break in the debugger we need a quick and easy way to look up
-        # which conditional bp we've breaked on.
-        for cbp in self._conditional_bps:
-            conditional_bp_list = self._path_and_line_to_conditional_bp[(cbp.path, cbp.range_from)]
-            conditional_bp_list.append(cbp)
-
-        # Set break points only on the first line of any conditional range, we'll set
-        # more break points for a range when the condition is satisfied.
-        for cbp in self._conditional_bps:
-            for cond_expr in cbp.get_conditional_expression_list():
-                self.debugger.add_conditional_breakpoint(cbp.path, cbp.range_from, cond_expr)
-
-    def _conditional_met(self, cbp):
-        for cond_expr in cbp.get_conditional_expression_list():
-            valueIR = self.debugger.evaluate_expression(cond_expr)
-            if valueIR.type_name == 'bool' and valueIR.value == 'true':
-                return True
-        return False
-
-    def _run_debugger_custom(self):
-        # TODO: Add conditional and unconditional breakpoint support to dbgeng.
-        if self.debugger.get_name() == 'dbgeng':
-            raise DebuggerException('DexLimitSteps commands are not supported by dbgeng')
-
-        self.step_collection.clear_steps()
-        self._set_conditional_bps()
-
-        for command_obj in chain.from_iterable(self.step_collection.commands.values()):
-            self._watches.update(command_obj.get_watches())
-
-        self.debugger.launch()
-        time.sleep(self._pause_between_steps) 
-        while not self.debugger.is_finished:
-            while self.debugger.is_running:
-                pass
-
-            step_info = self.debugger.get_step_info(self._watches, self._step_index)
-            if step_info.current_frame:
-                self._step_index += 1
-                update_step_watches(step_info, self._watches, self.step_collection.commands)
-                self.step_collection.new_step(self.context, step_info)
-
-                loc = step_info.current_location
-                conditional_bp_key = (loc.path, loc.lineno)
-                if conditional_bp_key in self._path_and_line_to_conditional_bp:
-
-                    conditional_bps = self._path_and_line_to_conditional_bp[conditional_bp_key]
-                    for cbp in conditional_bps:
-                        if self._conditional_met(cbp):
-                            # Unconditional range should ignore first line as that's the
-                            # conditional bp we just hit and should be inclusive of final line
-                            for line in range(cbp.range_from + 1, cbp.range_to + 1):
-                                self.debugger.add_conditional_breakpoint(cbp.path, line, condition='')
-
-            # Clear any uncondtional break points at this loc.
-            self.debugger.delete_conditional_breakpoint(file_=loc.path, line=loc.lineno, condition='')
-            self.debugger.go()
-            time.sleep(self._pause_between_steps)
diff --git a/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ControllerHelpers.py b/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ControllerHelpers.py
deleted file mode 100644 (file)
index adac767..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-# DExTer : Debugging Experience Tester
-# ~~~~~~   ~         ~~         ~   ~~
-#
-# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-# See https://llvm.org/LICENSE.txt for license information.
-# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-import os
-from itertools import chain
-
-def in_source_file(source_files, step_info):
-    if not step_info.current_frame:
-        return False
-    if not step_info.current_location.path:
-        return False
-    if not os.path.exists(step_info.current_location.path):
-        return False
-    return any(os.path.samefile(step_info.current_location.path, f) \
-               for f in source_files)
-
-def update_step_watches(step_info, watches, commands):
-    watch_cmds = ['DexUnreachable', 'DexExpectStepOrder']
-    towatch = chain.from_iterable(commands[x]
-                                  for x in watch_cmds
-                                  if x in commands)
-    try:
-        # Iterate over all watches of the types named in watch_cmds
-        for watch in towatch:
-            loc = step_info.current_location
-            if (os.path.exists(loc.path)
-                    and os.path.samefile(watch.path, loc.path)
-                    and watch.lineno == loc.lineno):
-                result = watch.eval(step_info)
-                step_info.watches.update(result)
-                break
-    except KeyError:
-        pass
index 87b13fc..ff98baa 100644 (file)
@@ -4,7 +4,7 @@
 # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 # See https://llvm.org/LICENSE.txt for license information.
 # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-"""Abstract Base class for controlling debuggers."""
+"""Default class for controlling debuggers."""
 
 import abc
 
index c41a3ef..0077a19 100644 (file)
@@ -4,37 +4,61 @@
 # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 # See https://llvm.org/LICENSE.txt for license information.
 # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-"""Default class for controlling debuggers."""
+"""Base class for controlling debuggers."""
 
 from itertools import chain
 import os
 import time
 
 from dex.debugger.DebuggerControllers.DebuggerControllerBase import DebuggerControllerBase
-from dex.debugger.DebuggerControllers.ControllerHelpers import in_source_file, update_step_watches
-from dex.utils.Exceptions import DebuggerException, LoadDebuggerException
+from dex.utils.Exceptions import DebuggerException
 
 class DefaultController(DebuggerControllerBase):
     def __init__(self, context, step_collection):
         self.context = context
         self.step_collection = step_collection
-        self.source_files = self.context.options.source_files
         self.watches = set()
         self.step_index = 0
 
+    def _update_step_watches(self, step_info):
+        watch_cmds = ['DexUnreachable', 'DexExpectStepOrder']
+        towatch = chain.from_iterable(self.step_collection.commands[x]
+                                      for x in watch_cmds
+                                      if x in self.step_collection.commands)
+        try:
+            # Iterate over all watches of the types named in watch_cmds
+            for watch in towatch:
+                loc = step_info.current_location
+                if (os.path.exists(loc.path)
+                        and os.path.samefile(watch.path, loc.path)
+                        and watch.lineno == loc.lineno):
+                    result = watch.eval(step_info)
+                    step_info.watches.update(result)
+                    break
+        except KeyError:
+            pass
+
     def _break_point_all_lines(self):
         for s in self.context.options.source_files:
             with open(s, 'r') as fp:
                 num_lines = len(fp.readlines())
             for line in range(1, num_lines + 1):
-                try:
-                   self.debugger.add_breakpoint(s, line)
-                except DebuggerException:
-                   raise LoadDebuggerException(DebuggerException.msg)
+                self.debugger.add_breakpoint(s, line)
+
+    def _in_source_file(self, step_info):
+        if not step_info.current_frame:
+            return False
+        if not step_info.current_location.path:
+            return False
+        if not os.path.exists(step_info.current_location.path):
+            return False
+        return any(os.path.samefile(step_info.current_location.path, f) \
+                   for f in self.context.options.source_files)
 
     def _run_debugger_custom(self):
         self.step_collection.debugger = self.debugger.debugger_info
         self._break_point_all_lines()
+
         self.debugger.launch()
 
         for command_obj in chain.from_iterable(self.step_collection.commands.values()):
@@ -52,10 +76,10 @@ class DefaultController(DebuggerControllerBase):
             step_info = self.debugger.get_step_info(self.watches, self.step_index)
 
             if step_info.current_frame:
-                update_step_watches(step_info, self.watches, self.step_collection.commands)
+                self._update_step_watches(step_info)
                 self.step_collection.new_step(self.context, step_info)
 
-            if in_source_file(self.source_files, step_info):
+            if self._in_source_file(step_info):
                 self.debugger.step()
             else:
                 self.debugger.go()
index d812fd9..0afc748 100644 (file)
@@ -77,21 +77,11 @@ class DbgEng(DebuggerBase):
             self.client.Control.RemoveBreakpoint(x)
 
     def add_breakpoint(self, file_, line):
-        # Breakpoint setting/deleting is not supported by dbgeng at this moment
-        # but is something that should be considered in the future.
-        # TODO: this method is called in the DefaultController but has no effect.
+        # This is something to implement in the future -- as it stands, Dexter
+        # doesn't test for such things as "I can set a breakpoint on this line".
+        # This is only called AFAICT right now to ensure we break on every step.
         pass
 
-    def add_conditional_breakpoint(self, file_, line, condition):
-        # breakpoint setting/deleting is not supported by dbgeng at this moment
-        # but is something that should be considered in the future.
-        raise NotImplementedError('add_conditional_breakpoint is not yet implemented by dbgeng')
-
-    def delete_conditional_breakpoint(self, file_, line, condition):
-        # breakpoint setting/deleting is not supported by dbgeng at this moment
-        # but is something that should be considered in the future.
-        raise NotImplementedError('delete_conditional_breakpoint is not yet implemented by dbgeng')
-
     def launch(self):
         # We are, by this point, already launched.
         self.step_info = probe_process.probe_state(self.client)
index c7bb746..a943431 100644 (file)
@@ -105,48 +105,9 @@ class LLDB(DebuggerBase):
 
     def add_breakpoint(self, file_, line):
         if not self._target.BreakpointCreateByLocation(file_, line):
-            raise DebuggerException(
+            raise LoadDebuggerException(
                 'could not add breakpoint [{}:{}]'.format(file_, line))
 
-    def add_conditional_breakpoint(self, file_, line, condition):
-        bp = self._target.BreakpointCreateByLocation(file_, line)
-        if bp:
-            bp.SetCondition(condition)
-        else:
-            raise DebuggerException(
-                  'could not add breakpoint [{}:{}]'.format(file_, line))
-
-    def delete_conditional_breakpoint(self, file_, line, condition):
-        bp_count = self._target.GetNumBreakpoints()
-        bps = [self._target.GetBreakpointAtIndex(ix) for ix in range(0, bp_count)]
-
-        for bp in bps:
-            bp_cond = bp.GetCondition()
-            bp_cond = bp_cond if bp_cond is not None else ''
-
-            if bp_cond != condition:
-                continue
-
-            # If one of the bound bp locations for this bp is bound to the same
-            # line in file_ above, then delete the entire parent bp and all
-            # bp locs.
-            # https://lldb.llvm.org/python_reference/lldb.SBBreakpoint-class.html
-            for breakpoint_location in bp:
-                sb_address = breakpoint_location.GetAddress()
-
-                sb_line_entry = sb_address.GetLineEntry()
-                bl_line = sb_line_entry.GetLine()
-
-                sb_file_entry = sb_line_entry.GetFileSpec()
-                bl_dir = sb_file_entry.GetDirectory()
-                bl_file_name = sb_file_entry.GetFilename()
-
-                bl_file_path = os.path.join(bl_dir, bl_file_name)
-
-                if bl_file_path == file_ and bl_line == line:
-                    self._target.BreakpointDelete(bp.GetID())
-                    break
-
     def launch(self):
         self._process = self._target.LaunchSimple(None, None, os.getcwd())
         if not self._process or self._process.GetNumThreads() == 0:
index 40a902b..b9816f8 100644 (file)
@@ -82,9 +82,6 @@ class VisualStudio(DebuggerBase, metaclass=abc.ABCMeta):  # pylint: disable=abst
 
     @property
     def _location(self):
-        #TODO: Find a better way of determining path, line and column info
-        # that doesn't require reading break points. This method requires
-        # all lines to have a break point on them.
         bp = self._debugger.BreakpointLastHit
         return {
             'path': getattr(bp, 'File', None),
@@ -114,20 +111,8 @@ class VisualStudio(DebuggerBase, metaclass=abc.ABCMeta):  # pylint: disable=abst
     def add_breakpoint(self, file_, line):
         self._debugger.Breakpoints.Add('', file_, line)
 
-    def add_conditional_breakpoint(self, file_, line, condition):
-        column = 1
-        self._debugger.Breakpoints.Add('', file_, line, column, condition)
-
-    def delete_conditional_breakpoint(self, file_, line, condition):
-        for bp in self._debugger.Breakpoints:
-            for bound_bp in bp.Children:
-                if (bound_bp.File == file_ and bound_bp.FileLine == line and
-                    bound_bp.Condition == condition):
-                    bp.Delete()
-                    break
-
     def launch(self):
-        self._fn_go()
+        self.step()
 
     def step(self):
         self._fn_step()
index 43191fd..a615c8c 100644 (file)
@@ -16,7 +16,6 @@ from dex.builder import run_external_build_script
 from dex.command.ParseCommand import get_command_infos
 from dex.debugger.Debuggers import run_debugger_subprocess
 from dex.debugger.DebuggerControllers.DefaultController import DefaultController
-from dex.debugger.DebuggerControllers.ConditionalController import ConditionalController
 from dex.dextIR.DextIR import DextIR
 from dex.heuristic import Heuristic
 from dex.tools import TestToolBase
@@ -137,15 +136,9 @@ class Tool(TestToolBase):
             executable_path=self.context.options.executable,
             source_paths=self.context.options.source_files,
             dexter_version=self.context.version)
-
         step_collection.commands = get_command_infos(
             self.context.options.source_files)
-
-        if 'DexLimitSteps' in step_collection.commands:
-            debugger_controller = ConditionalController(self.context, step_collection)
-        else:
-            debugger_controller = DefaultController(self.context, step_collection)
-
+        debugger_controller = DefaultController(self.context, step_collection)
         return debugger_controller
 
     def _get_steps(self, builderIR):
diff --git a/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_check_json_step_count.cpp b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_check_json_step_count.cpp
deleted file mode 100644 (file)
index 45683fc..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// Purpose:
-//      Check number of step lines are correctly reported in json output.
-//
-// REQUIRES: system-linux
-//
-// RUN: %dexter_regression_test --verbose -- %s | FileCheck %s
-// CHECK: limit_steps_check_json_step_count.cpp
-// CHECK: ## BEGIN ##
-// CHECK-COUNT-3: json_step_count.cpp",
-
-int main() {
-  int result = 0;
-  for(int ix = 0; ix != 10; ++ix) {
-    int index = ix;
-    result += index; // DexLabel('check')
-  }
-}
-
-// DexExpectWatchValue('index', 2, 7, 9, on_line='check')
-// DexLimitSteps('ix', 2, 7, 9, on_line='check')
diff --git a/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_expect_loop.cpp b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_expect_loop.cpp
deleted file mode 100644 (file)
index 5946fa6..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// Purpose:
-//      Check the DexLimit steps only gathers step info for 2 iterations of a
-//      for loop.
-//
-// REQUIRES: system-linux
-//
-// RUN: %dexter_regression_test -- %s | FileCheck %s
-// CHECK: limit_steps_expect_loop.cpp:
-
-int main(const int argc, const char * argv[]) {
-  unsigned int sum = 1;
-  for(unsigned int ix = 0; ix != 5; ++ix) {
-    unsigned thing_to_add = ix + ix - ix;   // DexLabel('start')
-    sum += ix;                              // DexLabel('end')
-  }
-  return sum;
-}
-
-// DexLimitSteps('ix', 0, 3, from_line='start', to_line='end')
-// DexExpectWatchValue('ix', 0, 3, from_line='start', to_line='end')
diff --git a/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_expect_value.cpp b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_expect_value.cpp
deleted file mode 100644 (file)
index 2715e28..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// Purpose:
-//      Ensure that limited stepping breaks for all expected values.
-//
-// REQUIRES: system-linux
-//
-// RUN: %dexter_regression_test -- %s | FileCheck %s
-// CHECK: limit_steps_expect_value.cpp
-
-int main() {
-  int i = 0;
-  i = 1;    // DexLabel('from')
-  i = 2;
-  i = 3;
-  return 0; // DexLabel('long_range')
-}
-
-// DexLimitSteps('i', '0', from_line='from', to_line='long_range')
-// DexExpectWatchValue('i', 0, 1, 2, 3, from_line='from', to_line='long_range')
diff --git a/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_overlapping_ranges.cpp b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_overlapping_ranges.cpp
deleted file mode 100644 (file)
index 3200fe0..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-// Purpose:
-//      Ensure that multiple overlapping \DexLimitSteps ranges do not interfere.
-//
-// REQUIRES: system-linux
-//
-// RUN: %dexter_regression_test -- %s | FileCheck %s
-// CHECK: limit_steps_overlapping_ranges.cpp
-
-int main() {
-  int val1;
-  int val2;
-  int placeholder;
-  for (int ix = 0; ix != 10; ++ix) {
-    placeholder=val1+val2;   // DexLabel('from')
-    if (ix == 0) {
-      val1 = ix;
-      val2 = ix;             // DexLabel('val1_check')
-      placeholder=val1+val2; // DexLabel('val1_check_to')
-    }
-    else if (ix == 2) {
-      val2 = ix;
-      val1 = ix;             // DexLabel('val2_check')
-      placeholder=val1+val2; // DexLabel('val2_check_to')
-    }
-    placeholder=val1+val2;   // DexLabel('to')
-  }
-  return val1 + val2;
-}
-
-// DexExpectWatchValue('ix', 0, 2, 5, from_line='from', to_line='to')
-// DexExpectWatchValue('val1', 0, from_line='val1_check', to_line='val1_check_to')
-// DexExpectWatchValue('val2', 2, from_line='val2_check', to_line='val2_check_to')
-
-// DexLimitSteps('ix', 5, from_line='from', to_line='to')
-// DexLimitSteps('val1', 0, from_line='val1_check', to_line='val1_check_to')
-// DexLimitSteps('val2', 2, from_line='val2_check', to_line='val2_check_to')
diff --git a/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_same_line_conditional.cpp b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_same_line_conditional.cpp
deleted file mode 100644 (file)
index 060ff0d..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// Purpose:
-//      Test that LimitStep commands can exist on the same from line.
-//
-// REQUIRES: system-linux
-//
-// RUN: %dexter_regression_test -- %s | FileCheck %s
-// CHECK: limit_steps_same_line_conditional.cpp
-
-int main() {
-  int val1 = 0;
-
-  int placeholder;
-  for(int ix = 0; ix != 4; ++ix) {
-    val1 = ix;
-    placeholder = ix;    // DexLabel('from')
-    placeholder = ix;
-    val1 += 2;           // DexLabel('to')
-    placeholder = ix;    // DexLabel('extended_to')
-  }
-  return val1 + placeholder;
-}
-
-// DexExpectWatchValue('val1', 0, 1, 3, from_line='from', to_line='extended_to')
-
-// DexLimitSteps('ix', 0, from_line='from', to_line='to')
-// DexLimitSteps('ix', 1, from_line='from', to_line='extended_to')