summaryrefslogtreecommitdiffstats
path: root/debuginfo-tests/dexter/dex/command/commands/DexExpectProgramState.py
diff options
context:
space:
mode:
Diffstat (limited to 'debuginfo-tests/dexter/dex/command/commands/DexExpectProgramState.py')
-rw-r--r--debuginfo-tests/dexter/dex/command/commands/DexExpectProgramState.py83
1 files changed, 83 insertions, 0 deletions
diff --git a/debuginfo-tests/dexter/dex/command/commands/DexExpectProgramState.py b/debuginfo-tests/dexter/dex/command/commands/DexExpectProgramState.py
new file mode 100644
index 00000000000..78335838a65
--- /dev/null
+++ b/debuginfo-tests/dexter/dex/command/commands/DexExpectProgramState.py
@@ -0,0 +1,83 @@
+# 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
+"""Command for specifying a partial or complete state for the program to enter
+during execution.
+"""
+
+from itertools import chain
+
+from dex.command.CommandBase import CommandBase
+from dex.dextIR import ProgramState, SourceLocation, StackFrame, DextIR
+
+def frame_from_dict(source: dict) -> StackFrame:
+ if 'location' in source:
+ assert isinstance(source['location'], dict)
+ source['location'] = SourceLocation(**source['location'])
+ return StackFrame(**source)
+
+def state_from_dict(source: dict) -> ProgramState:
+ if 'frames' in source:
+ assert isinstance(source['frames'], list)
+ source['frames'] = list(map(frame_from_dict, source['frames']))
+ return ProgramState(**source)
+
+class DexExpectProgramState(CommandBase):
+ """Expect to see a given program `state` a certain numer of `times`.
+
+ DexExpectProgramState(state [,**times])
+
+ See Commands.md for more info.
+ """
+
+ def __init__(self, *args, **kwargs):
+ if len(args) != 1:
+ raise TypeError('expected exactly one unnamed arg')
+
+ self.program_state_text = str(args[0])
+
+ self.expected_program_state = state_from_dict(args[0])
+
+ self.times = kwargs.pop('times', -1)
+ if kwargs:
+ raise TypeError('unexpected named args: {}'.format(
+ ', '.join(kwargs)))
+
+ # Step indices at which the expected program state was encountered.
+ self.encounters = []
+
+ super(DexExpectProgramState, self).__init__()
+
+ @staticmethod
+ def get_name():
+ return __class__.__name__
+
+ def get_watches(self):
+ frame_expects = chain.from_iterable(frame.watches
+ for frame in self.expected_program_state.frames)
+ return set(frame_expects)
+
+ def eval(self, step_collection: DextIR) -> bool:
+ for step in step_collection.steps:
+ if self.expected_program_state.match(step.program_state):
+ self.encounters.append(step.step_index)
+
+ return self.times < 0 < len(self.encounters) or len(self.encounters) == self.times
+
+ def has_labels(self):
+ return len(self.get_label_args()) > 0
+
+ def get_label_args(self):
+ return [frame.location.lineno
+ for frame in self.expected_program_state.frames
+ if frame.location and
+ isinstance(frame.location.lineno, str)]
+
+ def resolve_label(self, label_line__pair):
+ label, line = label_line__pair
+ for frame in self.expected_program_state.frames:
+ if frame.location and frame.location.lineno == label:
+ frame.location.lineno = line
OpenPOWER on IntegriCloud