brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.6 KiB · 42500c4 Raw
149 lines · python
1# DExTer : Debugging Experience Tester2# ~~~~~~   ~         ~~         ~   ~~3#4# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5# See https://llvm.org/LICENSE.txt for license information.6# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7from collections import OrderedDict8import os9from typing import List10 11from dex.dextIR.DebuggerIR import DebuggerIR12from dex.dextIR.StepIR import StepIR, StepKind13 14 15def _step_kind_func(context, step):16    if step.current_location.path is None or not os.path.exists(17        step.current_location.path18    ):19        return StepKind.FUNC_UNKNOWN20 21    if any(22        os.path.samefile(step.current_location.path, f)23        for f in context.options.source_files24    ):25        return StepKind.FUNC26 27    return StepKind.FUNC_EXTERNAL28 29 30class DextIR:31    """A full Dexter test report.32 33    This is composed of all the other *IR classes. They are used together to34    record Dexter inputs and the resultant debugger steps, providing a single35    high level access container.36 37    The Heuristic class works with dexter commands and the generated DextIR to38    determine the debugging score for a given test.39 40    Args:41        commands: { name (str), commands (list[CommandIR])42    """43 44    def __init__(45        self,46        dexter_version: str,47        executable_path: str,48        source_paths: List[str],49        debugger: DebuggerIR = None,50        commands: OrderedDict = None,51    ):52        self.dexter_version = dexter_version53        self.executable_path = executable_path54        self.source_paths = source_paths55        self.debugger = debugger56        self.commands = commands57        self.steps: List[StepIR] = []58 59    def __str__(self):60        colors = "rgby"61        st = "## BEGIN ##\n"62        color_idx = 063        for step in self.steps:64            if step.step_kind in (65                StepKind.FUNC,66                StepKind.FUNC_EXTERNAL,67                StepKind.FUNC_UNKNOWN,68            ):69                color_idx += 170 71            color = colors[color_idx % len(colors)]72            st += "<{}>{}</>\n".format(color, step)73        st += "## END ({} step{}) ##\n".format(74            self.num_steps, "" if self.num_steps == 1 else "s"75        )76        return st77 78    @property79    def num_steps(self):80        return len(self.steps)81 82    def _get_prev_step_in_this_frame(self, step):83        """Find the most recent step in the same frame as `step`.84 85        Returns:86            StepIR or None if there is no previous step in this frame.87        """88        return next(89            (90                s91                for s in reversed(self.steps)92                if s.current_function == step.current_function93                and s.num_frames == step.num_frames94            ),95            None,96        )97 98    def _get_new_step_kind(self, context, step):99        if step.current_function is None:100            return StepKind.UNKNOWN101 102        if len(self.steps) == 0:103            return _step_kind_func(context, step)104 105        prev_step = self.steps[-1]106 107        if prev_step.current_function is None:108            return StepKind.UNKNOWN109 110        if prev_step.num_frames < step.num_frames:111            return _step_kind_func(context, step)112 113        if prev_step.num_frames > step.num_frames:114            frame_step = self._get_prev_step_in_this_frame(step)115            prev_step = frame_step if frame_step is not None else prev_step116 117        # If we're missing line numbers to compare then the step kind has to be UNKNOWN.118        if (119            prev_step.current_location.lineno is None120            or step.current_location.lineno is None121        ):122            return StepKind.UNKNOWN123 124        # We're in the same func as prev step, check lineo.125        if prev_step.current_location.lineno > step.current_location.lineno:126            return StepKind.VERTICAL_BACKWARD127 128        if prev_step.current_location.lineno < step.current_location.lineno:129            return StepKind.VERTICAL_FORWARD130 131        # We're on the same line as prev step, check column.132        if prev_step.current_location.column > step.current_location.column:133            return StepKind.HORIZONTAL_BACKWARD134 135        if prev_step.current_location.column < step.current_location.column:136            return StepKind.HORIZONTAL_FORWARD137 138        # This step is in exactly the same location as the prev step.139        return StepKind.SAME140 141    def new_step(self, context, step):142        assert isinstance(step, StepIR), type(step)143        step.step_kind = self._get_new_step_kind(context, step)144        self.steps.append(step)145        return step146 147    def clear_steps(self):148        self.steps.clear()149