mirror of https://github.com/rspamd/rspamd.git
Rapid spam filtering system
https://rspamd.com/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
344 lines
7.3 KiB
344 lines
7.3 KiB
/*-
|
|
* Copyright 2021 Vsevolod Stakhov
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef RSPAMD_RSPAMD_CXX_LOCAL_PTR_HXX
|
|
#define RSPAMD_RSPAMD_CXX_LOCAL_PTR_HXX
|
|
|
|
#define DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
|
|
#include "doctest/doctest.h"
|
|
|
|
#include "libutil/cxx/local_shared_ptr.hxx"
|
|
|
|
namespace test_internal {
|
|
struct deleter_test {
|
|
bool *pv;
|
|
|
|
deleter_test(bool &v)
|
|
{
|
|
v = false;
|
|
pv = &v;
|
|
}
|
|
|
|
~deleter_test()
|
|
{
|
|
*pv = true;
|
|
}
|
|
};
|
|
}// namespace test_internal
|
|
|
|
namespace std {
|
|
template<>
|
|
struct hash<test_internal::deleter_test> {
|
|
inline auto operator()(const test_internal::deleter_test &) const noexcept -> auto
|
|
{
|
|
return 42;
|
|
}
|
|
};
|
|
}// namespace std
|
|
|
|
TEST_SUITE("local_ptr")
|
|
{
|
|
using namespace test_internal;
|
|
|
|
TEST_CASE("shared_ptr from nullptr")
|
|
{
|
|
rspamd::local_shared_ptr<int const> pi(static_cast<int *>(nullptr));
|
|
CHECK((!!pi ? false : true));
|
|
CHECK(!pi);
|
|
CHECK(pi.get() == nullptr);
|
|
CHECK(pi.use_count() == 1);
|
|
CHECK(pi.unique());
|
|
}
|
|
TEST_CASE("shared_ptr from ptr")
|
|
{
|
|
int *p = new int(7);
|
|
rspamd::local_shared_ptr<int> pi(p);
|
|
CHECK((pi ? true : false));
|
|
CHECK(!!pi);
|
|
CHECK(pi.get() == p);
|
|
CHECK(pi.use_count() == 1);
|
|
CHECK(pi.unique());
|
|
CHECK(*pi == 7);
|
|
}
|
|
|
|
TEST_CASE("shared_ptr copy")
|
|
{
|
|
rspamd::local_shared_ptr<int> pi;
|
|
|
|
rspamd::local_shared_ptr<int> pi2(pi);
|
|
CHECK(pi2 == pi);
|
|
CHECK((pi2 ? false : true));
|
|
CHECK(!pi2);
|
|
CHECK(pi2.get() == nullptr);
|
|
CHECK(pi2.use_count() == pi.use_count());
|
|
|
|
rspamd::local_shared_ptr<int> pi3(pi);
|
|
CHECK(pi3 == pi);
|
|
CHECK((pi3 ? false : true));
|
|
CHECK(!pi3);
|
|
CHECK(pi3.get() == nullptr);
|
|
CHECK(pi3.use_count() == pi.use_count());
|
|
|
|
rspamd::local_shared_ptr<int> pi4(pi3);
|
|
CHECK(pi4 == pi3);
|
|
CHECK((pi4 ? false : true));
|
|
CHECK(!pi4);
|
|
CHECK(pi4.get() == nullptr);
|
|
CHECK(pi4.use_count() == pi3.use_count());
|
|
|
|
int *p = new int(7);
|
|
rspamd::local_shared_ptr<int> pi5(p);
|
|
|
|
rspamd::local_shared_ptr<int> pi6(pi5);
|
|
CHECK(pi5 == pi6);
|
|
CHECK((pi6 ? true : false));
|
|
CHECK(!!pi6);
|
|
CHECK(pi6.get() == p);
|
|
CHECK(pi6.use_count() == 2);
|
|
CHECK(!pi6.unique());
|
|
CHECK(*pi6 == 7);
|
|
CHECK(pi6.use_count() == pi6.use_count());
|
|
CHECK(!(pi5 < pi6 || pi5 < pi6));// shared ownership test
|
|
|
|
auto pi7 = pi6;
|
|
CHECK(pi5 == pi7);
|
|
CHECK((pi7 ? true : false));
|
|
CHECK(!!pi7);
|
|
CHECK(pi7.get() == p);
|
|
CHECK(pi7.use_count() == 3);
|
|
CHECK(!pi7.unique());
|
|
CHECK(*pi7 == 7);
|
|
CHECK(pi7.use_count() == pi7.use_count());
|
|
CHECK(!(pi5 < pi7 || pi5 < pi7));// shared ownership test
|
|
}
|
|
|
|
TEST_CASE("shared_ptr move")
|
|
{
|
|
rspamd::local_shared_ptr<int> pi(new int);
|
|
|
|
rspamd::local_shared_ptr<int> pi2(std::move(pi));
|
|
CHECK(!(pi2 == pi));
|
|
CHECK((!pi2 ? false : true));
|
|
CHECK(!pi);
|
|
CHECK(pi.get() == nullptr);
|
|
CHECK(pi2.get() != nullptr);
|
|
CHECK(pi.use_count() != pi2.use_count());
|
|
|
|
std::swap(pi, pi2);
|
|
CHECK(!(pi2 == pi));
|
|
CHECK((!pi ? false : true));
|
|
CHECK(!pi2);
|
|
CHECK(pi.get() != nullptr);
|
|
CHECK(pi2.get() == nullptr);
|
|
CHECK(pi.use_count() != pi2.use_count());
|
|
}
|
|
|
|
TEST_CASE("shared_ptr dtor")
|
|
{
|
|
bool t;
|
|
|
|
{
|
|
rspamd::local_shared_ptr<deleter_test> pi(new deleter_test{t});
|
|
|
|
CHECK((!pi ? false : true));
|
|
CHECK(!!pi);
|
|
CHECK(pi.get() != nullptr);
|
|
CHECK(pi.use_count() == 1);
|
|
CHECK(pi.unique());
|
|
CHECK(t == false);
|
|
}
|
|
|
|
CHECK(t == true);
|
|
|
|
{
|
|
rspamd::local_shared_ptr<deleter_test> pi(new deleter_test{t});
|
|
|
|
CHECK((!pi ? false : true));
|
|
CHECK(!!pi);
|
|
CHECK(pi.get() != nullptr);
|
|
CHECK(pi.use_count() == 1);
|
|
CHECK(pi.unique());
|
|
CHECK(t == false);
|
|
|
|
rspamd::local_shared_ptr<deleter_test> pi2(pi);
|
|
CHECK(pi2 == pi);
|
|
CHECK(pi.use_count() == 2);
|
|
pi.reset();
|
|
CHECK(!(pi2 == pi));
|
|
CHECK(pi2.use_count() == 1);
|
|
CHECK(t == false);
|
|
|
|
pi = pi2;
|
|
CHECK(pi2 == pi);
|
|
CHECK(pi.use_count() == 2);
|
|
CHECK(t == false);
|
|
}
|
|
|
|
CHECK(t == true);
|
|
}
|
|
|
|
TEST_CASE("make_shared dtor")
|
|
{
|
|
bool t;
|
|
|
|
{
|
|
auto pi = rspamd::local_make_shared<deleter_test>(t);
|
|
|
|
CHECK((!pi ? false : true));
|
|
CHECK(!!pi);
|
|
CHECK(pi.get() != nullptr);
|
|
CHECK(pi.use_count() == 1);
|
|
CHECK(pi.unique());
|
|
CHECK(t == false);
|
|
|
|
rspamd::local_shared_ptr<deleter_test> pi2(pi);
|
|
CHECK(pi2 == pi);
|
|
CHECK(pi.use_count() == 2);
|
|
pi.reset();
|
|
CHECK(!(pi2 == pi));
|
|
CHECK(pi2.use_count() == 1);
|
|
CHECK(t == false);
|
|
|
|
pi = pi2;
|
|
CHECK(pi2 == pi);
|
|
CHECK(pi.use_count() == 2);
|
|
CHECK(t == false);
|
|
}
|
|
|
|
CHECK(t == true);
|
|
}
|
|
|
|
TEST_CASE("shared_ptr dtor")
|
|
{
|
|
bool t;
|
|
|
|
{
|
|
rspamd::local_shared_ptr<deleter_test> pi(new deleter_test{t});
|
|
|
|
CHECK((!pi ? false : true));
|
|
CHECK(!!pi);
|
|
CHECK(pi.get() != nullptr);
|
|
CHECK(pi.use_count() == 1);
|
|
CHECK(pi.unique());
|
|
CHECK(t == false);
|
|
}
|
|
|
|
CHECK(t == true);
|
|
|
|
{
|
|
rspamd::local_shared_ptr<deleter_test> pi(new deleter_test{t});
|
|
|
|
CHECK((!pi ? false : true));
|
|
CHECK(!!pi);
|
|
CHECK(pi.get() != nullptr);
|
|
CHECK(pi.use_count() == 1);
|
|
CHECK(pi.unique());
|
|
CHECK(t == false);
|
|
|
|
rspamd::local_shared_ptr<deleter_test> pi2(pi);
|
|
CHECK(pi2 == pi);
|
|
CHECK(pi.use_count() == 2);
|
|
pi.reset();
|
|
CHECK(!(pi2 == pi));
|
|
CHECK(pi2.use_count() == 1);
|
|
CHECK(t == false);
|
|
|
|
pi = pi2;
|
|
CHECK(pi2 == pi);
|
|
CHECK(pi.use_count() == 2);
|
|
CHECK(t == false);
|
|
}
|
|
|
|
CHECK(t == true);
|
|
}
|
|
|
|
TEST_CASE("weak_ptr")
|
|
{
|
|
bool t;
|
|
|
|
{
|
|
rspamd::local_shared_ptr<deleter_test> pi(new deleter_test{t});
|
|
|
|
CHECK((!pi ? false : true));
|
|
CHECK(!!pi);
|
|
CHECK(pi.get() != nullptr);
|
|
CHECK(pi.use_count() == 1);
|
|
CHECK(pi.unique());
|
|
CHECK(t == false);
|
|
|
|
rspamd::local_weak_ptr<deleter_test> wp(pi);
|
|
CHECK(wp.lock().get() != nullptr);
|
|
CHECK(pi.use_count() == 1);
|
|
CHECK(wp.use_count() == 1);
|
|
pi.reset();
|
|
CHECK(pi.use_count() == 0);
|
|
CHECK(wp.use_count() == 0);
|
|
}
|
|
|
|
CHECK(t == true);
|
|
|
|
rspamd::local_weak_ptr<deleter_test> wp;
|
|
{
|
|
rspamd::local_shared_ptr<deleter_test> pi(new deleter_test{t});
|
|
wp = pi;
|
|
CHECK(!wp.expired());
|
|
CHECK(wp.lock().get() != nullptr);
|
|
}
|
|
|
|
CHECK(t == true);
|
|
CHECK(wp.expired());
|
|
}
|
|
|
|
TEST_CASE("std::swap")
|
|
{
|
|
bool t;
|
|
|
|
{
|
|
rspamd::local_shared_ptr<deleter_test> pi(new deleter_test{t});
|
|
CHECK(pi.use_count() == 1);
|
|
CHECK(pi.unique());
|
|
CHECK(t == false);
|
|
|
|
rspamd::local_shared_ptr<deleter_test> pi1;
|
|
CHECK(pi1.get() == nullptr);
|
|
CHECK(pi1.use_count() == 0);
|
|
std::swap(pi1, pi);
|
|
CHECK(pi.use_count() == 0);
|
|
CHECK(pi.get() == nullptr);
|
|
CHECK(pi1.get() != nullptr);
|
|
std::swap(pi, pi1);
|
|
CHECK(pi.use_count() != 0);
|
|
CHECK(pi.get() != nullptr);
|
|
CHECK(pi1.get() == nullptr);
|
|
}
|
|
|
|
CHECK(t == true);
|
|
}
|
|
|
|
TEST_CASE("std::hash")
|
|
{
|
|
bool v;
|
|
deleter_test dt(v);
|
|
CHECK(std::hash<deleter_test>()(dt) == 42);
|
|
auto pi = rspamd::local_make_shared<deleter_test>(v);
|
|
rspamd::local_shared_ptr<deleter_test> pi1;
|
|
CHECK(std::hash<decltype(pi)>()(pi) == 42);
|
|
// No hash for nullptr, different from std::smart_pointers!
|
|
CHECK_THROWS(std::hash<decltype(pi)>()(pi1));
|
|
}
|
|
}
|
|
|
|
#endif//RSPAMD_RSPAMD_CXX_LOCAL_PTR_HXX
|