mirror of
https://github.com/enduro2d/enduro2d.git
synced 2025-12-15 00:11:55 +07:00
262 lines
7.5 KiB
C++
262 lines
7.5 KiB
C++
/*******************************************************************************
|
|
* This file is part of the "Enduro2D"
|
|
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
|
* Copyright (C) 2018-2020, by Matvey Cherevko (blackmatov@gmail.com)
|
|
******************************************************************************/
|
|
|
|
#include "_utils.hpp"
|
|
using namespace e2d;
|
|
|
|
namespace
|
|
{
|
|
class obj_t : public ref_counter<obj_t> {
|
|
public:
|
|
obj_t() {
|
|
++ctor_counter;
|
|
}
|
|
|
|
obj_t(int ni) : i(ni) {
|
|
++ctor_counter;
|
|
}
|
|
|
|
virtual ~obj_t() noexcept {
|
|
++dtor_counter;
|
|
}
|
|
|
|
int i{42};
|
|
public:
|
|
static int ctor_counter;
|
|
static int dtor_counter;
|
|
static void reset_counters() {
|
|
ctor_counter = 0u;
|
|
dtor_counter = 0u;
|
|
}
|
|
};
|
|
int obj_t::ctor_counter = 0;
|
|
int obj_t::dtor_counter = 0;
|
|
|
|
class derived_t final : public obj_t {
|
|
public:
|
|
derived_t() : obj_t(84) {}
|
|
int j{100500};
|
|
};
|
|
|
|
class derived2_t final : public obj_t {
|
|
public:
|
|
derived2_t() : obj_t(21) {}
|
|
int j{500100};
|
|
};
|
|
|
|
class obj2_t : public ref_counter<obj2_t, ref_counter_thread_unsafe_policy<>> {
|
|
public:
|
|
obj2_t() {
|
|
++ctor_counter;
|
|
}
|
|
|
|
obj2_t(int ni) : i(ni) {
|
|
++ctor_counter;
|
|
}
|
|
|
|
virtual ~obj2_t() noexcept {
|
|
++dtor_counter;
|
|
}
|
|
|
|
int i{42};
|
|
public:
|
|
static int ctor_counter;
|
|
static int dtor_counter;
|
|
static void reset_counters() {
|
|
ctor_counter = 0u;
|
|
dtor_counter = 0u;
|
|
}
|
|
};
|
|
int obj2_t::ctor_counter = 0;
|
|
int obj2_t::dtor_counter = 0;
|
|
}
|
|
|
|
TEST_CASE("intrusive_ptr") {
|
|
{
|
|
intrusive_ptr<obj_t> p;
|
|
REQUIRE_FALSE(p);
|
|
REQUIRE(p.get() == nullptr);
|
|
REQUIRE(p.release() == nullptr);
|
|
}
|
|
{
|
|
obj_t::reset_counters();
|
|
intrusive_ptr<obj_t> p(new obj_t());
|
|
REQUIRE(p);
|
|
REQUIRE(p.get());
|
|
REQUIRE(p.get()->i == 42);
|
|
REQUIRE(p->i == 42);
|
|
REQUIRE((*p).i == 42);
|
|
REQUIRE(p->use_count() == 1u);
|
|
REQUIRE(obj_t::ctor_counter == 1u);
|
|
REQUIRE(obj_t::dtor_counter == 0);
|
|
p.reset();
|
|
REQUIRE_FALSE(p);
|
|
REQUIRE(p.get() == nullptr);
|
|
REQUIRE(p.release() == nullptr);
|
|
REQUIRE(obj_t::dtor_counter == 1u);
|
|
}
|
|
{
|
|
obj_t::reset_counters();
|
|
intrusive_ptr<obj_t> p(new obj_t());
|
|
obj_t* o = p.release();
|
|
REQUIRE_FALSE(p);
|
|
REQUIRE(p.get() == nullptr);
|
|
REQUIRE(obj_t::ctor_counter == 1u);
|
|
REQUIRE(obj_t::dtor_counter == 0u);
|
|
REQUIRE(o->use_count() == 1u);
|
|
|
|
{
|
|
intrusive_ptr<obj_t> p2(o, false);
|
|
REQUIRE(p2);
|
|
REQUIRE(p2->use_count() == 1u);
|
|
|
|
o = p2.release();
|
|
REQUIRE_FALSE(p2);
|
|
|
|
p2.reset(o, false);
|
|
REQUIRE(p2);
|
|
REQUIRE(p2->use_count() == 1u);
|
|
REQUIRE(obj_t::ctor_counter == 1u);
|
|
REQUIRE(obj_t::dtor_counter == 0u);
|
|
|
|
p2.reset(new obj_t());
|
|
REQUIRE(p2);
|
|
REQUIRE(obj_t::ctor_counter == 2u);
|
|
REQUIRE(obj_t::dtor_counter == 1u);
|
|
}
|
|
REQUIRE(obj_t::ctor_counter == 2u);
|
|
REQUIRE(obj_t::dtor_counter == 2u);
|
|
}
|
|
{
|
|
obj_t::reset_counters();
|
|
{
|
|
intrusive_ptr<obj_t> p1(new obj_t(10));
|
|
intrusive_ptr<obj_t> p2(new obj_t(20));
|
|
|
|
p1.swap(p2);
|
|
REQUIRE(p1->i == 20);
|
|
REQUIRE(p2->i == 10);
|
|
}
|
|
REQUIRE(obj_t::ctor_counter == 2u);
|
|
REQUIRE(obj_t::dtor_counter == 2u);
|
|
}
|
|
{
|
|
intrusive_ptr<obj_t> p1(new obj_t(10));
|
|
intrusive_ptr<obj_t> p2(new obj_t(20));
|
|
|
|
{
|
|
intrusive_ptr<obj_t> p3;
|
|
|
|
REQUIRE_FALSE(p2 == nullptr);
|
|
REQUIRE_FALSE(nullptr == p2);
|
|
REQUIRE(p2 != nullptr);
|
|
REQUIRE(nullptr != p2);
|
|
|
|
REQUIRE(p3 == nullptr);
|
|
REQUIRE(nullptr == p3);
|
|
REQUIRE_FALSE(p3 != nullptr);
|
|
REQUIRE_FALSE(nullptr != p3);
|
|
}
|
|
|
|
{
|
|
REQUIRE((p1 == p1) == (p1.get() == p1.get()));
|
|
REQUIRE((p1 != p1) == (p1.get() != p1.get()));
|
|
|
|
REQUIRE((p1 == p1.get()) == (p1.get() == p1.get()));
|
|
REQUIRE((p1 != p1.get()) == (p1.get() != p1.get()));
|
|
|
|
REQUIRE((p1.get() == p1) == (p1.get() == p1.get()));
|
|
REQUIRE((p1.get() != p1) == (p1.get() != p1.get()));
|
|
|
|
REQUIRE((p1 < p1) == p1.get() < p1.get());
|
|
REQUIRE((p1 <= p1) == p1.get() <= p1.get());
|
|
REQUIRE((p1 > p1) == p1.get() > p1.get());
|
|
REQUIRE((p1 >= p1) == p1.get() >= p1.get());
|
|
}
|
|
|
|
{
|
|
REQUIRE((p2 == p1) == (p2.get() == p1.get()));
|
|
REQUIRE((p2 != p1) == (p2.get() != p1.get()));
|
|
|
|
REQUIRE((p2 == p1.get()) == (p2.get() == p1.get()));
|
|
REQUIRE((p2 != p1.get()) == (p2.get() != p1.get()));
|
|
|
|
REQUIRE((p2.get() == p1) == (p2.get() == p1.get()));
|
|
REQUIRE((p2.get() != p1) == (p2.get() != p1.get()));
|
|
|
|
REQUIRE((p2 < p1) == p2.get() < p1.get());
|
|
REQUIRE((p2 <= p1) == p2.get() <= p1.get());
|
|
REQUIRE((p2 > p1) == p2.get() > p1.get());
|
|
REQUIRE((p2 >= p1) == p2.get() >= p1.get());
|
|
}
|
|
}
|
|
{
|
|
obj_t::reset_counters();
|
|
{
|
|
intrusive_ptr<obj_t> p1(new derived_t());
|
|
REQUIRE(p1->i == 84);
|
|
intrusive_ptr<obj_t> p2 = p1;
|
|
REQUIRE(p2->i == 84);
|
|
REQUIRE(p2->use_count() == 2u);
|
|
}
|
|
REQUIRE(obj_t::ctor_counter == 1u);
|
|
REQUIRE(obj_t::dtor_counter == 1u);
|
|
{
|
|
intrusive_ptr<obj_t> p1(new derived_t());
|
|
intrusive_ptr<obj_t> p2;
|
|
p2 = p1;
|
|
REQUIRE(p2->i == 84);
|
|
}
|
|
REQUIRE(obj_t::ctor_counter == 2u);
|
|
REQUIRE(obj_t::dtor_counter == 2u);
|
|
{
|
|
intrusive_ptr<obj_t> p1(new derived_t());
|
|
intrusive_ptr<obj_t> p2 = std::move(p1);
|
|
REQUIRE(p2->i == 84);
|
|
REQUIRE_FALSE(p1);
|
|
}
|
|
REQUIRE(obj_t::ctor_counter == 3u);
|
|
REQUIRE(obj_t::dtor_counter == 3u);
|
|
{
|
|
intrusive_ptr<obj_t> p1(new derived_t());
|
|
intrusive_ptr<obj_t> p2;
|
|
p2 = std::move(p1);
|
|
REQUIRE(p2->i == 84);
|
|
REQUIRE_FALSE(p1);
|
|
}
|
|
REQUIRE(obj_t::ctor_counter == 4u);
|
|
REQUIRE(obj_t::dtor_counter == 4u);
|
|
}
|
|
{
|
|
E2D_UNUSED(std::make_unique<obj_t>(10));
|
|
intrusive_ptr<const obj_t> p1(new derived2_t());
|
|
intrusive_ptr<const derived2_t> p2 = static_pointer_cast<const derived2_t>(p1);
|
|
REQUIRE(p2->i == 21);
|
|
REQUIRE(p2->j == 500100);
|
|
intrusive_ptr<const derived2_t> p3 = dynamic_pointer_cast<const derived2_t>(p1);
|
|
REQUIRE(p3->i == 21);
|
|
REQUIRE(p3->j == 500100);
|
|
intrusive_ptr<const derived_t> p4 = dynamic_pointer_cast<const derived_t>(p1);
|
|
REQUIRE_FALSE(p4);
|
|
intrusive_ptr<obj_t> p5 = const_pointer_cast<obj_t>(p1);
|
|
REQUIRE(p5);
|
|
REQUIRE(p5->i == 21);
|
|
}
|
|
{
|
|
auto p1 = make_intrusive<obj_t>(10);
|
|
hash_set<intrusive_ptr<obj_t>> s;
|
|
s.insert(p1);
|
|
}
|
|
{
|
|
auto p = make_intrusive<obj2_t>(10);
|
|
REQUIRE(p->i == 10);
|
|
REQUIRE(p->use_count() == 1u);
|
|
p.reset();
|
|
REQUIRE(obj2_t::ctor_counter == 1u);
|
|
REQUIRE(obj2_t::dtor_counter == 1u);
|
|
}
|
|
}
|