Files
clang-p2996/cross-project-tests/debuginfo-tests/dexter/dex/dextIR/ProgramState.py
Stephen Tozer b03451bb9a [Dexter] Use PurePath to compare paths in Dexter commands
Prior to this patch, when comparing the paths of source files in Dexter
commands, we would use os.samefile. This function performs actual file
operations and requires the files to exist on the current system; this
is suitable when running the test for the first time, but renders the
DextIR output files non-portable, and unusable if the source files no
longer exist in their original location.

Differential Revision: https://reviews.llvm.org/D127099
2022-06-08 16:28:27 +01:00

119 lines
3.8 KiB
Python

# 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