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

/*-
* 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