?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. // https://github.com/vinniefalco/LuaBridge
  2. // Copyright 2021, Stefan Frings
  3. // SPDX-License-Identifier: MIT
  4.  
  5. #include <gtest/gtest.h>
  6.  
  7. #include "LuaBridge/RefCountedPtr.h"
  8.  
  9. class RefCountedPtrTests : public ::testing::Test, private luabridge::detail::RefCountedPtrBase
  10. {
  11. public:
  12.     void SetUp() override { getRefCounts().clear(); }
  13.  
  14.     void TearDown() override
  15.     {
  16.         for (const RefCountsType::value_type& refCountEntry : getRefCounts())
  17.         {
  18.             std::cout << "REMAINING ptr=" << refCountEntry.first
  19.                       << ", count=" << refCountEntry.second << std::endl;
  20.         }
  21.  
  22.         ASSERT_TRUE(getRefCounts().empty());
  23.     }
  24.  
  25.     size_t getNumRefCounts() const { return getRefCounts().size(); }
  26. };
  27.  
  28. TEST_F(RefCountedPtrTests, ConstructorDefault)
  29. {
  30.     const luabridge::RefCountedPtr<int> ptr;
  31.  
  32.     ASSERT_EQ(ptr, nullptr);
  33.     ASSERT_EQ(getNumRefCounts(), 0);
  34.     ASSERT_EQ(ptr.use_count(), 0);
  35. }
  36.  
  37. TEST_F(RefCountedPtrTests, ConstructorObject)
  38. {
  39.     int* const rawPtr = new int(123);
  40.     const luabridge::RefCountedPtr<int> ptr(rawPtr);
  41.  
  42.     ASSERT_EQ(ptr, rawPtr);
  43.     ASSERT_EQ(getNumRefCounts(), 1);
  44.     ASSERT_EQ(ptr.use_count(), 1);
  45. }
  46.  
  47. TEST_F(RefCountedPtrTests, ConstructorCopy)
  48. {
  49.     int* const rawPtr = new int(123);
  50.     const luabridge::RefCountedPtr<int> ptr(rawPtr);
  51.     const luabridge::RefCountedPtr<int> ptrCopy(ptr);
  52.  
  53.     ASSERT_EQ(ptr, rawPtr);
  54.     ASSERT_EQ(ptrCopy, rawPtr);
  55.     ASSERT_EQ(getNumRefCounts(), 1);
  56.     ASSERT_EQ(ptr.use_count(), 2);
  57.     ASSERT_EQ(ptrCopy.use_count(), 2);
  58. }
  59.  
  60. TEST_F(RefCountedPtrTests, ConstructorCopyPolymorph)
  61. {
  62.     struct Base
  63.     {
  64.     };
  65.     struct Specialized : public Base
  66.     {
  67.     };
  68.     Specialized* const rawPtr = new Specialized;
  69.  
  70.     const luabridge::RefCountedPtr<Specialized> ptr(rawPtr);
  71.     const luabridge::RefCountedPtr<Base> ptrCopy(ptr);
  72.  
  73.     ASSERT_EQ(ptr, rawPtr);
  74.     ASSERT_EQ(ptrCopy, rawPtr);
  75.     ASSERT_EQ(getNumRefCounts(), 1);
  76.     ASSERT_EQ(ptr.use_count(), 2);
  77.     ASSERT_EQ(ptrCopy.use_count(), 2);
  78. }
  79.  
  80. namespace {
  81.  
  82. class TestObject
  83. {
  84. public:
  85.     explicit TestObject(bool& deleted) : m_deleted(deleted) { m_deleted = false; }
  86.  
  87.     ~TestObject() { m_deleted = true; }
  88.  
  89. private:
  90.     bool& m_deleted;
  91. };
  92.  
  93. } // namespace
  94.  
  95. TEST_F(RefCountedPtrTests, Destructor)
  96. {
  97.     bool deleted = false;
  98.     {
  99.         const luabridge::RefCountedPtr<TestObject> ptr(new TestObject(deleted));
  100.         ASSERT_FALSE(deleted);
  101.     }
  102.  
  103.     ASSERT_TRUE(deleted);
  104. }
  105.  
  106. TEST_F(RefCountedPtrTests, ResetObject)
  107. {
  108.     bool deleted = false;
  109.     luabridge::RefCountedPtr<TestObject> ptr(new TestObject(deleted));
  110.     ASSERT_FALSE(deleted);
  111.  
  112.     ptr.reset();
  113.  
  114.     ASSERT_EQ(ptr, nullptr);
  115.     ASSERT_TRUE(deleted);
  116. }
  117.  
  118. TEST_F(RefCountedPtrTests, ResetNull)
  119. {
  120.     luabridge::RefCountedPtr<TestObject> ptr;
  121.  
  122.     ptr.reset();
  123.  
  124.     ASSERT_EQ(ptr, nullptr);
  125. }
  126.  
  127. TEST_F(RefCountedPtrTests, AssignOperator)
  128. {
  129.     bool deletedPrevious = false;
  130.     luabridge::RefCountedPtr<TestObject> ptr(new TestObject(deletedPrevious));
  131.  
  132.     bool deletedNew = false;
  133.     TestObject* const rawPtr = new TestObject(deletedNew);
  134.  
  135.     const luabridge::RefCountedPtr<TestObject>& returnValue = (ptr = rawPtr);
  136.  
  137.     ASSERT_EQ(&returnValue, &ptr);
  138.     ASSERT_EQ(ptr, rawPtr);
  139.     ASSERT_EQ(getNumRefCounts(), 1);
  140.     ASSERT_EQ(ptr.use_count(), 1);
  141.     ASSERT_TRUE(deletedPrevious);
  142.     ASSERT_FALSE(deletedNew);
  143. }
  144.  
  145. TEST_F(RefCountedPtrTests, AssignOperatorSameObject)
  146. {
  147.     bool deleted = false;
  148.     TestObject* const rawPtr = new TestObject(deleted);
  149.  
  150.     luabridge::RefCountedPtr<TestObject> ptr(rawPtr);
  151.  
  152.     const luabridge::RefCountedPtr<TestObject>& returnValue = (ptr = rawPtr);
  153.  
  154.     ASSERT_EQ(&returnValue, &ptr);
  155.     ASSERT_EQ(ptr, rawPtr);
  156.     ASSERT_EQ(getNumRefCounts(), 1);
  157.     ASSERT_EQ(ptr.use_count(), 1);
  158.     ASSERT_FALSE(deleted);
  159. }
  160.  
  161. TEST_F(RefCountedPtrTests, AssignOperatorRef)
  162. {
  163.     bool deletedPrevious = false;
  164.     luabridge::RefCountedPtr<TestObject> ptr(new TestObject(deletedPrevious));
  165.  
  166.     bool deletedNew = false;
  167.     TestObject* const rawPtrNew = new TestObject(deletedNew);
  168.     const luabridge::RefCountedPtr<TestObject> ptrNew(rawPtrNew);
  169.  
  170.     const luabridge::RefCountedPtr<TestObject>& returnValue = (ptr = ptrNew);
  171.  
  172.     ASSERT_EQ(&returnValue, &ptr);
  173.     ASSERT_EQ(ptr, rawPtrNew);
  174.     ASSERT_EQ(getNumRefCounts(), 1);
  175.     ASSERT_EQ(ptr.use_count(), 2);
  176.     ASSERT_EQ(ptrNew.use_count(), 2);
  177.     ASSERT_TRUE(deletedPrevious);
  178.     ASSERT_FALSE(deletedNew);
  179. }
  180.  
  181. TEST_F(RefCountedPtrTests, AssignOperatorRefPolymorph)
  182. {
  183.     struct TestObjectSpecialized : public TestObject
  184.     {
  185.         explicit TestObjectSpecialized(bool& deleted) : TestObject(deleted) {}
  186.     };
  187.  
  188.     bool deletedPrevious = false;
  189.     luabridge::RefCountedPtr<TestObject> ptr(new TestObject(deletedPrevious));
  190.  
  191.     bool deletedNew = false;
  192.     TestObjectSpecialized* const rawPtrNew = new TestObjectSpecialized(deletedNew);
  193.     const luabridge::RefCountedPtr<TestObjectSpecialized> ptrNew(rawPtrNew);
  194.  
  195.     const luabridge::RefCountedPtr<TestObject>& returnValue = (ptr = ptrNew);
  196.  
  197.     ASSERT_EQ(&returnValue, &ptr);
  198.     ASSERT_EQ(ptr, rawPtrNew);
  199.     ASSERT_EQ(getNumRefCounts(), 1);
  200.     ASSERT_EQ(ptr.use_count(), 2);
  201.     ASSERT_EQ(ptrNew.use_count(), 2);
  202.     ASSERT_TRUE(deletedPrevious);
  203.     ASSERT_FALSE(deletedNew);
  204. }
  205.  
  206. TEST_F(RefCountedPtrTests, AssignOperatorRefSelfAssignment)
  207. {
  208.     bool deleted = false;
  209.     TestObject* const rawPtr = new TestObject(deleted);
  210.  
  211.     luabridge::RefCountedPtr<TestObject> ptr(rawPtr);
  212.  
  213.     const luabridge::RefCountedPtr<TestObject>& returnValue = (ptr = ptr);
  214.  
  215.     ASSERT_EQ(&returnValue, &ptr);
  216.     ASSERT_EQ(ptr, rawPtr);
  217.     ASSERT_EQ(getNumRefCounts(), 1);
  218.     ASSERT_EQ(ptr.use_count(), 1);
  219.     ASSERT_FALSE(deleted);
  220. }
  221.  
  222. TEST_F(RefCountedPtrTests, AssignOperatorRefSameObject)
  223. {
  224.     bool deleted = false;
  225.     TestObject* const rawPtr = new TestObject(deleted);
  226.  
  227.     const luabridge::RefCountedPtr<TestObject> ptr1(rawPtr);
  228.     luabridge::RefCountedPtr<TestObject> ptr2(rawPtr);
  229.  
  230.     const luabridge::RefCountedPtr<TestObject>& returnValue = (ptr2 = ptr1);
  231.  
  232.     ASSERT_EQ(&returnValue, &ptr2);
  233.     ASSERT_EQ(ptr1, rawPtr);
  234.     ASSERT_EQ(ptr2, rawPtr);
  235.     ASSERT_EQ(getNumRefCounts(), 1);
  236.     ASSERT_EQ(ptr1.use_count(), 2);
  237.     ASSERT_EQ(ptr2.use_count(), 2);
  238.     ASSERT_FALSE(deleted);
  239. }
  240.  
  241. namespace {
  242.  
  243. class TestObjectNested
  244. {
  245. public:
  246.     explicit TestObjectNested(const uint64_t value) : m_value(value) {}
  247.  
  248.     uint64_t getValue() const { return m_value; }
  249.  
  250.     luabridge::RefCountedPtr<TestObjectNested>& getChild() { return m_child; }
  251.  
  252. private:
  253.     const uint64_t m_value;
  254.  
  255.     luabridge::RefCountedPtr<TestObjectNested> m_child;
  256. };
  257.  
  258. } // namespace
  259.  
  260. TEST_F(RefCountedPtrTests, AssignOperatorRefNestedObjects)
  261. {
  262.     // Test assignment operator in the case that the previous referenced object is
  263.     // part of the new referenced object. This nested situation can only be handled
  264.     // if the reference count of the new object is FIRST increased and after that
  265.     // the count of the old object is decreased. If this happens vice versa the
  266.     // stored pointer is invalid after the assignment because it points to an already
  267.     // deleted object.
  268.     const uint64_t parentValue = 123, childValue = 456;
  269.  
  270.     luabridge::RefCountedPtr<TestObjectNested> ref = new TestObjectNested(parentValue);
  271.     ref->getChild() = new TestObjectNested(childValue);
  272.  
  273.     ASSERT_EQ(ref->getValue(), parentValue);
  274.     ASSERT_EQ(ref->getChild()->getValue(), childValue);
  275.  
  276.     const luabridge::RefCountedPtr<TestObjectNested>& returnValue = (ref = ref->getChild());
  277.     ASSERT_EQ(&returnValue, &ref);
  278.     ASSERT_EQ(ref->getValue(), childValue);
  279. }
  280.  
  281. TEST_F(RefCountedPtrTests, CompareOperators)
  282. {
  283.     int* const rawPtr1 = new int;
  284.     luabridge::RefCountedPtr<int> ptr1(rawPtr1);
  285.  
  286.     int* const rawPtr2 = new int;
  287.     luabridge::RefCountedPtr<int> ptr2(rawPtr2);
  288.  
  289.     ASSERT_TRUE(ptr1 == ptr1);
  290.     ASSERT_TRUE(ptr1 != ptr2);
  291.  
  292.     ASSERT_TRUE(rawPtr1 == ptr1);
  293.     ASSERT_TRUE(ptr1 == rawPtr1);
  294.  
  295.     ASSERT_TRUE(rawPtr2 != ptr1);
  296.     ASSERT_TRUE(ptr1 != rawPtr2);
  297. }
  298.