mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
247879f7fc
This commit switches `model::Type::ID` from being a GUID to be a progressive number, in order to make things easier for humans. On top of this, this commit introduces the following changes: * TypeCopier: import all the necessary PrimitiveTypes and improve handling of CustomName. * Move Kind as the last field of the key of each TupleTree type used in an `UpcastablePointer`. * Update the ground truth of tests to ignore the `CustomName` in favor of focusing on `OriginalName`. * Increase adoption of `model::Binary::makeType`, equivalent to `Binary.recordNewType(makeType<model::*Type>())`.
150 lines
5.4 KiB
C++
150 lines
5.4 KiB
C++
//
|
|
// This file is distributed under the MIT License. See LICENSE.md for details.
|
|
//
|
|
|
|
#define BOOST_TEST_MODULE location
|
|
bool init_unit_test();
|
|
#include "boost/test/unit_test.hpp"
|
|
|
|
#include "revng/Model/Binary.h"
|
|
#include "revng/Pipeline/Location.h"
|
|
#include "revng/Pipes/Ranks.h"
|
|
#include "revng/Support/BasicBlockID.h"
|
|
|
|
BOOST_AUTO_TEST_SUITE(RevngLocationInfrastructure);
|
|
|
|
BOOST_AUTO_TEST_CASE(DefinitionStyles) {
|
|
namespace ranks = revng::ranks;
|
|
|
|
const auto A0 = MetaAddress::fromString("0x1:Generic64");
|
|
const auto A1 = BasicBlockID::fromString("0x2:Generic64");
|
|
const auto A2 = MetaAddress::fromString("0x3:Generic64");
|
|
auto Location = pipeline::location(ranks::Instruction, A0, A1, A2);
|
|
|
|
constexpr auto S = "/instruction/0x1:Generic64/0x2:Generic64/0x3:Generic64";
|
|
auto MaybeInstruction = pipeline::locationFromString(ranks::Instruction, S);
|
|
revng_check(MaybeInstruction.has_value());
|
|
|
|
revng_check(Location.tuple() == MaybeInstruction->tuple());
|
|
revng_check(Location.toString() == S);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(MetaAddressAsTheKey) {
|
|
namespace ranks = revng::ranks;
|
|
|
|
const auto A0 = MetaAddress::fromString("0x123:Generic64");
|
|
const auto A1 = BasicBlockID::fromString("0x456:Generic64");
|
|
const auto A2 = MetaAddress::fromString("0x789:Generic64");
|
|
auto Location = pipeline::location(ranks::Instruction, A0, A1, A2);
|
|
|
|
revng_check(std::get<0>(Location.at(ranks::Function)).address() == 0x123);
|
|
revng_check(Location.at(ranks::BasicBlock).start().address() == 0x456);
|
|
revng_check(Location.at(ranks::Instruction).address() == 0x789);
|
|
|
|
constexpr auto Expected = "/instruction/0x123:Generic64/"
|
|
"0x456:Generic64/0x789:Generic64";
|
|
revng_check(Location.toString() == Expected);
|
|
revng_check(Location.toString() == serializeToString(Location));
|
|
}
|
|
|
|
static model::TypePath makeFunction(model::Binary &Model) {
|
|
model::CABIFunctionType Function;
|
|
Function.CustomName() = "my_cool_func";
|
|
Function.OriginalName() = "Function_at_0x40012f:Code_x86_64";
|
|
Function.ABI() = model::ABI::SystemV_x86_64;
|
|
|
|
using UT = model::UpcastableType;
|
|
auto Ptr = UT::make<model::CABIFunctionType>(std::move(Function));
|
|
|
|
return Model.recordNewType(std::move(Ptr));
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(TypeIDAsTheKey) {
|
|
TupleTree<model::Binary> NewModel;
|
|
auto Function = makeFunction(*NewModel);
|
|
|
|
namespace ranks = revng::ranks;
|
|
auto FieldLocation = pipeline::location(ranks::UnionField,
|
|
Function.get()->key(),
|
|
2);
|
|
|
|
auto FetchedPath = NewModel->getTypePath(FieldLocation.at(ranks::Type));
|
|
revng_check(FetchedPath.getConst()->name() == "my_cool_func");
|
|
|
|
std::string ID = Function.toString();
|
|
ID = ID.substr(ID.find_last_of('/') + 1);
|
|
revng_check(FieldLocation.toString() == "/union-field/" + ID + "/2");
|
|
revng_check(FieldLocation.toString() == serializeToString(FieldLocation));
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(Serialization) {
|
|
constexpr std::array<std::string_view, 4> TestCases{
|
|
// a list of unrelated serialized locations to use as sources of truth
|
|
"/binary",
|
|
"/instruction/0x12:Generic64/0x34:Generic64/0x56:Generic64",
|
|
"/type/1026-PrimitiveType",
|
|
"/raw-byte-range/0x78:Generic64/0x90:Generic64"
|
|
};
|
|
|
|
using pipeline::locationFromString;
|
|
namespace ranks = revng::ranks;
|
|
for (auto TestCase : TestCases) {
|
|
bool ParsedOnce = false;
|
|
|
|
if (auto Binary = locationFromString(ranks::Binary, TestCase)) {
|
|
revng_check(TestCase == TestCases[0]);
|
|
revng_check(ParsedOnce == false);
|
|
ParsedOnce = true;
|
|
|
|
revng_check(TestCase == Binary->toString());
|
|
}
|
|
|
|
if (auto Instruction = locationFromString(ranks::Instruction, TestCase)) {
|
|
revng_check(TestCase == TestCases[1]);
|
|
revng_check(ParsedOnce == false);
|
|
ParsedOnce = true;
|
|
|
|
auto FunctionMetaAddress = std::get<0>(Instruction->at(ranks::Function));
|
|
revng_check(FunctionMetaAddress.address() == 0x12);
|
|
revng_check(Instruction->at(ranks::BasicBlock).start().address() == 0x34);
|
|
revng_check(Instruction->at(ranks::Instruction).address() == 0x56);
|
|
|
|
revng_check(TestCase == Instruction->toString());
|
|
}
|
|
|
|
if (auto Type = locationFromString(ranks::Type, TestCase)) {
|
|
revng_check(TestCase == TestCases[2]);
|
|
revng_check(ParsedOnce == false);
|
|
ParsedOnce = true;
|
|
|
|
revng_check(std::get<uint64_t>(Type->at(ranks::Type)) == 1026);
|
|
|
|
revng_check(TestCase == Type->toString());
|
|
}
|
|
|
|
if (auto RawRange = locationFromString(ranks::RawByteRange, TestCase)) {
|
|
revng_check(TestCase == TestCases[3]);
|
|
revng_check(ParsedOnce == false);
|
|
ParsedOnce = true;
|
|
|
|
revng_check(RawRange->at(ranks::RawByte).address() == 0x78);
|
|
revng_check(RawRange->at(ranks::RawByteRange).address() == 0x90);
|
|
|
|
revng_check(TestCase == RawRange->toString());
|
|
}
|
|
|
|
revng_check(!locationFromString(ranks::Function, TestCase).has_value());
|
|
revng_check(!locationFromString(ranks::BasicBlock, TestCase).has_value());
|
|
revng_check(!locationFromString(ranks::StructField, TestCase).has_value());
|
|
revng_check(!locationFromString(ranks::UnionField, TestCase).has_value());
|
|
revng_check(!locationFromString(ranks::EnumEntry, TestCase).has_value());
|
|
revng_check(!locationFromString(ranks::RawByte, TestCase).has_value());
|
|
|
|
using namespace std::string_literals;
|
|
revng_check(ParsedOnce,
|
|
("Parsing of '"s + TestCase.data() + "' failed").c_str());
|
|
}
|
|
}
|
|
|
|
BOOST_AUTO_TEST_SUITE_END();
|