1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
# 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
"""Set of data classes for representing the complete debug program state at a
fixed point in execution.
"""
import os
from collections import OrderedDict
from pathlib import PurePath
from typing import List
class SourceLocation:
def __init__(self, path: str = None, lineno: int = None, column: int = None):
if path:
path = os.path.normcase(path)
self.path = path
self.lineno = lineno
self.column = column
def __str__(self):
return "{}({}:{})".format(self.path, self.lineno, self.column)
def match(self, other) -> bool:
"""Returns true iff all the properties that appear in `self` have the
same value in `other`, but not necessarily vice versa.
"""
if not other or not isinstance(other, SourceLocation):
return False
if self.path and (
other.path is None or (PurePath(self.path) != PurePath(other.path))
):
return False
if self.lineno and (self.lineno != other.lineno):
return False
if self.column and (self.column != other.column):
return False
return True
class StackFrame:
def __init__(
self,
function: str = None,
is_inlined: bool = None,
location: SourceLocation = None,
watches: OrderedDict = None,
):
if watches is None:
watches = {}
self.function = function
self.is_inlined = is_inlined
self.location = location
self.watches = watches
def __str__(self):
return "{}{}: {} | {}".format(
self.function,
" (inlined)" if self.is_inlined else "",
self.location,
{k: str(self.watches[k]) for k in self.watches},
)
def match(self, other) -> bool:
"""Returns true iff all the properties that appear in `self` have the
same value in `other`, but not necessarily vice versa.
"""
if not other or not isinstance(other, StackFrame):
return False
if self.location and not self.location.match(other.location):
return False
if self.watches:
for name in iter(self.watches):
try:
if isinstance(self.watches[name], dict):
for attr in iter(self.watches[name]):
if (
getattr(other.watches[name], attr, None)
!= self.watches[name][attr]
):
return False
else:
if other.watches[name].value != self.watches[name]:
return False
except KeyError:
return False
return True
class ProgramState:
def __init__(self, frames: List[StackFrame] = None):
self.frames = frames
def __str__(self):
return "\n".join(
map(
lambda enum: "Frame {}: {}".format(enum[0], enum[1]),
enumerate(self.frames),
)
)
def match(self, other) -> bool:
"""Returns true iff all the properties that appear in `self` have the
same value in `other`, but not necessarily vice versa.
"""
if not other or not isinstance(other, ProgramState):
return False
if self.frames:
for idx, frame in enumerate(self.frames):
try:
if not frame.match(other.frames[idx]):
return False
except (IndexError, KeyError):
return False
return True
|