From faa419fc8bd29011d8efb58c5144d2e815d0f600 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Fri, 12 Apr 2019 19:27:39 +0300 Subject: Add Irrlicht-specific smart pointer (#6814) --- src/unittest/CMakeLists.txt | 1 + src/unittest/test_irrptr.cpp | 131 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 src/unittest/test_irrptr.cpp (limited to 'src/unittest') diff --git a/src/unittest/CMakeLists.txt b/src/unittest/CMakeLists.txt index 71aa1fa56..82f9a4a13 100644 --- a/src/unittest/CMakeLists.txt +++ b/src/unittest/CMakeLists.txt @@ -10,6 +10,7 @@ set (UNITTEST_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/test_connection.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_filepath.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_inventory.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test_irrptr.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_map_settings_manager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_mapnode.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_modchannels.cpp diff --git a/src/unittest/test_irrptr.cpp b/src/unittest/test_irrptr.cpp new file mode 100644 index 000000000..aa857ff46 --- /dev/null +++ b/src/unittest/test_irrptr.cpp @@ -0,0 +1,131 @@ +/* +Minetest +Copyright (C) 2018 numzero, Lobachevskiy Vitaliy + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "test.h" + +#include "exceptions.h" +#include "irr_ptr.h" + +class TestIrrPtr : public TestBase +{ +public: + TestIrrPtr() { TestManager::registerTestModule(this); } + const char *getName() { return "TestIrrPtr"; } + + void runTests(IGameDef *gamedef); + + void testRefCounting(); + void testSelfAssignment(); + void testNullHandling(); +}; + +static TestIrrPtr g_test_instance; + +void TestIrrPtr::runTests(IGameDef *gamedef) +{ + TEST(testRefCounting); + TEST(testSelfAssignment); + TEST(testNullHandling); +} + +//////////////////////////////////////////////////////////////////////////////// + +#define UASSERT_REFERENCE_COUNT(object, value, info) \ + UTEST((object)->getReferenceCount() == value, \ + info "Reference count is %d instead of " #value, \ + (object)->getReferenceCount()) + +void TestIrrPtr::testRefCounting() +{ + IReferenceCounted *obj = new IReferenceCounted(); // RC=1 + obj->grab(); + UASSERT_REFERENCE_COUNT(obj, 2, "Pre-condition failed: "); + { + irr_ptr p1{obj}; // move semantics + UASSERT(p1.get() == obj); + UASSERT_REFERENCE_COUNT(obj, 2, ); + + irr_ptr p2{p1}; // copy ctor + UASSERT(p1.get() == obj); + UASSERT(p2.get() == obj); + UASSERT_REFERENCE_COUNT(obj, 3, ); + + irr_ptr p3{std::move(p1)}; // move ctor + UASSERT(p1.get() == nullptr); + UASSERT(p3.get() == obj); + UASSERT_REFERENCE_COUNT(obj, 3, ); + + p1 = std::move(p2); // move assignment + UASSERT(p1.get() == obj); + UASSERT(p2.get() == nullptr); + UASSERT_REFERENCE_COUNT(obj, 3, ); + + p2 = p3; // copy assignment + UASSERT(p2.get() == obj); + UASSERT(p3.get() == obj); + UASSERT_REFERENCE_COUNT(obj, 4, ); + + p1.release(); + UASSERT(p1.get() == nullptr); + UASSERT_REFERENCE_COUNT(obj, 4, ); + } + UASSERT_REFERENCE_COUNT(obj, 2, ); + obj->drop(); + UTEST(obj->drop(), "Dropping failed: reference count is %d", + obj->getReferenceCount()); +} + +void TestIrrPtr::testSelfAssignment() +{ + irr_ptr p1{new IReferenceCounted()}; + UASSERT(p1); + UASSERT_REFERENCE_COUNT(p1, 1, ); + p1 = p1; + UASSERT(p1); + UASSERT_REFERENCE_COUNT(p1, 1, ); + p1 = std::move(p1); + UASSERT(p1); + UASSERT_REFERENCE_COUNT(p1, 1, ); +} + +void TestIrrPtr::testNullHandling() +{ + // In the case of an error, it will probably crash with SEGV. + // Nevertheless, UASSERTs are used to catch possible corner cases. + irr_ptr p1{new IReferenceCounted()}; + UASSERT(p1); + irr_ptr p2; + UASSERT(!p2); + irr_ptr p3{p2}; + UASSERT(!p2); + UASSERT(!p3); + irr_ptr p4{std::move(p2)}; + UASSERT(!p2); + UASSERT(!p4); + p2 = p2; + UASSERT(!p2); + p2 = std::move(p2); + UASSERT(!p2); + p3 = p2; + UASSERT(!p2); + UASSERT(!p3); + p3 = std::move(p2); + UASSERT(!p2); + UASSERT(!p3); +} -- cgit v1.2.3