brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.3 KiB · ee7ccae Raw
206 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "ValueMatcher.h"10#include "llvm/Support/Format.h"11#include "llvm/Support/InterleavedRange.h"12#include "llvm/Support/raw_os_ostream.h"13#include "llvm/Support/raw_ostream.h"14 15using namespace lldb_private;16 17static void FormatValueDetails(llvm::raw_ostream &os,18                               Value::ValueType value_type,19                               Value::ContextType context_type,20                               const Scalar &scalar,21                               llvm::ArrayRef<uint8_t> buffer_data) {22  os << "Value(";23  os << "value_type=" << Value::GetValueTypeAsCString(value_type);24  os << ", context_type=" << Value::GetContextTypeAsCString(context_type);25 26  if (value_type == Value::ValueType::HostAddress) {27    auto bytes_to_print = buffer_data.take_front(16);28    os << ", buffer=[";29    llvm::interleave(30        bytes_to_print,31        [&](uint8_t byte) {32          os << llvm::format("%02x", static_cast<unsigned>(byte));33        },34        [&]() { os << " "; });35    if (buffer_data.size() > 16)36      os << " ...";37    os << "] (" << buffer_data.size() << " bytes)";38  } else {39    os << ", value=" << scalar;40  }41  os << ")";42}43 44void lldb_private::PrintTo(const Value &val, std::ostream *os) {45  if (!os)46    return;47 48  llvm::raw_os_ostream raw_os(*os);49  FormatValueDetails(raw_os, val.GetValueType(), val.GetContextType(),50                     val.GetScalar(), val.GetBuffer().GetData());51}52 53bool ValueMatcher::MatchAndExplain(const Value &val,54                                   std::ostream *stream) const {55  if (stream) {56    llvm::raw_os_ostream os(*stream);57    return MatchAndExplainImpl(val, os);58  }59 60  llvm::raw_null_ostream os;61  return MatchAndExplainImpl(val, os);62}63 64// Match the provided value and explain any mismatches using65// the raw_ostream. We use the llvm::raw_ostream here to simplify the formatting66// of Scalar values which already know how to print themselves to that stream.67bool ValueMatcher::MatchAndExplainImpl(const Value &val,68                                       llvm::raw_ostream &os) const {69  if (val.GetValueType() != m_value_type) {70    os << "value_type mismatch: expected "71       << Value::GetValueTypeAsCString(m_value_type) << ", got "72       << Value::GetValueTypeAsCString(val.GetValueType()) << " ";73    return false;74  }75 76  if (val.GetContextType() != m_context_type) {77    os << "context_type mismatch: expected "78       << Value::GetContextTypeAsCString(m_context_type) << ", got "79       << Value::GetContextTypeAsCString(val.GetContextType()) << " ";80    return false;81  }82 83  if (m_value_type == Value::ValueType::HostAddress) {84    const DataBufferHeap &buffer = val.GetBuffer();85    const size_t buffer_size = buffer.GetByteSize();86    if (buffer_size != m_expected_bytes.size()) {87      os << "buffer size mismatch: expected " << m_expected_bytes.size()88         << ", got " << buffer_size << " ";89      return false;90    }91 92    const uint8_t *data = buffer.GetBytes();93    for (size_t i = 0; i < buffer_size; ++i) {94      if (data[i] != m_expected_bytes[i]) {95        os << "byte mismatch at index " << i << ": expected "96           << llvm::format("0x%02x", static_cast<unsigned>(m_expected_bytes[i]))97           << ", got " << llvm::format("0x%02x", static_cast<unsigned>(data[i]))98           << " ";99        return false;100      }101    }102  } else {103    // For Scalar, FileAddress, and LoadAddress compare m_value.104    const Scalar &actual_scalar = val.GetScalar();105    if (actual_scalar != m_expected_scalar) {106      os << "scalar value mismatch: expected " << m_expected_scalar << ", got "107         << actual_scalar;108      return false;109    }110  }111 112  return true;113}114 115void ValueMatcher::DescribeTo(std::ostream *os) const {116  if (!os)117    return;118  llvm::raw_os_ostream raw_os(*os);119  FormatValueDetails(raw_os, m_value_type, m_context_type, m_expected_scalar,120                     m_expected_bytes);121}122 123void ValueMatcher::DescribeNegationTo(std::ostream *os) const {124  if (!os)125    return;126  *os << "value does not match";127}128 129testing::Matcher<Value>130lldb_private::MatchScalarValue(Value::ValueType value_type,131                               const Scalar &expected_scalar,132                               Value::ContextType context_type) {133  return ValueMatcher(value_type, expected_scalar, context_type);134}135 136testing::Matcher<Value>137lldb_private::MatchHostValue(Value::ValueType value_type,138                             const std::vector<uint8_t> &expected_bytes,139                             Value::ContextType context_type) {140  return ValueMatcher(value_type, expected_bytes, context_type);141}142 143testing::Matcher<Value>144lldb_private::IsScalar(const Scalar &expected_scalar,145                       Value::ContextType context_type) {146  return MatchScalarValue(Value::ValueType::Scalar, expected_scalar,147                          context_type);148}149 150testing::Matcher<Value>151lldb_private::IsLoadAddress(const Scalar &expected_address,152                            Value::ContextType context_type) {153  return MatchScalarValue(Value::ValueType::LoadAddress, expected_address,154                          context_type);155}156 157testing::Matcher<Value>158lldb_private::IsFileAddress(const Scalar &expected_address,159                            Value::ContextType context_type) {160  return MatchScalarValue(Value::ValueType::FileAddress, expected_address,161                          context_type);162}163 164testing::Matcher<Value>165lldb_private::IsHostValue(const std::vector<uint8_t> &expected_bytes,166                          Value::ContextType context_type) {167  return MatchHostValue(Value::ValueType::HostAddress, expected_bytes,168                        context_type);169}170 171Scalar lldb_private::GetScalar(unsigned bits, uint64_t value, bool sign) {172  Scalar scalar(value);173  scalar.TruncOrExtendTo(bits, sign);174  return scalar;175}176 177llvm::detail::ValueMatchesPoly<testing::Matcher<Value>>178lldb_private::ExpectScalar(const Scalar &expected_scalar,179                           Value::ContextType context_type) {180  return llvm::HasValue(IsScalar(expected_scalar, context_type));181}182 183llvm::detail::ValueMatchesPoly<testing::Matcher<Value>>184lldb_private::ExpectScalar(unsigned bits, uint64_t value, bool sign,185                           Value::ContextType context_type) {186  return ExpectScalar(GetScalar(bits, value, sign), context_type);187}188 189llvm::detail::ValueMatchesPoly<testing::Matcher<Value>>190lldb_private::ExpectLoadAddress(const Scalar &expected_address,191                                Value::ContextType context_type) {192  return llvm::HasValue(IsLoadAddress(expected_address, context_type));193}194 195llvm::detail::ValueMatchesPoly<testing::Matcher<Value>>196lldb_private::ExpectFileAddress(const Scalar &expected_address,197                                Value::ContextType context_type) {198  return llvm::HasValue(IsFileAddress(expected_address, context_type));199}200 201llvm::detail::ValueMatchesPoly<testing::Matcher<Value>>202lldb_private::ExpectHostAddress(const std::vector<uint8_t> &expected_bytes,203                                Value::ContextType context_type) {204  return llvm::HasValue(IsHostValue(expected_bytes, context_type));205}206