fsfw/contrib/fsfw_contrib/etl-20.39.4/test/test_intrusive_links.cpp

1399 lines
46 KiB
C++

/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Copyright(c) 2016 John Wellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#include "unit_test_framework.h"
#include "data.h"
#include "etl/intrusive_links.h"
namespace
{
//*******************************************************
// Forward
//*******************************************************
typedef etl::forward_link<0> FLink0;
typedef etl::forward_link<1> FLink1;
struct FData : public FLink0, public FLink1
{
FData(int value_)
: value(value_)
{
}
int value;
};
//*******************************************************
// Bidirectional
//*******************************************************
typedef etl::bidirectional_link<0> BLink0;
typedef etl::bidirectional_link<1> BLink1;
struct BData : public BLink0, public BLink1
{
BData(int value_)
: value(value_)
{
}
int value;
};
//*******************************************************
// Tree
//*******************************************************
typedef etl::tree_link<0> TLink0;
typedef etl::tree_link<1> TLink1;
typedef etl::tree_link<2> TLink2;
struct TData : public TLink0, public TLink1
{
TData(int value_)
: value(value_)
{
}
int value;
};
//*******************************************************
// Mixed
//*******************************************************
struct MData : public FLink0, public BLink1, public TLink2
{
MData(int value_)
: value(value_)
{
}
int value;
};
SUITE(test_intrusive_links)
{
//*************************************************************************
TEST(test_link_forward_link)
{
FData data0(0);
FData data1(1);
FData data2(2);
FData data3(3);
etl::link_clear<FLink0>(data0);
etl::link<FLink0>(data0, data1);
CHECK(data0.FLink0::etl_next == &data1);
etl::link_clear<FLink0>(data0);
etl::link<FLink0>(&data0, data1);
CHECK(data0.FLink0::etl_next == &data1);
etl::link_clear<FLink0>(data0);
etl::link<FLink0>(data0, &data1);
CHECK(data0.FLink0::etl_next == &data1);
etl::link_clear<FLink0>(data0);
etl::link<FLink0>(&data0, &data1);
CHECK(data0.FLink0::etl_next == &data1);
etl::link<FLink0>(data1, data2);
etl::link<FLink0>(data2, data3);
etl::link<FLink0>(data3, nullptr);
etl::link<FLink1>(data3, data2);
etl::link<FLink1>(data2, data1);
etl::link<FLink1>(data1, data0);
etl::link<FLink1>(data0, nullptr);
CHECK(data1.FLink0::etl_next == &data2);
CHECK(data2.FLink0::etl_next == &data3);
CHECK(data3.FLink0::etl_next == nullptr);
CHECK(data3.FLink1::etl_next == &data2);
CHECK(data2.FLink1::etl_next == &data1);
CHECK(data1.FLink1::etl_next == &data0);
CHECK(data0.FLink1::etl_next == nullptr);
FData* pdata;
pdata = static_cast<FData*>(data0.FLink0::etl_next);
CHECK_EQUAL(1, pdata->value);
pdata = static_cast<FData*>(pdata->FLink0::etl_next);
CHECK_EQUAL(2, pdata->value);
pdata = static_cast<FData*>(pdata->FLink0::etl_next);
CHECK_EQUAL(3, pdata->value);
pdata = static_cast<FData*>(data3.FLink1::etl_next);
CHECK_EQUAL(2, pdata->value);
pdata = static_cast<FData*>(pdata->FLink1::etl_next);
CHECK_EQUAL(1, pdata->value);
pdata = static_cast<FData*>(pdata->FLink1::etl_next);
CHECK_EQUAL(0, pdata->value);
}
//*************************************************************************
TEST(test_link_forward_link_get_set)
{
FData data0(0);
FData data1(1);
FData data2(2);
FData data3(3);
// Use reference interface
data0.FLink0::set_next(data1);
data1.FLink0::set_next(data2);
data2.FLink0::set_next(data3);
data3.FLink0::clear();
CHECK(data0.FLink0::get_next() == &data1);
CHECK(data1.FLink0::get_next() == &data2);
CHECK(data2.FLink0::get_next() == &data3);
CHECK(data3.FLink0::get_next() == nullptr);
// Use pointer interface
data3.FLink0::set_next(&data2);
data2.FLink0::set_next(&data1);
data1.FLink0::set_next(&data0);
data0.FLink0::set_next(nullptr);
CHECK(data3.FLink0::get_next() == &data2);
CHECK(data2.FLink0::get_next() == &data1);
CHECK(data1.FLink0::get_next() == &data0);
CHECK(data0.FLink0::get_next() == nullptr);
}
//*************************************************************************
TEST(test_link_forward_link_has_links)
{
FData data0(0);
FData data1(1);
CHECK_FALSE(data0.FLink0::has_next());
data0.FLink0::set_next(data1);
CHECK_TRUE(data0.FLink0::has_next());
}
//*************************************************************************
TEST(test_link_splice_forward_link)
{
FData data0(0);
FData data1(1);
FData data2(2);
FData data3(3);
data0.FLink0::clear();
etl::link_splice<FLink0>(data0, data1);
CHECK(data0.FLink0::etl_next == &data1);
CHECK(data1.FLink0::etl_next == nullptr);
data0.FLink0::clear();
etl::link_splice<FLink0>(data0, &data1);
CHECK(data0.FLink0::etl_next == &data1);
CHECK(data1.FLink0::etl_next == nullptr);
data0.FLink0::clear();
etl::link_splice<FLink0>(&data0, data1);
CHECK(data0.FLink0::etl_next == &data1);
CHECK(data1.FLink0::etl_next == nullptr);
data0.FLink0::clear();
etl::link_splice<FLink0>(&data0, &data1);
CHECK(data0.FLink0::etl_next == &data1);
CHECK(data1.FLink0::etl_next == nullptr);
data0.FLink0::clear();
etl::link_splice<FLink0>(data0, data3);
etl::link_splice<FLink0>(data0, data1);
etl::link_splice<FLink0>(data1, data2);
CHECK(data0.FLink0::etl_next == &data1);
CHECK(data1.FLink0::etl_next == &data2);
CHECK(data2.FLink0::etl_next == &data3);
CHECK(data3.FLink0::etl_next == nullptr);
}
//*************************************************************************
TEST(test_link_splice_forward_link_range)
{
FData data0(0);
FData data1(1);
FData data2(2);
FData data3(3);
FData data4(4);
FData data5(5);
FData data6(6);
FData data7(7);
// First range.
data0.FLink0::clear();
etl::link_splice<FLink0>(data0, data1);
etl::link_splice<FLink0>(data1, data6);
etl::link_splice<FLink0>(data6, data7);
// Second range.
data2.FLink0::clear();
etl::link_splice<FLink0>(data2, data3);
etl::link_splice<FLink0>(data3, data4);
etl::link_splice<FLink0>(data4, data5);
etl::link_splice<FLink0>(data1, data2, data5);
CHECK(data0.FLink0::etl_next == &data1);
CHECK(data1.FLink0::etl_next == &data2);
CHECK(data2.FLink0::etl_next == &data3);
CHECK(data3.FLink0::etl_next == &data4);
CHECK(data4.FLink0::etl_next == &data5);
CHECK(data5.FLink0::etl_next == &data6);
CHECK(data6.FLink0::etl_next == &data7);
CHECK(data7.FLink0::etl_next == nullptr);
// Do it again with a pointer.
// First range.
data0.FLink0::clear();
etl::link_splice<FLink0>(data0, data1);
etl::link_splice<FLink0>(data1, data6);
etl::link_splice<FLink0>(data6, data7);
// Second range.
data2.FLink0::clear();
etl::link_splice<FLink0>(data2, data3);
etl::link_splice<FLink0>(data3, data4);
etl::link_splice<FLink0>(data4, data5);
etl::link_splice<FLink0>(&data1, data2, data5);
CHECK(data0.FLink0::etl_next == &data1);
CHECK(data1.FLink0::etl_next == &data2);
CHECK(data2.FLink0::etl_next == &data3);
CHECK(data3.FLink0::etl_next == &data4);
CHECK(data4.FLink0::etl_next == &data5);
CHECK(data5.FLink0::etl_next == &data6);
CHECK(data6.FLink0::etl_next == &data7);
CHECK(data7.FLink0::etl_next == nullptr);
// Do it again with a nullptr pointer.
// Second range.
data2.FLink0::clear();
etl::link_splice<FLink0>(data2, data3);
etl::link_splice<FLink0>(data3, data4);
etl::link_splice<FLink0>(data4, data5);
etl::link_splice<FLink0>(nullptr, data2, data5);
CHECK(data2.FLink0::etl_next == &data3);
CHECK(data3.FLink0::etl_next == &data4);
CHECK(data4.FLink0::etl_next == &data5);
CHECK(data5.FLink0::etl_next == nullptr);
}
//*************************************************************************
TEST(test_unlink_after_forward_link)
{
FData data0(0);
FData data1(1);
FData data2(2);
FData data3(3);
etl::link<FLink0>(data0, data1);
etl::link<FLink0>(data1, data2);
etl::link<FLink0>(data2, data3);
etl::link<FLink0>(data3, nullptr);
etl::link<FLink1>(data3, data2);
etl::link<FLink1>(data2, data1);
etl::link<FLink1>(data1, data0);
etl::link<FLink1>(data0, nullptr);
etl::unlink_after<FLink0>(data1);
data2.FLink0::clear();
CHECK(data0.FLink0::etl_next == &data1);
CHECK(data1.FLink0::etl_next == &data3);
CHECK(data2.FLink0::etl_next == nullptr);
CHECK(data3.FLink0::etl_next == nullptr);
CHECK(data3.FLink1::etl_next == &data2);
CHECK(data2.FLink1::etl_next == &data1);
CHECK(data1.FLink1::etl_next == &data0);
CHECK(data0.FLink1::etl_next == nullptr);
etl::unlink_after<FLink1>(data2);
data1.FLink1::clear();
CHECK(data0.FLink0::etl_next == &data1);
CHECK(data1.FLink0::etl_next == &data3);
CHECK(data3.FLink0::etl_next == nullptr);
CHECK(data3.FLink1::etl_next == &data2);
CHECK(data2.FLink1::etl_next == &data0);
CHECK(data1.FLink1::etl_next == nullptr);
CHECK(data0.FLink1::etl_next == nullptr);
etl::unlink_after<FLink0>(data3);
etl::unlink_after<FLink1>(data0);
CHECK(data0.FLink0::etl_next == &data1);
CHECK(data1.FLink0::etl_next == &data3);
CHECK(data3.FLink0::etl_next == nullptr);
CHECK(data3.FLink1::etl_next == &data2);
CHECK(data2.FLink1::etl_next == &data0);
CHECK(data0.FLink1::etl_next == nullptr);
}
//*************************************************************************
TEST(test_unlink_after_range_forward_link)
{
FData data0(0);
FData data1(1);
FData data2(2);
FData data3(3);
etl::link<FLink0>(data0, data1);
etl::link<FLink0>(data1, data2);
etl::link<FLink0>(data2, data3);
etl::link<FLink0>(data3, nullptr);
etl::link<FLink1>(data3, data2);
etl::link<FLink1>(data2, data1);
etl::link<FLink1>(data1, data0);
etl::link<FLink1>(data0, nullptr);
FLink0* start = etl::unlink_after<FLink0>(data0, data2);
CHECK(data0.FLink0::etl_next == &data3);
CHECK(data1.FLink0::etl_next == &data2);
CHECK(data2.FLink0::etl_next == nullptr);
CHECK(data3.FLink0::etl_next == nullptr);
etl::link_clear_range(*start);
CHECK(data0.FLink0::etl_next == &data3);
CHECK(data1.FLink0::etl_next == nullptr);
CHECK(data2.FLink0::etl_next == nullptr);
CHECK(data3.FLink0::etl_next == nullptr);
CHECK(data3.FLink1::etl_next == &data2);
CHECK(data2.FLink1::etl_next == &data1);
CHECK(data1.FLink1::etl_next == &data0);
CHECK(data0.FLink1::etl_next == nullptr);
}
//*************************************************************************
TEST(test_self_link_forward_link)
{
FData data0(0);
etl::link<FLink0>(data0, data0);
CHECK(data0.FLink0::etl_next == &data0);
etl::unlink_after<FLink0>(data0);
CHECK(data0.FLink0::etl_next == nullptr);
}
//*************************************************************************
TEST(test_link_bidirectional_link)
{
BData data0(0);
BData data1(1);
BData data2(2);
BData data3(3);
etl::link<BLink0>(nullptr, data0);
data1.BLink0::clear();
etl::link<BLink0>(data0, data1);
CHECK(data0.BLink0::etl_next == &data1);
CHECK(data1.BLink0::etl_previous == &data0);
data1.BLink0::clear();
etl::link<BLink0>(data0, data1);
CHECK(data0.BLink0::etl_next == &data1);
CHECK(data1.BLink0::etl_previous == &data0);
data1.BLink0::clear();
etl::link<BLink0>(data0, data1);
CHECK(data0.BLink0::etl_next == &data1);
CHECK(data1.BLink0::etl_previous == &data0);
data1.BLink0::clear();
etl::link<BLink0>(data0, data1);
CHECK(data0.BLink0::etl_next == &data1);
CHECK(data1.BLink0::etl_previous == &data0);
etl::link<BLink0>(data1, data2);
etl::link<BLink0>(data2, data3);
etl::link<BLink0>(data3, nullptr);
CHECK(data0.BLink0::etl_previous == nullptr);
CHECK(data1.BLink0::etl_previous == &data0);
CHECK(data1.BLink0::etl_next == &data2);
CHECK(data2.BLink0::etl_previous == &data1);
CHECK(data2.BLink0::etl_next == &data3);
CHECK(data3.BLink0::etl_previous == &data2);
CHECK(data3.BLink0::etl_next == nullptr);
etl::link<BLink1>(nullptr, data3);
etl::link<BLink1>(data3, data2);
etl::link<BLink1>(data2, data1);
etl::link<BLink1>(data1, data0);
etl::link<BLink1>(data0, nullptr);
CHECK(data3.BLink1::etl_previous == nullptr);
CHECK(data3.BLink1::etl_next == &data2);
CHECK(data2.BLink1::etl_previous == &data3);
CHECK(data2.BLink1::etl_next == &data1);
CHECK(data1.BLink1::etl_previous == &data2);
CHECK(data1.BLink1::etl_next == &data0);
CHECK(data0.BLink1::etl_previous == &data1);
CHECK(data0.BLink1::etl_next == nullptr);
BData* pdata;
pdata = static_cast<BData*>(data0.BLink0::etl_next);
CHECK_EQUAL(1, pdata->value);
pdata = static_cast<BData*>(pdata->BLink0::etl_next);
CHECK_EQUAL(2, pdata->value);
pdata = static_cast<BData*>(pdata->BLink0::etl_next);
CHECK_EQUAL(3, pdata->value);
pdata = static_cast<BData*>(data3.BLink0::etl_previous);
CHECK_EQUAL(2, pdata->value);
pdata = static_cast<BData*>(pdata->BLink0::etl_previous);
CHECK_EQUAL(1, pdata->value);
pdata = static_cast<BData*>(pdata->BLink0::etl_previous);
CHECK_EQUAL(0, pdata->value);
pdata = static_cast<BData*>(data3.BLink1::etl_next);
CHECK_EQUAL(2, pdata->value);
pdata = static_cast<BData*>(pdata->BLink1::etl_next);
CHECK_EQUAL(1, pdata->value);
pdata = static_cast<BData*>(pdata->BLink1::etl_next);
CHECK_EQUAL(0, pdata->value);
pdata = static_cast<BData*>(data0.BLink1::etl_previous);
CHECK_EQUAL(1, pdata->value);
pdata = static_cast<BData*>(pdata->BLink1::etl_previous);
CHECK_EQUAL(2, pdata->value);
pdata = static_cast<BData*>(pdata->BLink1::etl_previous);
CHECK_EQUAL(3, pdata->value);
data1.BLink0::unlink();
CHECK(data0.BLink0::etl_next == &data2);
CHECK(data2.BLink0::etl_previous == &data0);
CHECK(data3.BLink1::etl_previous == nullptr);
CHECK(data3.BLink1::etl_next == &data2);
CHECK(data2.BLink1::etl_previous == &data3);
CHECK(data2.BLink1::etl_next != nullptr);
CHECK(data0.BLink1::etl_previous != nullptr);
CHECK(data0.BLink1::etl_next == nullptr);
data0.BLink0::unlink();
CHECK(data2.BLink0::etl_next == &data3);
CHECK(data2.BLink0::etl_previous == nullptr);
CHECK(data3.BLink0::etl_previous == &data2);
CHECK(data3.BLink1::etl_previous == nullptr);
CHECK(data3.BLink1::etl_next == &data2);
CHECK(data2.BLink1::etl_previous == &data3);
CHECK(data2.BLink1::etl_next != nullptr);
data3.BLink0::unlink();
CHECK(data2.BLink0::etl_next == nullptr);
CHECK(data2.BLink0::etl_previous == nullptr);
CHECK(data2.BLink1::etl_next != nullptr);
CHECK(data2.BLink1::etl_previous != nullptr);
data2.BLink0::unlink();
}
//*************************************************************************
TEST(test_link_bidirectional_link_get_set)
{
BData data0(0);
BData data1(1);
BData data2(2);
BData data3(3);
// Use reference interface
data0.BLink0::set_next(data1);
data1.BLink0::set_next(data2);
data2.BLink0::set_next(data3);
data1.BLink0::set_previous(data0);
data2.BLink0::set_previous(data1);
data3.BLink0::set_previous(data2);
CHECK(data0.BLink0::get_next() == &data1);
CHECK(data1.BLink0::get_next() == &data2);
CHECK(data2.BLink0::get_next() == &data3);
CHECK(data3.BLink0::get_next() == nullptr);
CHECK(data3.BLink0::get_previous() == &data2);
CHECK(data2.BLink0::get_previous() == &data1);
CHECK(data1.BLink0::get_previous() == &data0);
CHECK(data0.BLink0::get_previous() == nullptr);
// Use pointer interface
data0.BLink0::clear();
data1.BLink0::clear();
data2.BLink0::clear();
data3.BLink0::clear();
data3.BLink0::set_next(&data2);
data2.BLink0::set_next(&data1);
data1.BLink0::set_next(&data0);
data0.BLink0::set_previous(&data1);
data1.BLink0::set_previous(&data2);
data2.BLink0::set_previous(&data3);
CHECK(data3.BLink0::get_next() == &data2);
CHECK(data2.BLink0::get_next() == &data1);
CHECK(data1.BLink0::get_next() == &data0);
CHECK(data0.BLink0::get_next() == nullptr);
CHECK(data0.BLink0::get_previous() == &data1);
CHECK(data1.BLink0::get_previous() == &data2);
CHECK(data2.BLink0::get_previous() == &data3);
CHECK(data3.BLink0::get_previous() == nullptr);
}
//*************************************************************************
TEST(test_link_bidirectional_link_has_links)
{
BData data0(0);
BData data1(1);
BData data2(2);
CHECK_FALSE(data1.BLink0::has_previous());
CHECK_FALSE(data1.BLink0::has_next());
data1.BLink0::set_previous(data0);
CHECK_TRUE(data1.BLink0::has_previous());
CHECK_FALSE(data1.BLink0::has_next());
data1.BLink0::set_next(data2);
CHECK_TRUE(data1.BLink0::has_previous());
CHECK_TRUE(data1.BLink0::has_next());
}
//*************************************************************************
TEST(test_link_splice_bidirectional_link)
{
BData data0(0);
BData data1(1);
BData data2(2);
BData data3(3);
data0.BLink0::clear();
etl::link_splice<BLink0>(nullptr, data0);
etl::link_splice<BLink0>(data0, data1);
CHECK(data0.BLink0::etl_next == &data1);
CHECK(data1.BLink0::etl_previous == &data0);
CHECK(data1.BLink0::etl_next == nullptr);
data0.BLink0::clear();
etl::link_splice<BLink0>(nullptr, data0);
etl::link_splice<BLink0>(data0, &data1);
CHECK(data0.BLink0::etl_next == &data1);
CHECK(data1.BLink0::etl_previous == &data0);
CHECK(data1.BLink0::etl_next == nullptr);
data0.BLink0::clear();
etl::link_splice<BLink0>(nullptr, data0);
etl::link_splice<BLink0>(&data0, data1);
CHECK(data0.BLink0::etl_next == &data1);
CHECK(data1.BLink0::etl_previous == &data0);
CHECK(data1.BLink0::etl_next == nullptr);
data0.BLink0::clear();
etl::link_splice<BLink0>(nullptr, data0);
etl::link_splice<BLink0>(&data0, &data1);
CHECK(data0.BLink0::etl_next == &data1);
CHECK(data1.BLink0::etl_previous == &data0);
CHECK(data1.BLink0::etl_next == nullptr);
data0.BLink0::clear();
etl::link_splice<BLink0>(nullptr, data0);
etl::link_splice<BLink0>(data0, data3);
etl::link_splice<BLink0>(data0, data1);
etl::link_splice<BLink0>(data1, data2);
CHECK(data0.BLink0::etl_previous == nullptr);
CHECK(data0.BLink0::etl_next == &data1);
CHECK(data1.BLink0::etl_previous == &data0);
CHECK(data1.BLink0::etl_next == &data2);
CHECK(data2.BLink0::etl_previous == &data1);
CHECK(data2.BLink0::etl_next == &data3);
CHECK(data3.BLink0::etl_previous == &data2);
CHECK(data3.BLink0::etl_next == nullptr);
}
//*************************************************************************
TEST(test_link_splice_range_bidirectional_link)
{
BData data0(0);
BData data1(1);
BData data2(2);
BData data3(3);
BData data4(4);
BData data5(5);
BData data6(6);
BData data7(7);
// Build the first range.
data0.BLink0::clear();
etl::link_splice<BLink0>(nullptr, data0);
etl::link_splice<BLink0>(data0, data1);
etl::link_splice<BLink0>(data1, data6);
etl::link_splice<BLink0>(data6, data7);
// Build the second range.
data2.BLink0::clear();
etl::link_splice<BLink0>(nullptr, data2);
etl::link_splice<BLink0>(data2, data3);
etl::link_splice<BLink0>(data3, data4);
etl::link_splice<BLink0>(data4, data5);
etl::link_splice<BLink0>(data1, data2, data5);
CHECK(data0.BLink0::etl_previous == nullptr);
CHECK(data0.BLink0::etl_next == &data1);
CHECK(data1.BLink0::etl_previous == &data0);
CHECK(data1.BLink0::etl_next == &data2);
CHECK(data2.BLink0::etl_previous == &data1);
CHECK(data2.BLink0::etl_next == &data3);
CHECK(data3.BLink0::etl_previous == &data2);
CHECK(data3.BLink0::etl_next == &data4);
CHECK(data4.BLink0::etl_previous == &data3);
CHECK(data4.BLink0::etl_next == &data5);
CHECK(data5.BLink0::etl_previous == &data4);
CHECK(data5.BLink0::etl_next == &data6);
CHECK(data6.BLink0::etl_previous == &data5);
CHECK(data6.BLink0::etl_next == &data7);
CHECK(data7.BLink0::etl_previous == &data6);
CHECK(data7.BLink0::etl_next == nullptr);
// Do it again with a pointer parameter.
// Build the first range.
data0.BLink0::clear();
etl::link_splice<BLink0>(nullptr, data0);
etl::link_splice<BLink0>(data0, data1);
etl::link_splice<BLink0>(data1, data6);
etl::link_splice<BLink0>(data6, data7);
// Build the second range.
data2.BLink0::clear();
etl::link_splice<BLink0>(nullptr, data2);
etl::link_splice<BLink0>(data2, data3);
etl::link_splice<BLink0>(data3, data4);
etl::link_splice<BLink0>(data4, data5);
etl::link_splice<BLink0>(&data1, data2, data5);
CHECK(data0.BLink0::etl_previous == nullptr);
CHECK(data0.BLink0::etl_next == &data1);
CHECK(data1.BLink0::etl_previous == &data0);
CHECK(data1.BLink0::etl_next == &data2);
CHECK(data2.BLink0::etl_previous == &data1);
CHECK(data2.BLink0::etl_next == &data3);
CHECK(data3.BLink0::etl_previous == &data2);
CHECK(data3.BLink0::etl_next == &data4);
CHECK(data4.BLink0::etl_previous == &data3);
CHECK(data4.BLink0::etl_next == &data5);
CHECK(data5.BLink0::etl_previous == &data4);
CHECK(data5.BLink0::etl_next == &data6);
CHECK(data6.BLink0::etl_previous == &data5);
CHECK(data6.BLink0::etl_next == &data7);
CHECK(data7.BLink0::etl_previous == &data6);
CHECK(data7.BLink0::etl_next == nullptr);
// Do it again with a nullptr parameter.
// Build the range.
data2.BLink0::clear();
etl::link_splice<BLink0>(nullptr, data2);
etl::link_splice<BLink0>(data2, data3);
etl::link_splice<BLink0>(data3, data4);
etl::link_splice<BLink0>(data4, data5);
etl::link_splice<BLink0>(nullptr, data2, data5);
CHECK(data2.BLink0::etl_previous == nullptr);
CHECK(data2.BLink0::etl_next == &data3);
CHECK(data3.BLink0::etl_previous == &data2);
CHECK(data3.BLink0::etl_next == &data4);
CHECK(data4.BLink0::etl_previous == &data3);
CHECK(data4.BLink0::etl_next == &data5);
CHECK(data5.BLink0::etl_previous == &data4);
CHECK(data5.BLink0::etl_next == nullptr);
}
//*************************************************************************
TEST(test_unlink_bidirectional_link)
{
BData data0(0);
BData data1(1);
BData data2(2);
BData data3(3);
etl::link<BLink0>(nullptr, data0);
etl::link<BLink0>(data0, data1);
etl::link<BLink0>(data1, data2);
etl::link<BLink0>(data2, data3);
etl::link<BLink0>(data3, nullptr);
etl::link<BLink1>(nullptr, data3);
etl::link<BLink1>(data3, data2);
etl::link<BLink1>(data2, data1);
etl::link<BLink1>(data1, data0);
etl::link<BLink1>(data0, nullptr);
etl::unlink<BLink0>(data1);
data1.BLink0::clear();
CHECK(data0.BLink0::etl_previous == nullptr);
CHECK(data0.BLink0::etl_next == &data2);
CHECK(data1.BLink0::etl_previous == nullptr);
CHECK(data1.BLink0::etl_next == nullptr);
CHECK(data2.BLink0::etl_previous == &data0);
CHECK(data2.BLink0::etl_next == &data3);
CHECK(data3.BLink0::etl_previous == &data2);
CHECK(data3.BLink0::etl_next == nullptr);
CHECK(data3.BLink1::etl_previous == nullptr);
CHECK(data3.BLink1::etl_next == &data2);
CHECK(data2.BLink1::etl_previous == &data3);
CHECK(data2.BLink1::etl_next == &data1);
CHECK(data1.BLink1::etl_previous == &data2);
CHECK(data1.BLink1::etl_next == &data0);
CHECK(data0.BLink1::etl_previous == &data1);
CHECK(data0.BLink1::etl_next == nullptr);
etl::unlink<BLink1>(data2);
data2.BLink1::clear();
CHECK(data0.BLink0::etl_previous == nullptr);
CHECK(data0.BLink0::etl_next == &data2);
CHECK(data1.BLink0::etl_previous == nullptr);
CHECK(data1.BLink0::etl_next == nullptr);
CHECK(data2.BLink0::etl_previous == &data0);
CHECK(data2.BLink0::etl_next == &data3);
CHECK(data3.BLink0::etl_previous == &data2);
CHECK(data3.BLink0::etl_next == nullptr);
CHECK(data3.BLink1::etl_previous == nullptr);
CHECK(data3.BLink1::etl_next == &data1);
CHECK(data2.BLink1::etl_previous == nullptr);
CHECK(data2.BLink1::etl_next == nullptr);
CHECK(data1.BLink1::etl_previous == &data3);
CHECK(data1.BLink1::etl_next == &data0);
CHECK(data0.BLink1::etl_previous == &data1);
CHECK(data0.BLink1::etl_next == nullptr);
etl::unlink<BLink0>(data0);
data0.BLink0::clear();
CHECK(data0.BLink0::etl_previous == nullptr);
CHECK(data0.BLink0::etl_next == nullptr);
CHECK(data1.BLink0::etl_previous == nullptr);
CHECK(data1.BLink0::etl_next == nullptr);
CHECK(data2.BLink0::etl_previous == nullptr);
CHECK(data2.BLink0::etl_next == &data3);
CHECK(data3.BLink0::etl_previous == &data2);
CHECK(data3.BLink0::etl_next == nullptr);
CHECK(data3.BLink1::etl_previous == nullptr);
CHECK(data3.BLink1::etl_next == &data1);
CHECK(data2.BLink1::etl_previous == nullptr);
CHECK(data2.BLink1::etl_next == nullptr);
CHECK(data1.BLink1::etl_previous == &data3);
CHECK(data1.BLink1::etl_next == &data0);
CHECK(data0.BLink1::etl_previous == &data1);
CHECK(data0.BLink1::etl_next == nullptr);
etl::unlink<BLink1>(data3);
data3.BLink1::clear();
CHECK(data0.BLink0::etl_previous == nullptr);
CHECK(data0.BLink0::etl_next == nullptr);
CHECK(data1.BLink0::etl_previous == nullptr);
CHECK(data1.BLink0::etl_next == nullptr);
CHECK(data2.BLink0::etl_previous == nullptr);
CHECK(data2.BLink0::etl_next == &data3);
CHECK(data3.BLink0::etl_previous == &data2);
CHECK(data3.BLink0::etl_next == nullptr);
CHECK(data3.BLink1::etl_previous == nullptr);
CHECK(data3.BLink1::etl_next == nullptr);
CHECK(data2.BLink1::etl_previous == nullptr);
CHECK(data2.BLink1::etl_next == nullptr);
CHECK(data1.BLink1::etl_previous == nullptr);
CHECK(data1.BLink1::etl_next == &data0);
CHECK(data0.BLink1::etl_previous == &data1);
CHECK(data0.BLink1::etl_next == nullptr);
}
//*************************************************************************
TEST(test_unlink_range_bidirectional_link)
{
BData data0(0);
BData data1(1);
BData data2(2);
BData data3(3);
etl::link<BLink0>(nullptr, data0);
etl::link<BLink0>(data0, data1);
etl::link<BLink0>(data1, data2);
etl::link<BLink0>(data2, data3);
etl::link<BLink0>(data3, nullptr);
etl::link<BLink1>(nullptr, data3);
etl::link<BLink1>(data3, data2);
etl::link<BLink1>(data2, data1);
etl::link<BLink1>(data1, data0);
etl::link<BLink1>(data0, nullptr);
etl::unlink<BLink0>(data1, data2);
data1.BLink0::clear();
data2.BLink0::clear();
CHECK(data0.BLink0::etl_previous == nullptr);
CHECK(data0.BLink0::etl_next == &data3);
CHECK(data1.BLink0::etl_previous == nullptr);
CHECK(data1.BLink0::etl_next == nullptr);
CHECK(data2.BLink0::etl_previous == nullptr);
CHECK(data2.BLink0::etl_next == nullptr);
CHECK(data3.BLink0::etl_previous == &data0);
CHECK(data3.BLink0::etl_next == nullptr);
CHECK(data3.BLink1::etl_previous == nullptr);
CHECK(data3.BLink1::etl_next == &data2);
CHECK(data2.BLink1::etl_previous == &data3);
CHECK(data2.BLink1::etl_next == &data1);
CHECK(data1.BLink1::etl_previous == &data2);
CHECK(data1.BLink1::etl_next == &data0);
CHECK(data0.BLink1::etl_previous == &data1);
CHECK(data0.BLink1::etl_next == nullptr);
}
//*************************************************************************
TEST(test_self_link_bidirectional_link)
{
BData data0(0);
etl::link<BLink0>(data0, data0);
CHECK(data0.BLink0::etl_previous == &data0);
CHECK(data0.BLink0::etl_next == &data0);
etl::unlink<BLink0>(data0);
CHECK(data0.BLink0::etl_previous == ETL_NULLPTR);
CHECK(data0.BLink0::etl_next == ETL_NULLPTR);
}
//*************************************************************************
TEST(test_tree_link)
{
TData data0(0);
TData data1(1);
TData data2(2);
TData data3(3);
TData data4(4);
TData data5(5);
TData data6(6);
// First link
data0.TLink0::clear();
etl::link_left<TLink0>(data0, data1);
etl::link_right<TLink0>(data0, data2);
CHECK(data0.TLink0::etl_left == &data1);
CHECK(data0.TLink0::etl_right == &data2);
CHECK(data1.TLink0::etl_parent == &data0);
CHECK(data2.TLink0::etl_parent == &data0);
data0.TLink0::clear();
etl::link_left<TLink0>(&data0, data1);
etl::link_right<TLink0>(&data0, data2);
CHECK(data0.TLink0::etl_left == &data1);
CHECK(data0.TLink0::etl_right == &data2);
CHECK(data1.TLink0::etl_parent == &data0);
CHECK(data2.TLink0::etl_parent == &data0);
data0.TLink0::clear();
etl::link_left<TLink0>(data0, &data1);
etl::link_right<TLink0>(data0, &data2);
CHECK(data0.TLink0::etl_left == &data1);
CHECK(data0.TLink0::etl_right == &data2);
CHECK(data1.TLink0::etl_parent == &data0);
CHECK(data2.TLink0::etl_parent == &data0);
data0.TLink0::clear();
etl::link_left<TLink0>(&data0, &data1);
etl::link_right<TLink0>(&data0, &data2);
etl::link_left<TLink0>(data1, data3);
etl::link_right<TLink0>(data1, data4);
etl::link_left<TLink0>(data3, nullptr);
etl::link_right<TLink0>(data3, nullptr);
etl::link_left<TLink0>(data4, nullptr);
etl::link_right<TLink0>(data4, nullptr);
etl::link_left<TLink0>(data2, data5);
etl::link_right<TLink0>(data2, data6);
etl::link_left<TLink0>(data5, nullptr);
etl::link_right<TLink0>(data5, nullptr);
etl::link_left<TLink0>(data6, nullptr);
etl::link_right<TLink0>(data6, nullptr);
// Second link
data0.TLink1::clear();
etl::link_left<TLink1>(&data6, &data4);
etl::link_right<TLink1>(&data6, &data5);
etl::link_left<TLink1>(data4, data0);
etl::link_right<TLink1>(data4, data1);
etl::link_left<TLink1>(data0, nullptr);
etl::link_right<TLink1>(data0, nullptr);
etl::link_left<TLink1>(data1, nullptr);
etl::link_right<TLink1>(data1, nullptr);
etl::link_left<TLink1>(data5, data2);
etl::link_right<TLink1>(data5, data3);
etl::link_left<TLink1>(data2, nullptr);
etl::link_right<TLink1>(data2, nullptr);
etl::link_left<TLink1>(data3, nullptr);
etl::link_right<TLink1>(data3, nullptr);
// Check first
CHECK(data0.TLink0::etl_left == &data1);
CHECK(data0.TLink0::etl_right == &data2);
CHECK(data1.TLink0::etl_parent == &data0);
CHECK(data2.TLink0::etl_parent == &data0);
CHECK(data1.TLink0::etl_left == &data3);
CHECK(data1.TLink0::etl_right == &data4);
CHECK(data3.TLink0::etl_parent == &data1);
CHECK(data3.TLink0::etl_left == nullptr);
CHECK(data3.TLink0::etl_right == nullptr);
CHECK(data4.TLink0::etl_parent == &data1);
CHECK(data4.TLink0::etl_left == nullptr);
CHECK(data4.TLink0::etl_right == nullptr);
CHECK(data2.TLink0::etl_left == &data5);
CHECK(data2.TLink0::etl_right == &data6);
CHECK(data5.TLink0::etl_parent == &data2);
CHECK(data5.TLink0::etl_left == nullptr);
CHECK(data5.TLink0::etl_right == nullptr);
CHECK(data6.TLink0::etl_parent == &data2);
CHECK(data6.TLink0::etl_left == nullptr);
CHECK(data6.TLink0::etl_right == nullptr);
// Check second
CHECK(data6.TLink1::etl_left == &data4);
CHECK(data6.TLink1::etl_right == &data5);
CHECK(data4.TLink1::etl_parent == &data6);
CHECK(data5.TLink1::etl_parent == &data6);
CHECK(data4.TLink1::etl_left == &data0);
CHECK(data4.TLink1::etl_right == &data1);
CHECK(data0.TLink1::etl_parent == &data4);
CHECK(data0.TLink1::etl_left == nullptr);
CHECK(data0.TLink1::etl_right == nullptr);
CHECK(data1.TLink1::etl_parent == &data4);
CHECK(data1.TLink1::etl_left == nullptr);
CHECK(data1.TLink1::etl_right == nullptr);
CHECK(data5.TLink1::etl_left == &data2);
CHECK(data5.TLink1::etl_right == &data3);
CHECK(data2.TLink1::etl_parent == &data5);
CHECK(data2.TLink1::etl_left == nullptr);
CHECK(data2.TLink1::etl_right == nullptr);
CHECK(data3.TLink1::etl_parent == &data5);
CHECK(data3.TLink1::etl_left == nullptr);
CHECK(data3.TLink1::etl_right == nullptr);
}
//*************************************************************************
TEST(test_link_tree_link_get_set)
{
TData dataParent(0);
TData dataNode(1);
TData dataLeft(2);
TData dataRight(3);
// Use reference interface
dataNode.TLink0::set_parent(dataParent);
dataNode.TLink0::set_left(dataLeft);
dataNode.TLink0::set_right(dataRight);
CHECK(dataNode.TLink0::get_parent() == &dataParent);
CHECK(dataNode.TLink0::get_left() == &dataLeft);
CHECK(dataNode.TLink0::get_right() == &dataRight);
// Use pointer interface
dataNode.TLink0::clear();
dataNode.TLink0::set_parent(&dataParent);
dataNode.TLink0::set_left(&dataLeft);
dataNode.TLink0::set_right(&dataRight);
CHECK(dataNode.TLink0::get_parent() == &dataParent);
CHECK(dataNode.TLink0::get_left() == &dataLeft);
CHECK(dataNode.TLink0::get_right() == &dataRight);
}
//*************************************************************************
TEST(test_link_tree_link_has_links)
{
TData dataParent(0);
TData dataNode(1);
TData dataLeft(2);
TData dataRight(3);
CHECK_FALSE(dataNode.TLink0::has_parent());
CHECK_FALSE(dataNode.TLink0::has_left());
CHECK_FALSE(dataNode.TLink0::has_right());
dataNode.TLink0::set_parent(dataParent);
CHECK_TRUE(dataNode.TLink0::has_parent());
CHECK_FALSE(dataNode.TLink0::has_left());
CHECK_FALSE(dataNode.TLink0::has_right());
dataNode.TLink0::set_left(dataLeft);
CHECK_TRUE(dataNode.TLink0::has_parent());
CHECK_TRUE(dataNode.TLink0::has_left());
CHECK_FALSE(dataNode.TLink0::has_right());
dataNode.TLink0::set_right(dataRight);
CHECK_TRUE(dataNode.TLink0::has_parent());
CHECK_TRUE(dataNode.TLink0::has_left());
CHECK_TRUE(dataNode.TLink0::has_right());
}
//*************************************************************************
TEST(test_link_tree_link_mirror)
{
TData dataParent(0);
TData dataNode(1);
TData dataLeft(2);
TData dataRight(3);
dataNode.TLink0::set_parent(dataParent);
dataNode.TLink0::set_left(dataLeft);
dataNode.TLink0::set_right(dataRight);
dataNode.TLink0::mirror();
CHECK(dataNode.TLink0::get_parent() == &dataParent);
CHECK(dataNode.TLink0::get_left() == &dataRight);
CHECK(dataNode.TLink0::get_right() == &dataLeft);
}
//*************************************************************************
TEST(test_is_linked)
{
// Forward link
FData fdata(0);
fdata.FLink0::clear();
fdata.FLink1::clear();
CHECK(!fdata.FLink0::is_linked());
CHECK(!fdata.FLink1::is_linked());
etl::link<FLink0>(fdata, fdata);
CHECK(fdata.FLink0::is_linked());
CHECK(!fdata.FLink1::is_linked());
etl::link<FLink1>(fdata, fdata);
CHECK(fdata.FLink0::is_linked());
CHECK(fdata.FLink1::is_linked());
// Bidirectional link
BData bdata(0);
bdata.BLink0::clear();
bdata.BLink1::clear();
CHECK(!bdata.BLink0::is_linked());
CHECK(!bdata.BLink1::is_linked());
etl::link<BLink0>(bdata, bdata);
CHECK(bdata.BLink0::is_linked());
CHECK(!bdata.BLink1::is_linked());
etl::link<BLink1>(bdata, bdata);
CHECK(bdata.BLink0::is_linked());
CHECK(bdata.BLink1::is_linked());
etl::unlink<BLink0>(bdata); // Global API
CHECK(!bdata.BLink0::is_linked());
CHECK(bdata.BLink1::is_linked());
bdata.BLink1::unlink(); // Member API
CHECK(!bdata.BLink0::is_linked());
CHECK(!bdata.BLink1::is_linked());
bdata.BLink0::clear();
CHECK(!bdata.BLink0::is_linked());
CHECK(!bdata.BLink1::is_linked());
// Tree link
TData tdata(0);
tdata.TLink0::clear();
tdata.TLink1::clear();
CHECK(!tdata.TLink0::is_linked());
CHECK(!tdata.TLink1::is_linked());
etl::link_left<TLink0>(tdata, tdata);
CHECK(tdata.TLink0::is_linked());
CHECK(!tdata.TLink1::is_linked());
etl::link_right<TLink1>(tdata, tdata);
CHECK(tdata.TLink0::is_linked());
CHECK(tdata.TLink1::is_linked());
}
//*************************************************************************
TEST(test_link_mixed_links)
{
MData data0(0);
MData data1(1);
MData data2(2);
MData data3(3);
MData data4(4);
MData data5(5);
MData data6(6);
// Forward
data0.FLink0::clear();
etl::link<FLink0>(data0, data1);
etl::link<FLink0>(data1, data2);
etl::link<FLink0>(data2, data3);
etl::link<FLink0>(data3, nullptr);
// Bidirectional
etl::link<BLink1>(nullptr, data3);
etl::link<BLink1>(data3, data2);
etl::link<BLink1>(data2, data1);
etl::link<BLink1>(data1, data0);
etl::link<BLink1>(data0, nullptr);
// Tree
data0.TLink2::clear();
etl::link_left<TLink2>(data0, data1);
etl::link_right<TLink2>(data0, data2);
etl::link_left<TLink2>(data1, data3);
etl::link_right<TLink2>(data1, data4);
etl::link_left<TLink2>(data3, nullptr);
etl::link_right<TLink2>(data3, nullptr);
etl::link_left<TLink2>(data4, nullptr);
etl::link_right<TLink2>(data4, nullptr);
etl::link_left<TLink2>(data2, data5);
etl::link_right<TLink2>(data2, data6);
etl::link_left<TLink2>(data5, nullptr);
etl::link_right<TLink2>(data5, nullptr);
etl::link_left<TLink2>(data6, nullptr);
etl::link_right<TLink2>(data6, nullptr);
CHECK(data0.FLink0::etl_next == &data1);
CHECK(data1.FLink0::etl_next == &data2);
CHECK(data2.FLink0::etl_next == &data3);
CHECK(data3.FLink0::etl_next == nullptr);
CHECK(data3.BLink1::etl_previous == nullptr);
CHECK(data3.BLink1::etl_next == &data2);
CHECK(data2.BLink1::etl_previous == &data3);
CHECK(data2.BLink1::etl_next == &data1);
CHECK(data1.BLink1::etl_previous == &data2);
CHECK(data1.BLink1::etl_next == &data0);
CHECK(data0.BLink1::etl_previous == &data1);
CHECK(data0.BLink1::etl_next == nullptr);
CHECK(data0.TLink2::etl_left == &data1);
CHECK(data0.TLink2::etl_right == &data2);
CHECK(data1.TLink2::etl_parent == &data0);
CHECK(data2.TLink2::etl_parent == &data0);
CHECK(data1.TLink2::etl_left == &data3);
CHECK(data1.TLink2::etl_right == &data4);
CHECK(data3.TLink2::etl_parent == &data1);
CHECK(data3.TLink2::etl_left == nullptr);
CHECK(data3.TLink2::etl_right == nullptr);
CHECK(data4.TLink2::etl_parent == &data1);
CHECK(data4.TLink2::etl_left == nullptr);
CHECK(data4.TLink2::etl_right == nullptr);
CHECK(data2.TLink2::etl_left == &data5);
CHECK(data2.TLink2::etl_right == &data6);
CHECK(data5.TLink2::etl_parent == &data2);
CHECK(data5.TLink2::etl_left == nullptr);
CHECK(data5.TLink2::etl_right == nullptr);
CHECK(data6.TLink2::etl_parent == &data2);
CHECK(data6.TLink2::etl_left == nullptr);
CHECK(data6.TLink2::etl_right == nullptr);
}
//*************************************************************************
TEST(test_tree_link_rotate_left)
{
TLink0 r;
TLink0 a;
TLink0 b;
TLink0 c;
TLink0 d;
TLink0 e;
r.clear();
c.clear();
d.clear();
e.clear();
etl::link_left(r, b);
etl::link_right(b, a);
etl::link_left(b, d);
etl::link_right(a, c);
etl::link_left(a, e);
etl::link_rotate_left(b, a);
CHECK(a.etl_parent == &r);
CHECK(b.etl_parent == &a);
CHECK(e.etl_parent == &b);
CHECK(d.etl_parent == &b);
CHECK(c.etl_parent == &a);
CHECK(a.etl_left == &b);
CHECK(a.etl_right == &c);
CHECK(b.etl_left == &d);
CHECK(b.etl_right == &e);
}
//*************************************************************************
TEST(test_tree_link_rotate_left_nullptr)
{
TLink0 r;
TLink0 a;
TLink0 b;
TLink0 c;
TLink0 d;
r.clear();
a.clear();
c.clear();
d.clear();
etl::link_left(r, b);
etl::link_right(b, a);
etl::link_left(b, d);
etl::link_right(a, c);
etl::link_rotate_left(b, a);
CHECK(a.etl_parent == &r);
CHECK(b.etl_parent == &a);
CHECK(d.etl_parent == &b);
CHECK(c.etl_parent == &a);
CHECK(a.etl_left == &b);
CHECK(a.etl_right == &c);
CHECK(b.etl_left == &d);
CHECK(b.etl_right == nullptr);
}
//*************************************************************************
TEST(test_tree_link_rotate_right)
{
TLink0 r;
TLink0 a;
TLink0 b;
TLink0 c;
TLink0 d;
TLink0 e;
r.clear();
c.clear();
d.clear();
e.clear();
etl::link_left(r, a);
etl::link_left(a, b);
etl::link_left(b, d);
etl::link_right(a, c);
etl::link_right(b, e);
etl::link_rotate_right(a, b);
CHECK(b.etl_parent == &r);
CHECK(d.etl_parent == &b);
CHECK(a.etl_parent == &b);
CHECK(e.etl_parent == &a);
CHECK(c.etl_parent == &a);
CHECK(b.etl_left == &d);
CHECK(b.etl_right == &a);
CHECK(a.etl_left == &e);
CHECK(a.etl_right == &c);
}
//*************************************************************************
TEST(test_tree_link_rotate_right_nullptr)
{
TLink0 r;
TLink0 a;
TLink0 b;
TLink0 c;
TLink0 d;
r.clear();
b.clear();
c.clear();
d.clear();
etl::link_left(r, a);
etl::link_left(a, b);
etl::link_left(b, d);
etl::link_right(a, c);
etl::link_rotate_right(a, b);
CHECK(b.etl_parent == &r);
CHECK(d.etl_parent == &b);
CHECK(a.etl_parent == &b);
CHECK(c.etl_parent == &a);
CHECK(b.etl_left == &d);
CHECK(b.etl_right == &a);
CHECK(a.etl_left == nullptr);
CHECK(a.etl_right == &c);
}
};
}