Squashed 'external/entt/entt/' content from commit fef92113
git-subtree-dir: external/entt/entt git-subtree-split: fef921132cae7588213d0f9bcd2fb9c8ffd8b7fc
This commit is contained in:
433
test/entt/signal/delegate.cpp
Normal file
433
test/entt/signal/delegate.cpp
Normal file
@ -0,0 +1,433 @@
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/signal/delegate.hpp>
|
||||
#include "../common/config.h"
|
||||
|
||||
int delegate_function(const int &i) {
|
||||
return i * i;
|
||||
}
|
||||
|
||||
int curried_by_ref(const int &i, int j) {
|
||||
return i + j;
|
||||
}
|
||||
|
||||
int curried_by_ptr(const int *i, int j) {
|
||||
return (*i) * j;
|
||||
}
|
||||
|
||||
int non_const_reference(int &i) {
|
||||
return i *= i;
|
||||
}
|
||||
|
||||
int move_only_type(std::unique_ptr<int> ptr) {
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
struct delegate_functor {
|
||||
int operator()(int i) {
|
||||
return i + i;
|
||||
}
|
||||
|
||||
int identity(int i) const {
|
||||
return i;
|
||||
}
|
||||
|
||||
static const int static_value = 3;
|
||||
const int data_member = 42;
|
||||
};
|
||||
|
||||
struct const_nonconst_noexcept {
|
||||
void f() {
|
||||
++cnt;
|
||||
}
|
||||
|
||||
void g() noexcept {
|
||||
++cnt;
|
||||
}
|
||||
|
||||
void h() const {
|
||||
++cnt;
|
||||
}
|
||||
|
||||
void i() const noexcept {
|
||||
++cnt;
|
||||
}
|
||||
|
||||
int u{};
|
||||
const int v{};
|
||||
mutable int cnt{0};
|
||||
};
|
||||
|
||||
TEST(Delegate, Functionalities) {
|
||||
entt::delegate<int(int)> ff_del;
|
||||
entt::delegate<int(int)> mf_del;
|
||||
entt::delegate<int(int)> lf_del;
|
||||
delegate_functor functor;
|
||||
|
||||
ASSERT_FALSE(ff_del);
|
||||
ASSERT_FALSE(mf_del);
|
||||
ASSERT_EQ(ff_del, mf_del);
|
||||
|
||||
ff_del.connect<&delegate_function>();
|
||||
mf_del.connect<&delegate_functor::operator()>(functor);
|
||||
lf_del.connect([](const void *ptr, int value) { return static_cast<const delegate_functor *>(ptr)->identity(value); }, &functor);
|
||||
|
||||
ASSERT_TRUE(ff_del);
|
||||
ASSERT_TRUE(mf_del);
|
||||
ASSERT_TRUE(lf_del);
|
||||
|
||||
ASSERT_EQ(ff_del(3), 9);
|
||||
ASSERT_EQ(mf_del(3), 6);
|
||||
ASSERT_EQ(lf_del(3), 3);
|
||||
|
||||
ff_del.reset();
|
||||
|
||||
ASSERT_FALSE(ff_del);
|
||||
|
||||
ASSERT_EQ(ff_del, entt::delegate<int(int)>{});
|
||||
ASSERT_NE(mf_del, entt::delegate<int(int)>{});
|
||||
ASSERT_NE(lf_del, entt::delegate<int(int)>{});
|
||||
|
||||
ASSERT_NE(ff_del, mf_del);
|
||||
ASSERT_NE(ff_del, lf_del);
|
||||
ASSERT_NE(mf_del, lf_del);
|
||||
|
||||
mf_del.reset();
|
||||
|
||||
ASSERT_FALSE(ff_del);
|
||||
ASSERT_FALSE(mf_del);
|
||||
ASSERT_TRUE(lf_del);
|
||||
|
||||
ASSERT_EQ(ff_del, entt::delegate<int(int)>{});
|
||||
ASSERT_EQ(mf_del, entt::delegate<int(int)>{});
|
||||
ASSERT_NE(lf_del, entt::delegate<int(int)>{});
|
||||
|
||||
ASSERT_EQ(ff_del, mf_del);
|
||||
ASSERT_NE(ff_del, lf_del);
|
||||
ASSERT_NE(mf_del, lf_del);
|
||||
}
|
||||
|
||||
ENTT_DEBUG_TEST(DelegateDeathTest, InvokeEmpty) {
|
||||
entt::delegate<int(int)> del;
|
||||
|
||||
ASSERT_FALSE(del);
|
||||
ASSERT_DEATH(del(42), "");
|
||||
ASSERT_DEATH(std::as_const(del)(42), "");
|
||||
}
|
||||
|
||||
TEST(Delegate, DataMembers) {
|
||||
entt::delegate<double()> delegate;
|
||||
delegate_functor functor;
|
||||
|
||||
delegate.connect<&delegate_functor::data_member>(functor);
|
||||
|
||||
ASSERT_EQ(delegate(), 42);
|
||||
}
|
||||
|
||||
TEST(Delegate, Comparison) {
|
||||
entt::delegate<int(int)> lhs;
|
||||
entt::delegate<int(int)> rhs;
|
||||
delegate_functor functor;
|
||||
delegate_functor other;
|
||||
const int value = 0;
|
||||
|
||||
ASSERT_EQ(lhs, entt::delegate<int(int)>{});
|
||||
ASSERT_FALSE(lhs != rhs);
|
||||
ASSERT_TRUE(lhs == rhs);
|
||||
ASSERT_EQ(lhs, rhs);
|
||||
|
||||
lhs.connect<&delegate_function>();
|
||||
|
||||
ASSERT_EQ(lhs, entt::delegate<int(int)>{entt::connect_arg<&delegate_function>});
|
||||
ASSERT_TRUE(lhs != rhs);
|
||||
ASSERT_FALSE(lhs == rhs);
|
||||
ASSERT_NE(lhs, rhs);
|
||||
|
||||
rhs.connect<&delegate_function>();
|
||||
|
||||
ASSERT_EQ(rhs, entt::delegate<int(int)>{entt::connect_arg<&delegate_function>});
|
||||
ASSERT_FALSE(lhs != rhs);
|
||||
ASSERT_TRUE(lhs == rhs);
|
||||
ASSERT_EQ(lhs, rhs);
|
||||
|
||||
lhs.connect<&curried_by_ref>(value);
|
||||
|
||||
ASSERT_EQ(lhs, (entt::delegate<int(int)>{entt::connect_arg<&curried_by_ref>, value}));
|
||||
ASSERT_TRUE(lhs != rhs);
|
||||
ASSERT_FALSE(lhs == rhs);
|
||||
ASSERT_NE(lhs, rhs);
|
||||
|
||||
rhs.connect<&curried_by_ref>(value);
|
||||
|
||||
ASSERT_EQ(rhs, (entt::delegate<int(int)>{entt::connect_arg<&curried_by_ref>, value}));
|
||||
ASSERT_FALSE(lhs != rhs);
|
||||
ASSERT_TRUE(lhs == rhs);
|
||||
ASSERT_EQ(lhs, rhs);
|
||||
|
||||
lhs.connect<&curried_by_ptr>(&value);
|
||||
|
||||
ASSERT_EQ(lhs, (entt::delegate<int(int)>{entt::connect_arg<&curried_by_ptr>, &value}));
|
||||
ASSERT_TRUE(lhs != rhs);
|
||||
ASSERT_FALSE(lhs == rhs);
|
||||
ASSERT_NE(lhs, rhs);
|
||||
|
||||
rhs.connect<&curried_by_ptr>(&value);
|
||||
|
||||
ASSERT_EQ(rhs, (entt::delegate<int(int)>{entt::connect_arg<&curried_by_ptr>, &value}));
|
||||
ASSERT_FALSE(lhs != rhs);
|
||||
ASSERT_TRUE(lhs == rhs);
|
||||
ASSERT_EQ(lhs, rhs);
|
||||
|
||||
lhs.connect<&delegate_functor::operator()>(functor);
|
||||
|
||||
ASSERT_EQ(lhs, (entt::delegate<int(int)>{entt::connect_arg<&delegate_functor::operator()>, functor}));
|
||||
ASSERT_TRUE(lhs != rhs);
|
||||
ASSERT_FALSE(lhs == rhs);
|
||||
ASSERT_NE(lhs, rhs);
|
||||
|
||||
rhs.connect<&delegate_functor::operator()>(functor);
|
||||
|
||||
ASSERT_EQ(rhs, (entt::delegate<int(int)>{entt::connect_arg<&delegate_functor::operator()>, functor}));
|
||||
ASSERT_FALSE(lhs != rhs);
|
||||
ASSERT_TRUE(lhs == rhs);
|
||||
ASSERT_EQ(lhs, rhs);
|
||||
|
||||
lhs.connect<&delegate_functor::operator()>(other);
|
||||
|
||||
ASSERT_EQ(lhs, (entt::delegate<int(int)>{entt::connect_arg<&delegate_functor::operator()>, other}));
|
||||
ASSERT_NE(lhs.data(), rhs.data());
|
||||
ASSERT_TRUE(lhs != rhs);
|
||||
ASSERT_FALSE(lhs == rhs);
|
||||
ASSERT_NE(lhs, rhs);
|
||||
|
||||
lhs.connect([](const void *ptr, int val) { return static_cast<const delegate_functor *>(ptr)->identity(val) * val; }, &functor);
|
||||
|
||||
ASSERT_NE(lhs, (entt::delegate<int(int)>{[](const void *, int val) { return val + val; }, &functor}));
|
||||
ASSERT_TRUE(lhs != rhs);
|
||||
ASSERT_FALSE(lhs == rhs);
|
||||
ASSERT_NE(lhs, rhs);
|
||||
|
||||
rhs.connect([](const void *ptr, int val) { return static_cast<const delegate_functor *>(ptr)->identity(val) + val; }, &functor);
|
||||
|
||||
ASSERT_NE(rhs, (entt::delegate<int(int)>{[](const void *, int val) { return val * val; }, &functor}));
|
||||
ASSERT_TRUE(lhs != rhs);
|
||||
ASSERT_FALSE(lhs == rhs);
|
||||
ASSERT_NE(lhs, rhs);
|
||||
|
||||
lhs.reset();
|
||||
|
||||
ASSERT_EQ(lhs, (entt::delegate<int(int)>{}));
|
||||
ASSERT_TRUE(lhs != rhs);
|
||||
ASSERT_FALSE(lhs == rhs);
|
||||
ASSERT_NE(lhs, rhs);
|
||||
|
||||
rhs.reset();
|
||||
|
||||
ASSERT_EQ(rhs, (entt::delegate<int(int)>{}));
|
||||
ASSERT_FALSE(lhs != rhs);
|
||||
ASSERT_TRUE(lhs == rhs);
|
||||
ASSERT_EQ(lhs, rhs);
|
||||
}
|
||||
|
||||
TEST(Delegate, ConstNonConstNoExcept) {
|
||||
entt::delegate<void()> delegate;
|
||||
const_nonconst_noexcept functor;
|
||||
|
||||
delegate.connect<&const_nonconst_noexcept::f>(functor);
|
||||
delegate();
|
||||
|
||||
delegate.connect<&const_nonconst_noexcept::g>(functor);
|
||||
delegate();
|
||||
|
||||
delegate.connect<&const_nonconst_noexcept::h>(functor);
|
||||
delegate();
|
||||
|
||||
delegate.connect<&const_nonconst_noexcept::i>(functor);
|
||||
delegate();
|
||||
|
||||
ASSERT_EQ(functor.cnt, 4);
|
||||
}
|
||||
|
||||
TEST(Delegate, DeductionGuide) {
|
||||
const_nonconst_noexcept functor;
|
||||
int value = 0;
|
||||
|
||||
entt::delegate func{entt::connect_arg<&delegate_function>};
|
||||
entt::delegate curried_func_with_ref{entt::connect_arg<&curried_by_ref>, value};
|
||||
entt::delegate curried_func_with_const_ref{entt::connect_arg<&curried_by_ref>, std::as_const(value)};
|
||||
entt::delegate curried_func_with_ptr{entt::connect_arg<&curried_by_ptr>, &value};
|
||||
entt::delegate curried_func_with_const_ptr{entt::connect_arg<&curried_by_ptr>, &std::as_const(value)};
|
||||
entt::delegate member_func_f{entt::connect_arg<&const_nonconst_noexcept::f>, functor};
|
||||
entt::delegate member_func_g{entt::connect_arg<&const_nonconst_noexcept::g>, functor};
|
||||
entt::delegate member_func_h{entt::connect_arg<&const_nonconst_noexcept::h>, &functor};
|
||||
entt::delegate member_func_h_const{entt::connect_arg<&const_nonconst_noexcept::h>, &std::as_const(functor)};
|
||||
entt::delegate member_func_i{entt::connect_arg<&const_nonconst_noexcept::i>, functor};
|
||||
entt::delegate member_func_i_const{entt::connect_arg<&const_nonconst_noexcept::i>, std::as_const(functor)};
|
||||
entt::delegate data_member_u{entt::connect_arg<&const_nonconst_noexcept::u>, functor};
|
||||
entt::delegate data_member_v{entt::connect_arg<&const_nonconst_noexcept::v>, &functor};
|
||||
entt::delegate data_member_v_const{entt::connect_arg<&const_nonconst_noexcept::v>, &std::as_const(functor)};
|
||||
entt::delegate lambda{+[](const void *, int) { return 0; }};
|
||||
|
||||
static_assert(std::is_same_v<typename decltype(func)::type, int(const int &)>);
|
||||
static_assert(std::is_same_v<typename decltype(curried_func_with_ref)::type, int(int)>);
|
||||
static_assert(std::is_same_v<typename decltype(curried_func_with_const_ref)::type, int(int)>);
|
||||
static_assert(std::is_same_v<typename decltype(curried_func_with_ptr)::type, int(int)>);
|
||||
static_assert(std::is_same_v<typename decltype(curried_func_with_const_ptr)::type, int(int)>);
|
||||
static_assert(std::is_same_v<typename decltype(member_func_f)::type, void()>);
|
||||
static_assert(std::is_same_v<typename decltype(member_func_g)::type, void()>);
|
||||
static_assert(std::is_same_v<typename decltype(member_func_h)::type, void()>);
|
||||
static_assert(std::is_same_v<typename decltype(member_func_h_const)::type, void()>);
|
||||
static_assert(std::is_same_v<typename decltype(member_func_i)::type, void()>);
|
||||
static_assert(std::is_same_v<typename decltype(member_func_i_const)::type, void()>);
|
||||
static_assert(std::is_same_v<typename decltype(data_member_u)::type, int()>);
|
||||
static_assert(std::is_same_v<typename decltype(data_member_v)::type, const int()>);
|
||||
static_assert(std::is_same_v<typename decltype(data_member_v_const)::type, const int()>);
|
||||
static_assert(std::is_same_v<typename decltype(lambda)::type, int(int)>);
|
||||
|
||||
ASSERT_TRUE(func);
|
||||
ASSERT_TRUE(curried_func_with_ref);
|
||||
ASSERT_TRUE(curried_func_with_const_ref);
|
||||
ASSERT_TRUE(curried_func_with_ptr);
|
||||
ASSERT_TRUE(curried_func_with_const_ptr);
|
||||
ASSERT_TRUE(member_func_f);
|
||||
ASSERT_TRUE(member_func_g);
|
||||
ASSERT_TRUE(member_func_h);
|
||||
ASSERT_TRUE(member_func_h_const);
|
||||
ASSERT_TRUE(member_func_i);
|
||||
ASSERT_TRUE(member_func_i_const);
|
||||
ASSERT_TRUE(data_member_u);
|
||||
ASSERT_TRUE(data_member_v);
|
||||
ASSERT_TRUE(data_member_v_const);
|
||||
ASSERT_TRUE(lambda);
|
||||
}
|
||||
|
||||
TEST(Delegate, ConstInstance) {
|
||||
entt::delegate<int(int)> delegate;
|
||||
const delegate_functor functor;
|
||||
|
||||
ASSERT_FALSE(delegate);
|
||||
|
||||
delegate.connect<&delegate_functor::identity>(functor);
|
||||
|
||||
ASSERT_TRUE(delegate);
|
||||
ASSERT_EQ(delegate(3), 3);
|
||||
|
||||
delegate.reset();
|
||||
|
||||
ASSERT_FALSE(delegate);
|
||||
ASSERT_EQ(delegate, entt::delegate<int(int)>{});
|
||||
}
|
||||
|
||||
TEST(Delegate, NonConstReference) {
|
||||
entt::delegate<int(int &)> delegate;
|
||||
delegate.connect<&non_const_reference>();
|
||||
int value = 3;
|
||||
|
||||
ASSERT_EQ(delegate(value), value);
|
||||
ASSERT_EQ(value, 9);
|
||||
}
|
||||
|
||||
TEST(Delegate, MoveOnlyType) {
|
||||
entt::delegate<int(std::unique_ptr<int>)> delegate;
|
||||
auto ptr = std::make_unique<int>(3);
|
||||
delegate.connect<&move_only_type>();
|
||||
|
||||
ASSERT_EQ(delegate(std::move(ptr)), 3);
|
||||
ASSERT_FALSE(ptr);
|
||||
}
|
||||
|
||||
TEST(Delegate, CurriedFunction) {
|
||||
entt::delegate<int(int)> delegate;
|
||||
const auto value = 3;
|
||||
|
||||
delegate.connect<&curried_by_ref>(value);
|
||||
|
||||
ASSERT_TRUE(delegate);
|
||||
ASSERT_EQ(delegate(1), 4);
|
||||
|
||||
delegate.connect<&curried_by_ptr>(&value);
|
||||
|
||||
ASSERT_TRUE(delegate);
|
||||
ASSERT_EQ(delegate(2), 6);
|
||||
}
|
||||
|
||||
TEST(Delegate, Constructors) {
|
||||
delegate_functor functor;
|
||||
const auto value = 2;
|
||||
|
||||
entt::delegate<int(int)> empty{};
|
||||
entt::delegate<int(int)> func{entt::connect_arg<&delegate_function>};
|
||||
entt::delegate<int(int)> ref{entt::connect_arg<&curried_by_ref>, value};
|
||||
entt::delegate<int(int)> ptr{entt::connect_arg<&curried_by_ptr>, &value};
|
||||
entt::delegate<int(int)> member{entt::connect_arg<&delegate_functor::operator()>, functor};
|
||||
|
||||
ASSERT_FALSE(empty);
|
||||
|
||||
ASSERT_TRUE(func);
|
||||
ASSERT_EQ(9, func(3));
|
||||
|
||||
ASSERT_TRUE(ref);
|
||||
ASSERT_EQ(5, ref(3));
|
||||
|
||||
ASSERT_TRUE(ptr);
|
||||
ASSERT_EQ(6, ptr(3));
|
||||
|
||||
ASSERT_TRUE(member);
|
||||
ASSERT_EQ(6, member(3));
|
||||
}
|
||||
|
||||
TEST(Delegate, VoidVsNonVoidReturnType) {
|
||||
delegate_functor functor;
|
||||
|
||||
entt::delegate<void(int)> func{entt::connect_arg<&delegate_function>};
|
||||
entt::delegate<void(int)> member{entt::connect_arg<&delegate_functor::operator()>, &functor};
|
||||
entt::delegate<void(int)> cmember{entt::connect_arg<&delegate_functor::identity>, &std::as_const(functor)};
|
||||
|
||||
ASSERT_TRUE(func);
|
||||
ASSERT_TRUE(member);
|
||||
ASSERT_TRUE(cmember);
|
||||
}
|
||||
|
||||
TEST(Delegate, UnboundDataMember) {
|
||||
entt::delegate<int(const delegate_functor &)> delegate;
|
||||
delegate.connect<&delegate_functor::data_member>();
|
||||
delegate_functor functor;
|
||||
|
||||
ASSERT_EQ(delegate(functor), 42);
|
||||
}
|
||||
|
||||
TEST(Delegate, UnboundMemberFunction) {
|
||||
entt::delegate<int(delegate_functor *, const int &i)> delegate;
|
||||
delegate.connect<&delegate_functor::operator()>();
|
||||
delegate_functor functor;
|
||||
|
||||
ASSERT_EQ(delegate(&functor, 3), 6);
|
||||
}
|
||||
|
||||
TEST(Delegate, TheLessTheBetter) {
|
||||
entt::delegate<int(int, char)> bound;
|
||||
entt::delegate<int(delegate_functor &, int, char)> unbound;
|
||||
delegate_functor functor;
|
||||
|
||||
// int delegate_function(const int &);
|
||||
bound.connect<&delegate_function>();
|
||||
|
||||
ASSERT_EQ(bound(3, 'c'), 9);
|
||||
|
||||
// int delegate_functor::operator()(int);
|
||||
bound.connect<&delegate_functor::operator()>(functor);
|
||||
|
||||
ASSERT_EQ(bound(3, 'c'), 6);
|
||||
|
||||
// int delegate_functor::operator()(int);
|
||||
bound.connect<&delegate_functor::identity>(&functor);
|
||||
|
||||
ASSERT_EQ(bound(3, 'c'), 3);
|
||||
|
||||
// int delegate_functor::operator()(int);
|
||||
unbound.connect<&delegate_functor::operator()>();
|
||||
|
||||
ASSERT_EQ(unbound(functor, 3, 'c'), 6);
|
||||
}
|
200
test/entt/signal/dispatcher.cpp
Normal file
200
test/entt/signal/dispatcher.cpp
Normal file
@ -0,0 +1,200 @@
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/hashed_string.hpp>
|
||||
#include <entt/signal/dispatcher.hpp>
|
||||
|
||||
struct an_event {};
|
||||
struct another_event {};
|
||||
|
||||
// makes the type non-aggregate
|
||||
struct one_more_event {
|
||||
one_more_event(int) {}
|
||||
};
|
||||
|
||||
struct receiver {
|
||||
static void forward(entt::dispatcher &dispatcher, an_event &event) {
|
||||
dispatcher.enqueue(event);
|
||||
}
|
||||
|
||||
void receive(const an_event &) {
|
||||
++cnt;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
cnt = 0;
|
||||
}
|
||||
|
||||
int cnt{0};
|
||||
};
|
||||
|
||||
TEST(Dispatcher, Functionalities) {
|
||||
entt::dispatcher dispatcher;
|
||||
entt::dispatcher other;
|
||||
receiver receiver;
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(entt::dispatcher{std::move(dispatcher)});
|
||||
ASSERT_NO_FATAL_FAILURE(dispatcher = std::move(other));
|
||||
|
||||
ASSERT_EQ(dispatcher.size<an_event>(), 0u);
|
||||
ASSERT_EQ(dispatcher.size(), 0u);
|
||||
|
||||
dispatcher.trigger(one_more_event{42});
|
||||
dispatcher.enqueue<one_more_event>(42);
|
||||
dispatcher.update<one_more_event>();
|
||||
|
||||
dispatcher.sink<an_event>().connect<&receiver::receive>(receiver);
|
||||
dispatcher.trigger<an_event>();
|
||||
dispatcher.enqueue<an_event>();
|
||||
|
||||
ASSERT_EQ(dispatcher.size<one_more_event>(), 0u);
|
||||
ASSERT_EQ(dispatcher.size<an_event>(), 1u);
|
||||
ASSERT_EQ(dispatcher.size(), 1u);
|
||||
ASSERT_EQ(receiver.cnt, 1);
|
||||
|
||||
dispatcher.enqueue(another_event{});
|
||||
dispatcher.update<another_event>();
|
||||
|
||||
ASSERT_EQ(dispatcher.size<another_event>(), 0u);
|
||||
ASSERT_EQ(dispatcher.size<an_event>(), 1u);
|
||||
ASSERT_EQ(dispatcher.size(), 1u);
|
||||
ASSERT_EQ(receiver.cnt, 1);
|
||||
|
||||
dispatcher.update<an_event>();
|
||||
dispatcher.trigger<an_event>();
|
||||
|
||||
ASSERT_EQ(dispatcher.size<an_event>(), 0u);
|
||||
ASSERT_EQ(dispatcher.size(), 0u);
|
||||
ASSERT_EQ(receiver.cnt, 3);
|
||||
|
||||
dispatcher.enqueue<an_event>();
|
||||
dispatcher.clear<an_event>();
|
||||
dispatcher.update();
|
||||
|
||||
dispatcher.enqueue(an_event{});
|
||||
dispatcher.clear();
|
||||
dispatcher.update();
|
||||
|
||||
ASSERT_EQ(dispatcher.size<an_event>(), 0u);
|
||||
ASSERT_EQ(dispatcher.size(), 0u);
|
||||
ASSERT_EQ(receiver.cnt, 3);
|
||||
|
||||
receiver.reset();
|
||||
|
||||
an_event event{};
|
||||
|
||||
dispatcher.sink<an_event>().disconnect<&receiver::receive>(receiver);
|
||||
dispatcher.trigger<an_event>();
|
||||
dispatcher.enqueue(event);
|
||||
dispatcher.update();
|
||||
dispatcher.trigger(std::as_const(event));
|
||||
|
||||
ASSERT_EQ(receiver.cnt, 0);
|
||||
}
|
||||
|
||||
TEST(Dispatcher, Swap) {
|
||||
entt::dispatcher dispatcher;
|
||||
entt::dispatcher other;
|
||||
receiver receiver;
|
||||
|
||||
dispatcher.sink<an_event>().connect<&receiver::receive>(receiver);
|
||||
dispatcher.enqueue<an_event>();
|
||||
|
||||
ASSERT_EQ(dispatcher.size(), 1u);
|
||||
ASSERT_EQ(other.size(), 0u);
|
||||
ASSERT_EQ(receiver.cnt, 0);
|
||||
|
||||
dispatcher.swap(other);
|
||||
dispatcher.update();
|
||||
|
||||
ASSERT_EQ(dispatcher.size(), 0u);
|
||||
ASSERT_EQ(other.size(), 1u);
|
||||
ASSERT_EQ(receiver.cnt, 0);
|
||||
|
||||
other.update();
|
||||
|
||||
ASSERT_EQ(dispatcher.size(), 0u);
|
||||
ASSERT_EQ(other.size(), 0u);
|
||||
ASSERT_EQ(receiver.cnt, 1);
|
||||
}
|
||||
|
||||
TEST(Dispatcher, StopAndGo) {
|
||||
entt::dispatcher dispatcher;
|
||||
receiver receiver;
|
||||
|
||||
dispatcher.sink<an_event>().connect<&receiver::forward>(dispatcher);
|
||||
dispatcher.sink<an_event>().connect<&receiver::receive>(receiver);
|
||||
|
||||
dispatcher.enqueue<an_event>();
|
||||
dispatcher.update();
|
||||
|
||||
ASSERT_EQ(receiver.cnt, 1);
|
||||
|
||||
dispatcher.sink<an_event>().disconnect<&receiver::forward>(dispatcher);
|
||||
dispatcher.update();
|
||||
|
||||
ASSERT_EQ(receiver.cnt, 2);
|
||||
}
|
||||
|
||||
TEST(Dispatcher, OpaqueDisconnect) {
|
||||
entt::dispatcher dispatcher;
|
||||
receiver receiver;
|
||||
|
||||
dispatcher.sink<an_event>().connect<&receiver::receive>(receiver);
|
||||
dispatcher.trigger<an_event>();
|
||||
|
||||
ASSERT_EQ(receiver.cnt, 1);
|
||||
|
||||
dispatcher.disconnect(receiver);
|
||||
dispatcher.trigger<an_event>();
|
||||
|
||||
ASSERT_EQ(receiver.cnt, 1);
|
||||
}
|
||||
|
||||
TEST(Dispatcher, NamedQueue) {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::dispatcher dispatcher;
|
||||
receiver receiver;
|
||||
|
||||
dispatcher.sink<an_event>("named"_hs).connect<&receiver::receive>(receiver);
|
||||
dispatcher.trigger<an_event>();
|
||||
|
||||
ASSERT_EQ(receiver.cnt, 0);
|
||||
|
||||
dispatcher.trigger("named"_hs, an_event{});
|
||||
|
||||
ASSERT_EQ(receiver.cnt, 1);
|
||||
|
||||
dispatcher.enqueue<an_event>();
|
||||
dispatcher.enqueue(an_event{});
|
||||
dispatcher.enqueue_hint<an_event>("named"_hs);
|
||||
dispatcher.enqueue_hint("named"_hs, an_event{});
|
||||
dispatcher.update<an_event>();
|
||||
|
||||
ASSERT_EQ(receiver.cnt, 1);
|
||||
|
||||
dispatcher.clear<an_event>();
|
||||
dispatcher.update<an_event>("named"_hs);
|
||||
|
||||
ASSERT_EQ(receiver.cnt, 3);
|
||||
|
||||
dispatcher.enqueue_hint<an_event>("named"_hs);
|
||||
dispatcher.clear<an_event>("named"_hs);
|
||||
dispatcher.update<an_event>("named"_hs);
|
||||
|
||||
ASSERT_EQ(receiver.cnt, 3);
|
||||
}
|
||||
|
||||
TEST(Dispatcher, CustomAllocator) {
|
||||
std::allocator<void> allocator;
|
||||
entt::dispatcher dispatcher{allocator};
|
||||
|
||||
ASSERT_EQ(dispatcher.get_allocator(), allocator);
|
||||
ASSERT_FALSE(dispatcher.get_allocator() != allocator);
|
||||
|
||||
dispatcher.enqueue<an_event>();
|
||||
decltype(dispatcher) other{std::move(dispatcher), allocator};
|
||||
|
||||
ASSERT_EQ(other.size<an_event>(), 1u);
|
||||
}
|
170
test/entt/signal/emitter.cpp
Normal file
170
test/entt/signal/emitter.cpp
Normal file
@ -0,0 +1,170 @@
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/signal/emitter.hpp>
|
||||
|
||||
struct test_emitter: entt::emitter<test_emitter> {
|
||||
using entt::emitter<test_emitter>::emitter;
|
||||
};
|
||||
|
||||
struct foo_event {
|
||||
int i;
|
||||
};
|
||||
|
||||
struct bar_event {};
|
||||
struct quux_event {};
|
||||
|
||||
TEST(Emitter, Move) {
|
||||
test_emitter emitter;
|
||||
emitter.on<foo_event>([](auto &, const auto &) {});
|
||||
|
||||
ASSERT_FALSE(emitter.empty());
|
||||
ASSERT_TRUE(emitter.contains<foo_event>());
|
||||
|
||||
test_emitter other{std::move(emitter)};
|
||||
|
||||
ASSERT_FALSE(other.empty());
|
||||
ASSERT_TRUE(other.contains<foo_event>());
|
||||
ASSERT_TRUE(emitter.empty());
|
||||
|
||||
emitter = std::move(other);
|
||||
|
||||
ASSERT_FALSE(emitter.empty());
|
||||
ASSERT_TRUE(emitter.contains<foo_event>());
|
||||
ASSERT_TRUE(other.empty());
|
||||
}
|
||||
|
||||
TEST(Emitter, Swap) {
|
||||
test_emitter emitter;
|
||||
test_emitter other;
|
||||
int value{};
|
||||
|
||||
emitter.on<foo_event>([&value](auto &event, const auto &) {
|
||||
value = event.i;
|
||||
});
|
||||
|
||||
ASSERT_FALSE(emitter.empty());
|
||||
ASSERT_TRUE(other.empty());
|
||||
|
||||
emitter.swap(other);
|
||||
emitter.publish(foo_event{42});
|
||||
|
||||
ASSERT_EQ(value, 0);
|
||||
ASSERT_TRUE(emitter.empty());
|
||||
ASSERT_FALSE(other.empty());
|
||||
|
||||
other.publish(foo_event{42});
|
||||
|
||||
ASSERT_EQ(value, 42);
|
||||
}
|
||||
|
||||
TEST(Emitter, Clear) {
|
||||
test_emitter emitter;
|
||||
|
||||
ASSERT_TRUE(emitter.empty());
|
||||
|
||||
emitter.on<foo_event>([](auto &, const auto &) {});
|
||||
emitter.on<quux_event>([](const auto &, const auto &) {});
|
||||
|
||||
ASSERT_FALSE(emitter.empty());
|
||||
ASSERT_TRUE(emitter.contains<foo_event>());
|
||||
ASSERT_TRUE(emitter.contains<quux_event>());
|
||||
ASSERT_FALSE(emitter.contains<bar_event>());
|
||||
|
||||
emitter.erase<bar_event>();
|
||||
|
||||
ASSERT_FALSE(emitter.empty());
|
||||
ASSERT_TRUE(emitter.contains<foo_event>());
|
||||
ASSERT_TRUE(emitter.contains<quux_event>());
|
||||
ASSERT_FALSE(emitter.contains<bar_event>());
|
||||
|
||||
emitter.erase<foo_event>();
|
||||
|
||||
ASSERT_FALSE(emitter.empty());
|
||||
ASSERT_FALSE(emitter.contains<foo_event>());
|
||||
ASSERT_TRUE(emitter.contains<quux_event>());
|
||||
ASSERT_FALSE(emitter.contains<bar_event>());
|
||||
|
||||
emitter.on<foo_event>([](auto &, const auto &) {});
|
||||
emitter.on<bar_event>([](const auto &, const auto &) {});
|
||||
|
||||
ASSERT_FALSE(emitter.empty());
|
||||
ASSERT_TRUE(emitter.contains<foo_event>());
|
||||
ASSERT_TRUE(emitter.contains<quux_event>());
|
||||
ASSERT_TRUE(emitter.contains<bar_event>());
|
||||
|
||||
emitter.clear();
|
||||
|
||||
ASSERT_TRUE(emitter.empty());
|
||||
ASSERT_FALSE(emitter.contains<foo_event>());
|
||||
ASSERT_FALSE(emitter.contains<bar_event>());
|
||||
}
|
||||
|
||||
TEST(Emitter, ClearFromCallback) {
|
||||
test_emitter emitter;
|
||||
|
||||
ASSERT_TRUE(emitter.empty());
|
||||
|
||||
emitter.on<foo_event>([](auto &, auto &owner) {
|
||||
owner.template on<foo_event>([](auto &, auto &) {});
|
||||
owner.template erase<foo_event>();
|
||||
});
|
||||
|
||||
emitter.on<bar_event>([](const auto &, auto &owner) {
|
||||
owner.template on<bar_event>([](const auto &, auto &) {});
|
||||
owner.template erase<bar_event>();
|
||||
});
|
||||
|
||||
ASSERT_FALSE(emitter.empty());
|
||||
|
||||
emitter.publish(foo_event{});
|
||||
emitter.publish(bar_event{});
|
||||
|
||||
ASSERT_TRUE(emitter.empty());
|
||||
}
|
||||
|
||||
TEST(Emitter, On) {
|
||||
test_emitter emitter;
|
||||
int value{};
|
||||
|
||||
emitter.on<foo_event>([&value](auto &event, const auto &) {
|
||||
value = event.i;
|
||||
});
|
||||
|
||||
ASSERT_FALSE(emitter.empty());
|
||||
ASSERT_TRUE(emitter.contains<foo_event>());
|
||||
ASSERT_EQ(value, 0);
|
||||
|
||||
emitter.publish(foo_event{42});
|
||||
|
||||
ASSERT_EQ(value, 42);
|
||||
}
|
||||
|
||||
TEST(Emitter, OnAndErase) {
|
||||
test_emitter emitter;
|
||||
std::function<void(bar_event &, test_emitter &)> func{};
|
||||
|
||||
emitter.on(func);
|
||||
|
||||
ASSERT_FALSE(emitter.empty());
|
||||
ASSERT_TRUE(emitter.contains<bar_event>());
|
||||
|
||||
emitter.erase<bar_event>();
|
||||
|
||||
ASSERT_TRUE(emitter.empty());
|
||||
ASSERT_FALSE(emitter.contains<bar_event>());
|
||||
}
|
||||
|
||||
TEST(Emitter, CustomAllocator) {
|
||||
std::allocator<void> allocator;
|
||||
test_emitter emitter{allocator};
|
||||
|
||||
ASSERT_EQ(emitter.get_allocator(), allocator);
|
||||
ASSERT_FALSE(emitter.get_allocator() != allocator);
|
||||
|
||||
emitter.on<foo_event>([](auto &, const auto &) {});
|
||||
decltype(emitter) other{std::move(emitter), allocator};
|
||||
|
||||
ASSERT_TRUE(emitter.empty());
|
||||
ASSERT_FALSE(other.empty());
|
||||
}
|
577
test/entt/signal/sigh.cpp
Normal file
577
test/entt/signal/sigh.cpp
Normal file
@ -0,0 +1,577 @@
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/signal/sigh.hpp>
|
||||
|
||||
struct sigh_listener {
|
||||
static void f(int &v) {
|
||||
v = 42;
|
||||
}
|
||||
|
||||
bool g(int) {
|
||||
k = !k;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool h(const int &) {
|
||||
return k;
|
||||
}
|
||||
|
||||
// useless definition just because msvc does weird things if both are empty
|
||||
void l() {
|
||||
k = true && k;
|
||||
}
|
||||
|
||||
bool k{false};
|
||||
};
|
||||
|
||||
struct before_after {
|
||||
void add(int v) {
|
||||
value += v;
|
||||
}
|
||||
|
||||
void mul(int v) {
|
||||
value *= v;
|
||||
}
|
||||
|
||||
static void static_add(int v) {
|
||||
before_after::value += v;
|
||||
}
|
||||
|
||||
static void static_mul(before_after &instance, int v) {
|
||||
instance.value *= v;
|
||||
}
|
||||
|
||||
static inline int value{};
|
||||
};
|
||||
|
||||
struct SigH: ::testing::Test {
|
||||
void SetUp() override {
|
||||
before_after::value = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct const_nonconst_noexcept {
|
||||
void f() {
|
||||
++cnt;
|
||||
}
|
||||
|
||||
void g() noexcept {
|
||||
++cnt;
|
||||
}
|
||||
|
||||
void h() const {
|
||||
++cnt;
|
||||
}
|
||||
|
||||
void i() const noexcept {
|
||||
++cnt;
|
||||
}
|
||||
|
||||
mutable int cnt{0};
|
||||
};
|
||||
|
||||
TEST_F(SigH, Lifetime) {
|
||||
using signal = entt::sigh<void(void)>;
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(signal{});
|
||||
|
||||
signal src{}, other{};
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(signal{src});
|
||||
ASSERT_NO_FATAL_FAILURE(signal{std::move(other)});
|
||||
ASSERT_NO_FATAL_FAILURE(src = other);
|
||||
ASSERT_NO_FATAL_FAILURE(src = std::move(other));
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(delete new signal{});
|
||||
}
|
||||
|
||||
TEST_F(SigH, Clear) {
|
||||
entt::sigh<void(int &)> sigh;
|
||||
entt::sink sink{sigh};
|
||||
|
||||
sink.connect<&sigh_listener::f>();
|
||||
|
||||
ASSERT_FALSE(sink.empty());
|
||||
ASSERT_FALSE(sigh.empty());
|
||||
|
||||
sink.disconnect(static_cast<const void *>(nullptr));
|
||||
|
||||
ASSERT_FALSE(sink.empty());
|
||||
ASSERT_FALSE(sigh.empty());
|
||||
|
||||
sink.disconnect();
|
||||
|
||||
ASSERT_TRUE(sink.empty());
|
||||
ASSERT_TRUE(sigh.empty());
|
||||
}
|
||||
|
||||
TEST_F(SigH, Swap) {
|
||||
entt::sigh<void(int &)> sigh1;
|
||||
entt::sigh<void(int &)> sigh2;
|
||||
entt::sink sink1{sigh1};
|
||||
entt::sink sink2{sigh2};
|
||||
|
||||
sink1.connect<&sigh_listener::f>();
|
||||
|
||||
ASSERT_FALSE(sink1.empty());
|
||||
ASSERT_TRUE(sink2.empty());
|
||||
|
||||
ASSERT_FALSE(sigh1.empty());
|
||||
ASSERT_TRUE(sigh2.empty());
|
||||
|
||||
sigh1.swap(sigh2);
|
||||
|
||||
ASSERT_TRUE(sink1.empty());
|
||||
ASSERT_FALSE(sink2.empty());
|
||||
|
||||
ASSERT_TRUE(sigh1.empty());
|
||||
ASSERT_FALSE(sigh2.empty());
|
||||
}
|
||||
|
||||
TEST_F(SigH, Functions) {
|
||||
entt::sigh<void(int &)> sigh;
|
||||
entt::sink sink{sigh};
|
||||
int v = 0;
|
||||
|
||||
sink.connect<&sigh_listener::f>();
|
||||
sigh.publish(v);
|
||||
|
||||
ASSERT_FALSE(sigh.empty());
|
||||
ASSERT_EQ(1u, sigh.size());
|
||||
ASSERT_EQ(42, v);
|
||||
|
||||
v = 0;
|
||||
sink.disconnect<&sigh_listener::f>();
|
||||
sigh.publish(v);
|
||||
|
||||
ASSERT_TRUE(sigh.empty());
|
||||
ASSERT_EQ(0u, sigh.size());
|
||||
ASSERT_EQ(v, 0);
|
||||
}
|
||||
|
||||
TEST_F(SigH, FunctionsWithPayload) {
|
||||
entt::sigh<void()> sigh;
|
||||
entt::sink sink{sigh};
|
||||
int v = 0;
|
||||
|
||||
sink.connect<&sigh_listener::f>(v);
|
||||
sigh.publish();
|
||||
|
||||
ASSERT_FALSE(sigh.empty());
|
||||
ASSERT_EQ(1u, sigh.size());
|
||||
ASSERT_EQ(42, v);
|
||||
|
||||
v = 0;
|
||||
sink.disconnect<&sigh_listener::f>(v);
|
||||
sigh.publish();
|
||||
|
||||
ASSERT_TRUE(sigh.empty());
|
||||
ASSERT_EQ(0u, sigh.size());
|
||||
ASSERT_EQ(v, 0);
|
||||
|
||||
sink.connect<&sigh_listener::f>(v);
|
||||
sink.disconnect(v);
|
||||
sigh.publish();
|
||||
|
||||
ASSERT_EQ(v, 0);
|
||||
}
|
||||
|
||||
TEST_F(SigH, Members) {
|
||||
sigh_listener l1, l2;
|
||||
entt::sigh<bool(int)> sigh;
|
||||
entt::sink sink{sigh};
|
||||
|
||||
sink.connect<&sigh_listener::g>(l1);
|
||||
sigh.publish(42);
|
||||
|
||||
ASSERT_TRUE(l1.k);
|
||||
ASSERT_FALSE(sigh.empty());
|
||||
ASSERT_EQ(1u, sigh.size());
|
||||
|
||||
sink.disconnect<&sigh_listener::g>(l1);
|
||||
sigh.publish(42);
|
||||
|
||||
ASSERT_TRUE(l1.k);
|
||||
ASSERT_TRUE(sigh.empty());
|
||||
ASSERT_EQ(0u, sigh.size());
|
||||
|
||||
sink.connect<&sigh_listener::g>(&l1);
|
||||
sink.connect<&sigh_listener::h>(l2);
|
||||
|
||||
ASSERT_FALSE(sigh.empty());
|
||||
ASSERT_EQ(2u, sigh.size());
|
||||
|
||||
sink.disconnect(static_cast<const void *>(nullptr));
|
||||
|
||||
ASSERT_FALSE(sigh.empty());
|
||||
ASSERT_EQ(2u, sigh.size());
|
||||
|
||||
sink.disconnect(&l1);
|
||||
|
||||
ASSERT_FALSE(sigh.empty());
|
||||
ASSERT_EQ(1u, sigh.size());
|
||||
}
|
||||
|
||||
TEST_F(SigH, Collector) {
|
||||
sigh_listener listener;
|
||||
entt::sigh<bool(int)> sigh;
|
||||
entt::sink sink{sigh};
|
||||
int cnt = 0;
|
||||
|
||||
sink.connect<&sigh_listener::g>(&listener);
|
||||
sink.connect<&sigh_listener::h>(listener);
|
||||
|
||||
auto no_return = [&listener, &cnt](bool value) {
|
||||
ASSERT_TRUE(value);
|
||||
listener.k = true;
|
||||
++cnt;
|
||||
};
|
||||
|
||||
listener.k = true;
|
||||
sigh.collect(std::move(no_return), 42);
|
||||
|
||||
ASSERT_FALSE(sigh.empty());
|
||||
ASSERT_EQ(cnt, 2);
|
||||
|
||||
auto bool_return = [&cnt](bool value) {
|
||||
// gtest and its macro hell are sometimes really annoying...
|
||||
[](auto v) { ASSERT_TRUE(v); }(value);
|
||||
++cnt;
|
||||
return true;
|
||||
};
|
||||
|
||||
cnt = 0;
|
||||
sigh.collect(std::move(bool_return), 42);
|
||||
|
||||
ASSERT_EQ(cnt, 1);
|
||||
}
|
||||
|
||||
TEST_F(SigH, CollectorVoid) {
|
||||
sigh_listener listener;
|
||||
entt::sigh<void(int)> sigh;
|
||||
entt::sink sink{sigh};
|
||||
int cnt = 0;
|
||||
|
||||
sink.connect<&sigh_listener::g>(&listener);
|
||||
sink.connect<&sigh_listener::h>(listener);
|
||||
sigh.collect([&cnt]() { ++cnt; }, 42);
|
||||
|
||||
ASSERT_FALSE(sigh.empty());
|
||||
ASSERT_EQ(cnt, 2);
|
||||
|
||||
auto test = [&cnt]() {
|
||||
++cnt;
|
||||
return true;
|
||||
};
|
||||
|
||||
cnt = 0;
|
||||
sigh.collect(std::move(test), 42);
|
||||
|
||||
ASSERT_EQ(cnt, 1);
|
||||
}
|
||||
|
||||
TEST_F(SigH, Connection) {
|
||||
entt::sigh<void(int &)> sigh;
|
||||
entt::sink sink{sigh};
|
||||
int v = 0;
|
||||
|
||||
auto conn = sink.connect<&sigh_listener::f>();
|
||||
sigh.publish(v);
|
||||
|
||||
ASSERT_FALSE(sigh.empty());
|
||||
ASSERT_TRUE(conn);
|
||||
ASSERT_EQ(42, v);
|
||||
|
||||
v = 0;
|
||||
conn.release();
|
||||
sigh.publish(v);
|
||||
|
||||
ASSERT_TRUE(sigh.empty());
|
||||
ASSERT_FALSE(conn);
|
||||
ASSERT_EQ(0, v);
|
||||
}
|
||||
|
||||
TEST_F(SigH, ScopedConnection) {
|
||||
sigh_listener listener;
|
||||
entt::sigh<void(int)> sigh;
|
||||
entt::sink sink{sigh};
|
||||
|
||||
{
|
||||
ASSERT_FALSE(listener.k);
|
||||
|
||||
entt::scoped_connection conn = sink.connect<&sigh_listener::g>(listener);
|
||||
sigh.publish(42);
|
||||
|
||||
ASSERT_FALSE(sigh.empty());
|
||||
ASSERT_TRUE(listener.k);
|
||||
ASSERT_TRUE(conn);
|
||||
}
|
||||
|
||||
sigh.publish(42);
|
||||
|
||||
ASSERT_TRUE(sigh.empty());
|
||||
ASSERT_TRUE(listener.k);
|
||||
}
|
||||
|
||||
TEST_F(SigH, ScopedConnectionMove) {
|
||||
sigh_listener listener;
|
||||
entt::sigh<void(int)> sigh;
|
||||
entt::sink sink{sigh};
|
||||
|
||||
entt::scoped_connection outer{sink.connect<&sigh_listener::g>(listener)};
|
||||
|
||||
ASSERT_FALSE(sigh.empty());
|
||||
ASSERT_TRUE(outer);
|
||||
|
||||
{
|
||||
entt::scoped_connection inner{std::move(outer)};
|
||||
|
||||
ASSERT_FALSE(listener.k);
|
||||
ASSERT_FALSE(outer);
|
||||
ASSERT_TRUE(inner);
|
||||
|
||||
sigh.publish(42);
|
||||
|
||||
ASSERT_TRUE(listener.k);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(sigh.empty());
|
||||
|
||||
outer = sink.connect<&sigh_listener::g>(listener);
|
||||
|
||||
ASSERT_FALSE(sigh.empty());
|
||||
ASSERT_TRUE(outer);
|
||||
|
||||
{
|
||||
entt::scoped_connection inner{};
|
||||
|
||||
ASSERT_TRUE(listener.k);
|
||||
ASSERT_TRUE(outer);
|
||||
ASSERT_FALSE(inner);
|
||||
|
||||
inner = std::move(outer);
|
||||
|
||||
ASSERT_FALSE(outer);
|
||||
ASSERT_TRUE(inner);
|
||||
|
||||
sigh.publish(42);
|
||||
|
||||
ASSERT_FALSE(listener.k);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(sigh.empty());
|
||||
}
|
||||
|
||||
TEST_F(SigH, ScopedConnectionConstructorsAndOperators) {
|
||||
sigh_listener listener;
|
||||
entt::sigh<void(int)> sigh;
|
||||
entt::sink sink{sigh};
|
||||
|
||||
{
|
||||
entt::scoped_connection inner{};
|
||||
|
||||
ASSERT_TRUE(sigh.empty());
|
||||
ASSERT_FALSE(listener.k);
|
||||
ASSERT_FALSE(inner);
|
||||
|
||||
inner = sink.connect<&sigh_listener::g>(listener);
|
||||
sigh.publish(42);
|
||||
|
||||
ASSERT_FALSE(sigh.empty());
|
||||
ASSERT_TRUE(listener.k);
|
||||
ASSERT_TRUE(inner);
|
||||
|
||||
inner.release();
|
||||
|
||||
ASSERT_TRUE(sigh.empty());
|
||||
ASSERT_FALSE(inner);
|
||||
|
||||
auto basic = sink.connect<&sigh_listener::g>(listener);
|
||||
inner = std::as_const(basic);
|
||||
sigh.publish(42);
|
||||
|
||||
ASSERT_FALSE(sigh.empty());
|
||||
ASSERT_FALSE(listener.k);
|
||||
ASSERT_TRUE(inner);
|
||||
}
|
||||
|
||||
sigh.publish(42);
|
||||
|
||||
ASSERT_TRUE(sigh.empty());
|
||||
ASSERT_FALSE(listener.k);
|
||||
}
|
||||
|
||||
TEST_F(SigH, ConstNonConstNoExcept) {
|
||||
entt::sigh<void()> sigh;
|
||||
entt::sink sink{sigh};
|
||||
const_nonconst_noexcept functor;
|
||||
const const_nonconst_noexcept cfunctor;
|
||||
|
||||
sink.connect<&const_nonconst_noexcept::f>(functor);
|
||||
sink.connect<&const_nonconst_noexcept::g>(&functor);
|
||||
sink.connect<&const_nonconst_noexcept::h>(cfunctor);
|
||||
sink.connect<&const_nonconst_noexcept::i>(&cfunctor);
|
||||
sigh.publish();
|
||||
|
||||
ASSERT_EQ(functor.cnt, 2);
|
||||
ASSERT_EQ(cfunctor.cnt, 2);
|
||||
|
||||
sink.disconnect<&const_nonconst_noexcept::f>(functor);
|
||||
sink.disconnect<&const_nonconst_noexcept::g>(&functor);
|
||||
sink.disconnect<&const_nonconst_noexcept::h>(cfunctor);
|
||||
sink.disconnect<&const_nonconst_noexcept::i>(&cfunctor);
|
||||
sigh.publish();
|
||||
|
||||
ASSERT_EQ(functor.cnt, 2);
|
||||
ASSERT_EQ(cfunctor.cnt, 2);
|
||||
}
|
||||
|
||||
TEST_F(SigH, BeforeFunction) {
|
||||
entt::sigh<void(int)> sigh;
|
||||
entt::sink sink{sigh};
|
||||
before_after functor;
|
||||
|
||||
sink.connect<&before_after::add>(functor);
|
||||
sink.connect<&before_after::static_add>();
|
||||
sink.before<&before_after::static_add>().connect<&before_after::mul>(functor);
|
||||
sigh.publish(2);
|
||||
|
||||
ASSERT_EQ(functor.value, 6);
|
||||
}
|
||||
|
||||
TEST_F(SigH, BeforeMemberFunction) {
|
||||
entt::sigh<void(int)> sigh;
|
||||
entt::sink sink{sigh};
|
||||
before_after functor;
|
||||
|
||||
sink.connect<&before_after::static_add>();
|
||||
sink.connect<&before_after::add>(functor);
|
||||
sink.before<&before_after::add>(functor).connect<&before_after::mul>(functor);
|
||||
sigh.publish(2);
|
||||
|
||||
ASSERT_EQ(functor.value, 6);
|
||||
}
|
||||
|
||||
TEST_F(SigH, BeforeFunctionWithPayload) {
|
||||
entt::sigh<void(int)> sigh;
|
||||
entt::sink sink{sigh};
|
||||
before_after functor;
|
||||
|
||||
sink.connect<&before_after::static_add>();
|
||||
sink.connect<&before_after::static_mul>(functor);
|
||||
sink.before<&before_after::static_mul>(functor).connect<&before_after::add>(functor);
|
||||
sigh.publish(2);
|
||||
|
||||
ASSERT_EQ(functor.value, 8);
|
||||
}
|
||||
|
||||
TEST_F(SigH, BeforeInstanceOrPayload) {
|
||||
entt::sigh<void(int)> sigh;
|
||||
entt::sink sink{sigh};
|
||||
before_after functor;
|
||||
|
||||
sink.connect<&before_after::static_mul>(functor);
|
||||
sink.connect<&before_after::add>(functor);
|
||||
sink.before(functor).connect<&before_after::static_add>();
|
||||
sigh.publish(2);
|
||||
|
||||
ASSERT_EQ(functor.value, 6);
|
||||
}
|
||||
|
||||
TEST_F(SigH, BeforeAnythingElse) {
|
||||
entt::sigh<void(int)> sigh;
|
||||
entt::sink sink{sigh};
|
||||
before_after functor;
|
||||
|
||||
sink.connect<&before_after::add>(functor);
|
||||
sink.before().connect<&before_after::mul>(functor);
|
||||
sigh.publish(2);
|
||||
|
||||
ASSERT_EQ(functor.value, 2);
|
||||
}
|
||||
|
||||
TEST_F(SigH, BeforeListenerNotPresent) {
|
||||
entt::sigh<void(int)> sigh;
|
||||
entt::sink sink{sigh};
|
||||
before_after functor;
|
||||
|
||||
sink.connect<&before_after::mul>(functor);
|
||||
sink.before<&before_after::add>(&functor).connect<&before_after::add>(functor);
|
||||
sigh.publish(2);
|
||||
|
||||
ASSERT_EQ(functor.value, 2);
|
||||
}
|
||||
|
||||
TEST_F(SigH, UnboundDataMember) {
|
||||
sigh_listener listener;
|
||||
entt::sigh<bool &(sigh_listener &)> sigh;
|
||||
entt::sink sink{sigh};
|
||||
|
||||
ASSERT_FALSE(listener.k);
|
||||
|
||||
sink.connect<&sigh_listener::k>();
|
||||
sigh.collect([](bool &value) { value = !value; }, listener);
|
||||
|
||||
ASSERT_TRUE(listener.k);
|
||||
}
|
||||
|
||||
TEST_F(SigH, UnboundMemberFunction) {
|
||||
sigh_listener listener;
|
||||
entt::sigh<void(sigh_listener *, int)> sigh;
|
||||
entt::sink sink{sigh};
|
||||
|
||||
ASSERT_FALSE(listener.k);
|
||||
|
||||
sink.connect<&sigh_listener::g>();
|
||||
sigh.publish(&listener, 42);
|
||||
|
||||
ASSERT_TRUE(listener.k);
|
||||
}
|
||||
|
||||
TEST_F(SigH, CustomAllocator) {
|
||||
std::allocator<void (*)(int)> allocator;
|
||||
entt::sigh<void(int), decltype(allocator)> sigh{allocator};
|
||||
|
||||
ASSERT_EQ(sigh.get_allocator(), allocator);
|
||||
ASSERT_FALSE(sigh.get_allocator() != allocator);
|
||||
ASSERT_TRUE(sigh.empty());
|
||||
|
||||
entt::sink sink{sigh};
|
||||
sigh_listener listener;
|
||||
sink.template connect<&sigh_listener::g>(listener);
|
||||
|
||||
decltype(sigh) copy{sigh, allocator};
|
||||
sink.disconnect(listener);
|
||||
|
||||
ASSERT_TRUE(sigh.empty());
|
||||
ASSERT_FALSE(copy.empty());
|
||||
|
||||
sigh = copy;
|
||||
|
||||
ASSERT_FALSE(sigh.empty());
|
||||
ASSERT_FALSE(copy.empty());
|
||||
|
||||
decltype(sigh) move{std::move(copy), allocator};
|
||||
|
||||
ASSERT_TRUE(copy.empty());
|
||||
ASSERT_FALSE(move.empty());
|
||||
|
||||
sink = entt::sink{move};
|
||||
sink.disconnect(&listener);
|
||||
|
||||
ASSERT_TRUE(copy.empty());
|
||||
ASSERT_TRUE(move.empty());
|
||||
|
||||
sink.template connect<&sigh_listener::g>(listener);
|
||||
copy.swap(move);
|
||||
|
||||
ASSERT_FALSE(copy.empty());
|
||||
ASSERT_TRUE(move.empty());
|
||||
|
||||
sink = entt::sink{copy};
|
||||
sink.disconnect();
|
||||
|
||||
ASSERT_TRUE(copy.empty());
|
||||
ASSERT_TRUE(move.empty());
|
||||
}
|
Reference in New Issue
Block a user