mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
175 lines
5.1 KiB
C++
175 lines
5.1 KiB
C++
/// \file stackanalysis.cpp
|
|
/// \brief Tests for StackAnalysis data structures
|
|
|
|
//
|
|
// This file is distributed under the MIT License. See LICENSE.md for details.
|
|
//
|
|
|
|
// Standard includes
|
|
|
|
// Boost includes
|
|
#define BOOST_TEST_MODULE StackAnalysis
|
|
#include <boost/test/unit_test.hpp>
|
|
|
|
// Local includes
|
|
#include "stackanalysis_impl.h"
|
|
|
|
using namespace StackAnalysis;
|
|
|
|
BOOST_TEST_DONT_PRINT_LOG_VALUE(ASID)
|
|
BOOST_TEST_DONT_PRINT_LOG_VALUE(ASSlot)
|
|
BOOST_TEST_DONT_PRINT_LOG_VALUE(std::vector<ASID>)
|
|
|
|
static_assert(ASID::RestOfTheStackID == ASID::LastStackID - 1,
|
|
"We expect RST to be right before SP0");
|
|
|
|
const ASID SP0 = ASID::lastStackID();
|
|
const ASID SP1 = ASID(SP0.id() + 1);
|
|
const ASID GLB = ASID::globalID();
|
|
const ASID CPU = ASID::cpuID();
|
|
const ASID RST = ASID::restOfTheStackID();
|
|
const ASID DED = ASID::deadStackID();
|
|
const ASID Invalid = ASID::invalidID();
|
|
|
|
using ASVector = std::vector<ASID>;
|
|
ASVector toVector(ASSet S) {
|
|
ASVector Result;
|
|
std::copy(S.begin(), S.end(), std::back_inserter(Result));
|
|
return Result;
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(TestAddressSpaceID) {
|
|
// Test ordering
|
|
BOOST_TEST(SP0.lowerThanOrEqual(SP0, Invalid));
|
|
BOOST_TEST(!SP0.greaterThan(SP0, Invalid));
|
|
BOOST_TEST(SP0.greaterThan(SP1, Invalid));
|
|
BOOST_TEST(SP0.greaterThan(GLB, Invalid));
|
|
|
|
BOOST_TEST(SP0.greaterThan(RST, Invalid));
|
|
BOOST_TEST(RST.greaterThan(SP0, Invalid));
|
|
BOOST_TEST(SP1.lowerThanOrEqual(RST, SP0));
|
|
BOOST_TEST(SP0.greaterThan(RST, SP0));
|
|
|
|
// Test moving and capping
|
|
BOOST_TEST(SP0.getCallerStack(Invalid.id()) == SP1);
|
|
BOOST_TEST(SP0.getCallerStack(SP0.id()) == RST);
|
|
|
|
BOOST_TEST(SP0.shiftAddressSpaces(+1) == SP1);
|
|
BOOST_TEST(SP1.shiftAddressSpaces(-1) == SP0);
|
|
BOOST_TEST(SP0.shiftAddressSpaces(-1) == DED);
|
|
BOOST_TEST(SP1.shiftAddressSpaces(-2) == DED);
|
|
BOOST_TEST(CPU.shiftAddressSpaces(-1) == CPU);
|
|
BOOST_TEST(CPU.shiftAddressSpaces(+1) == CPU);
|
|
BOOST_TEST(GLB.shiftAddressSpaces(-1) == GLB);
|
|
BOOST_TEST(GLB.shiftAddressSpaces(+1) == GLB);
|
|
|
|
BOOST_TEST(GLB.cap(SP0.id()) == GLB);
|
|
BOOST_TEST(SP0.cap(SP0.id()) == SP0);
|
|
BOOST_TEST(SP1.cap(SP0.id()) == RST);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(TestASFunction) {
|
|
ASID GLB = ASID::globalID();
|
|
ASID CPU = ASID::cpuID();
|
|
|
|
// Test membership and adding element
|
|
ASSet ASF = ASSet::singleElement(CPU);
|
|
BOOST_TEST(toVector(ASF) == (ASVector { CPU }));
|
|
BOOST_TEST(ASF[CPU] == true);
|
|
BOOST_TEST(ASF[GLB] == false);
|
|
|
|
ASF.add(GLB);
|
|
BOOST_TEST(toVector(ASF) == (ASVector { GLB, CPU }));
|
|
BOOST_TEST(ASF[CPU] == true);
|
|
BOOST_TEST(ASF[GLB] == true);
|
|
|
|
ASF.add(RST);
|
|
BOOST_TEST(toVector(ASF) == (ASVector { GLB, CPU, RST }));
|
|
BOOST_TEST(ASF.contains(SP1, SP0));
|
|
BOOST_TEST(!ASF.contains(SP1, SP1));
|
|
|
|
// Test lowerThanOrEqual
|
|
ASSet Other = ASF;
|
|
Other.add(SP0);
|
|
BOOST_TEST(toVector(ASF) == (ASVector { GLB, CPU, RST }));
|
|
BOOST_TEST(toVector(Other) == (ASVector { GLB, CPU, RST, SP0 }));
|
|
BOOST_TEST(ASF.lowerThanOrEqual(Other, Invalid));
|
|
|
|
ASF.add(SP1);
|
|
BOOST_TEST(toVector(ASF) == (ASVector { GLB, CPU, RST, SP1 }));
|
|
BOOST_TEST(ASF.greaterThan(Other, Invalid));
|
|
BOOST_TEST(ASF.lowerThanOrEqual(Other, SP0));
|
|
|
|
// Test combine
|
|
ASSet Tmp;
|
|
Tmp = Other;
|
|
Tmp.combine(ASF, Invalid);
|
|
BOOST_TEST(toVector(Tmp) == (ASVector { GLB, CPU, RST, SP0, SP1 }));
|
|
|
|
Tmp = Other;
|
|
Tmp.combine(ASF, SP0);
|
|
BOOST_TEST(toVector(Tmp) == (ASVector { GLB, CPU, RST, SP0 }));
|
|
|
|
ASSet A = ASSet::singleElement(CPU);
|
|
ASSet B = ASSet::singleElement(SP1);
|
|
Tmp = A;
|
|
Tmp.combine(B, SP0);
|
|
BOOST_TEST(toVector(Tmp) == (ASVector { CPU, RST }));
|
|
|
|
Tmp = A;
|
|
Tmp.combine(B, SP1);
|
|
BOOST_TEST(toVector(Tmp) == (ASVector { CPU, SP1 }));
|
|
|
|
// Test drop
|
|
Tmp = A;
|
|
Tmp.drop(CPU);
|
|
BOOST_TEST(toVector(Tmp) == (ASVector { }));
|
|
BOOST_TEST(Tmp.empty());
|
|
|
|
// Test shiftAddressSpaces
|
|
Tmp = Other;
|
|
BOOST_TEST(toVector(Tmp) == (ASVector { GLB, CPU, RST, SP0 }));
|
|
Tmp.shiftAddressSpaces(+1);
|
|
BOOST_TEST(toVector(Tmp) == (ASVector { GLB, CPU, RST, SP1 }));
|
|
Tmp.shiftAddressSpaces(-1);
|
|
BOOST_TEST(toVector(Tmp) == (ASVector { GLB, CPU, RST, SP0 }));
|
|
Tmp.shiftAddressSpaces(-1);
|
|
BOOST_TEST(toVector(Tmp) == (ASVector { DED, GLB, CPU, RST }));
|
|
|
|
// Test capAddressSpaces
|
|
Tmp = Other;
|
|
BOOST_TEST(toVector(Tmp) == (ASVector { GLB, CPU, RST, SP0 }));
|
|
Tmp.capAddressSpaces(RST.id());
|
|
BOOST_TEST(toVector(Tmp) == (ASVector { GLB, CPU, RST }));
|
|
Tmp.add(SP1);
|
|
BOOST_TEST(toVector(Tmp) == (ASVector { GLB, CPU, RST, SP1 }));
|
|
Tmp.capAddressSpaces(SP0.id());
|
|
BOOST_TEST(toVector(Tmp) == (ASVector { GLB, CPU, RST }));
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(TestASSlot) {
|
|
// Test comparisons
|
|
ASSlot SP1Slot(SP1, 0);
|
|
ASSlot RSTSlot(RST, 0);
|
|
BOOST_TEST(SP1Slot == SP1Slot);
|
|
BOOST_TEST(SP1Slot != RSTSlot);
|
|
BOOST_TEST(SP1Slot.greaterThan(RSTSlot, Invalid));
|
|
BOOST_TEST(SP1Slot.lowerThanOrEqual(RSTSlot, SP0));
|
|
|
|
// Test addition and masking
|
|
SP1Slot.add(-5);
|
|
BOOST_TEST(SP1Slot.offset() == -5);
|
|
SP1Slot.add(+10);
|
|
BOOST_TEST(SP1Slot.offset() == +5);
|
|
SP1Slot.mask(1);
|
|
BOOST_TEST(SP1Slot.offset() == +1);
|
|
|
|
// Test flattening
|
|
BOOST_TEST(toVector(SP1Slot.flatten()) == (ASVector { SP1 }));
|
|
|
|
// Test usage in a map
|
|
std::map<ASSlot, int> Map;
|
|
Map[SP1Slot] = 0;
|
|
BOOST_TEST(Map.count(SP1Slot) != 0U);
|
|
}
|