11e22817dSNiels Sascha Reedijk /*
21e22817dSNiels Sascha Reedijk * Copyright 2022 Haiku Inc. All rights reserved.
31e22817dSNiels Sascha Reedijk * Distributed under the terms of the MIT License.
41e22817dSNiels Sascha Reedijk *
51e22817dSNiels Sascha Reedijk * Authors:
61e22817dSNiels Sascha Reedijk * Niels Sascha Reedijk, niels.reedijk@gmail.com
71e22817dSNiels Sascha Reedijk */
81e22817dSNiels Sascha Reedijk
91e22817dSNiels Sascha Reedijk #include "ExclusiveBorrowTest.h"
101e22817dSNiels Sascha Reedijk
111e22817dSNiels Sascha Reedijk #include <atomic>
121e22817dSNiels Sascha Reedijk #include <tuple>
131e22817dSNiels Sascha Reedijk
141e22817dSNiels Sascha Reedijk #include <cppunit/TestCaller.h>
151e22817dSNiels Sascha Reedijk #include <cppunit/TestSuite.h>
161e22817dSNiels Sascha Reedijk
171e22817dSNiels Sascha Reedijk #include <ExclusiveBorrow.h>
181e22817dSNiels Sascha Reedijk
191e22817dSNiels Sascha Reedijk using BPrivate::Network::BBorrow;
201e22817dSNiels Sascha Reedijk using BPrivate::Network::BBorrowError;
211e22817dSNiels Sascha Reedijk using BPrivate::Network::BExclusiveBorrow;
221e22817dSNiels Sascha Reedijk using BPrivate::Network::make_exclusive_borrow;
231e22817dSNiels Sascha Reedijk
241e22817dSNiels Sascha Reedijk
251e22817dSNiels Sascha Reedijk class DeleteTestHelper
261e22817dSNiels Sascha Reedijk {
271e22817dSNiels Sascha Reedijk public:
DeleteTestHelper(std::atomic<bool> & deleted)281e22817dSNiels Sascha Reedijk DeleteTestHelper(std::atomic<bool>& deleted)
29*71e29bbeSNiels Sascha Reedijk :
30*71e29bbeSNiels Sascha Reedijk fDeleted(deleted)
311e22817dSNiels Sascha Reedijk {
321e22817dSNiels Sascha Reedijk }
331e22817dSNiels Sascha Reedijk
~DeleteTestHelper()34*71e29bbeSNiels Sascha Reedijk ~DeleteTestHelper() { fDeleted.store(true); }
351e22817dSNiels Sascha Reedijk
361e22817dSNiels Sascha Reedijk private:
371e22817dSNiels Sascha Reedijk std::atomic<bool>& fDeleted;
381e22817dSNiels Sascha Reedijk };
391e22817dSNiels Sascha Reedijk
401e22817dSNiels Sascha Reedijk
41*71e29bbeSNiels Sascha Reedijk class Base
42*71e29bbeSNiels Sascha Reedijk {
431e22817dSNiels Sascha Reedijk public:
Base()44*71e29bbeSNiels Sascha Reedijk Base() {}
451e22817dSNiels Sascha Reedijk
461e22817dSNiels Sascha Reedijk
~Base()47*71e29bbeSNiels Sascha Reedijk virtual ~Base() {}
481e22817dSNiels Sascha Reedijk
491e22817dSNiels Sascha Reedijk
IsDerived()50*71e29bbeSNiels Sascha Reedijk virtual bool IsDerived() { return false; }
511e22817dSNiels Sascha Reedijk };
521e22817dSNiels Sascha Reedijk
531e22817dSNiels Sascha Reedijk
54*71e29bbeSNiels Sascha Reedijk class Derived : public Base
551e22817dSNiels Sascha Reedijk {
56*71e29bbeSNiels Sascha Reedijk public:
Derived()57*71e29bbeSNiels Sascha Reedijk Derived() {}
58*71e29bbeSNiels Sascha Reedijk
59*71e29bbeSNiels Sascha Reedijk
~Derived()60*71e29bbeSNiels Sascha Reedijk virtual ~Derived() {}
61*71e29bbeSNiels Sascha Reedijk
62*71e29bbeSNiels Sascha Reedijk
IsDerived()63*71e29bbeSNiels Sascha Reedijk virtual bool IsDerived() override { return true; }
641e22817dSNiels Sascha Reedijk };
651e22817dSNiels Sascha Reedijk
661e22817dSNiels Sascha Reedijk
ExclusiveBorrowTest()671e22817dSNiels Sascha Reedijk ExclusiveBorrowTest::ExclusiveBorrowTest()
681e22817dSNiels Sascha Reedijk {
691e22817dSNiels Sascha Reedijk }
701e22817dSNiels Sascha Reedijk
711e22817dSNiels Sascha Reedijk
721e22817dSNiels Sascha Reedijk void
ObjectDeleteTest()731e22817dSNiels Sascha Reedijk ExclusiveBorrowTest::ObjectDeleteTest()
741e22817dSNiels Sascha Reedijk {
751e22817dSNiels Sascha Reedijk // Case 1: object never gets borrowed and goes out of scope
761e22817dSNiels Sascha Reedijk std::atomic<bool> deleted = false;
771e22817dSNiels Sascha Reedijk {
781e22817dSNiels Sascha Reedijk auto object = make_exclusive_borrow<DeleteTestHelper>(deleted);
791e22817dSNiels Sascha Reedijk }
801e22817dSNiels Sascha Reedijk CPPUNIT_ASSERT_EQUAL_MESSAGE("(1) Expected object to be deleted", true, deleted.load());
811e22817dSNiels Sascha Reedijk
821e22817dSNiels Sascha Reedijk // Case 2: object gets borrowed, returned and then goes out of scope
831e22817dSNiels Sascha Reedijk deleted.store(false);
841e22817dSNiels Sascha Reedijk {
851e22817dSNiels Sascha Reedijk auto object = make_exclusive_borrow<DeleteTestHelper>(deleted);
861e22817dSNiels Sascha Reedijk {
871e22817dSNiels Sascha Reedijk auto borrow = BBorrow<DeleteTestHelper>(object);
881e22817dSNiels Sascha Reedijk }
891e22817dSNiels Sascha Reedijk CPPUNIT_ASSERT_EQUAL_MESSAGE("(2) Object should not be deleted", false, deleted.load());
901e22817dSNiels Sascha Reedijk }
911e22817dSNiels Sascha Reedijk CPPUNIT_ASSERT_EQUAL_MESSAGE("(2) Expected object to be deleted", true, deleted.load());
921e22817dSNiels Sascha Reedijk
931e22817dSNiels Sascha Reedijk // Case 3: object gets borrowed, forfeited and then borrow goes out of scope
941e22817dSNiels Sascha Reedijk deleted.store(false);
951e22817dSNiels Sascha Reedijk {
961e22817dSNiels Sascha Reedijk auto borrow = BBorrow<DeleteTestHelper>(nullptr);
971e22817dSNiels Sascha Reedijk {
981e22817dSNiels Sascha Reedijk auto object = make_exclusive_borrow<DeleteTestHelper>(deleted);
991e22817dSNiels Sascha Reedijk borrow = BBorrow<DeleteTestHelper>(object);
1001e22817dSNiels Sascha Reedijk }
1011e22817dSNiels Sascha Reedijk CPPUNIT_ASSERT_EQUAL_MESSAGE("(3) Object should not be deleted", false, deleted.load());
1021e22817dSNiels Sascha Reedijk }
1031e22817dSNiels Sascha Reedijk CPPUNIT_ASSERT_EQUAL_MESSAGE("(3) Expected object to be deleted", true, deleted.load());
1041e22817dSNiels Sascha Reedijk }
1051e22817dSNiels Sascha Reedijk
1061e22817dSNiels Sascha Reedijk
1071e22817dSNiels Sascha Reedijk void
OwnershipTest()1081e22817dSNiels Sascha Reedijk ExclusiveBorrowTest::OwnershipTest()
1091e22817dSNiels Sascha Reedijk {
1101e22817dSNiels Sascha Reedijk auto ownedObject = make_exclusive_borrow<int>(1);
1111e22817dSNiels Sascha Reedijk CPPUNIT_ASSERT(*ownedObject == 1);
1121e22817dSNiels Sascha Reedijk
1131e22817dSNiels Sascha Reedijk auto borrow = BBorrow<int>(ownedObject);
1141e22817dSNiels Sascha Reedijk try {
1151e22817dSNiels Sascha Reedijk std::ignore = *ownedObject == 1;
1161e22817dSNiels Sascha Reedijk CPPUNIT_FAIL("Unexpected access to the owned object while borrowed");
1171e22817dSNiels Sascha Reedijk } catch (const BBorrowError& e) {
1181e22817dSNiels Sascha Reedijk // expected
1191e22817dSNiels Sascha Reedijk }
1201e22817dSNiels Sascha Reedijk
1211e22817dSNiels Sascha Reedijk try {
1221e22817dSNiels Sascha Reedijk std::ignore = *borrow == 1;
1231e22817dSNiels Sascha Reedijk // should succeed
1241e22817dSNiels Sascha Reedijk } catch (const BBorrowError& e) {
1251e22817dSNiels Sascha Reedijk CPPUNIT_FAIL("Unexpected error accessing the borrowed object");
1261e22817dSNiels Sascha Reedijk }
1271e22817dSNiels Sascha Reedijk
1281e22817dSNiels Sascha Reedijk try {
1291e22817dSNiels Sascha Reedijk auto borrowAgain = BBorrow<int>(ownedObject);
1301e22817dSNiels Sascha Reedijk CPPUNIT_FAIL("Unexpectedly able to borrow the owned object again");
1311e22817dSNiels Sascha Reedijk } catch (const BBorrowError& e) {
1321e22817dSNiels Sascha Reedijk // expected
1331e22817dSNiels Sascha Reedijk }
1341e22817dSNiels Sascha Reedijk
1351e22817dSNiels Sascha Reedijk try {
1361e22817dSNiels Sascha Reedijk borrow = BBorrow<int>(nullptr);
1371e22817dSNiels Sascha Reedijk std::ignore = *borrow == 1;
1381e22817dSNiels Sascha Reedijk CPPUNIT_FAIL("Unexpected access to an empty borrowed object");
1391e22817dSNiels Sascha Reedijk } catch (const BBorrowError& e) {
1401e22817dSNiels Sascha Reedijk // expected
1411e22817dSNiels Sascha Reedijk }
1421e22817dSNiels Sascha Reedijk
1431e22817dSNiels Sascha Reedijk try {
1441e22817dSNiels Sascha Reedijk std::ignore = *ownedObject == 1;
1451e22817dSNiels Sascha Reedijk } catch (const BBorrowError& e) {
1461e22817dSNiels Sascha Reedijk CPPUNIT_FAIL("Unexpected error accessing the owned object");
1471e22817dSNiels Sascha Reedijk }
1481e22817dSNiels Sascha Reedijk }
1491e22817dSNiels Sascha Reedijk
1501e22817dSNiels Sascha Reedijk
1511e22817dSNiels Sascha Reedijk void
PolymorphismTest()1521e22817dSNiels Sascha Reedijk ExclusiveBorrowTest::PolymorphismTest()
1531e22817dSNiels Sascha Reedijk {
1541e22817dSNiels Sascha Reedijk auto owned = make_exclusive_borrow<Derived>();
1551e22817dSNiels Sascha Reedijk {
1561e22817dSNiels Sascha Reedijk auto borrowDerived = BBorrow<Derived>(owned);
1571e22817dSNiels Sascha Reedijk CPPUNIT_ASSERT_EQUAL(true, borrowDerived->IsDerived());
1581e22817dSNiels Sascha Reedijk }
1591e22817dSNiels Sascha Reedijk {
1601e22817dSNiels Sascha Reedijk auto borrowBase = BBorrow<Base>(owned);
1611e22817dSNiels Sascha Reedijk CPPUNIT_ASSERT_EQUAL(true, borrowBase->IsDerived());
1621e22817dSNiels Sascha Reedijk }
1631e22817dSNiels Sascha Reedijk }
1641e22817dSNiels Sascha Reedijk
1651e22817dSNiels Sascha Reedijk
1661e22817dSNiels Sascha Reedijk void
ReleaseTest()1671e22817dSNiels Sascha Reedijk ExclusiveBorrowTest::ReleaseTest()
1681e22817dSNiels Sascha Reedijk {
1691e22817dSNiels Sascha Reedijk auto ownedObject = make_exclusive_borrow<int>(1);
1701e22817dSNiels Sascha Reedijk auto ownedPointer = std::addressof(*ownedObject);
1711e22817dSNiels Sascha Reedijk try {
1721e22817dSNiels Sascha Reedijk auto borrow = BBorrow<int>(ownedObject);
1731e22817dSNiels Sascha Reedijk auto invalidClaimedPointer = ownedObject.Release();
1741e22817dSNiels Sascha Reedijk CPPUNIT_FAIL("Unexpectedly able to release a borrowed pointer");
1751e22817dSNiels Sascha Reedijk } catch (const BBorrowError&) {
1761e22817dSNiels Sascha Reedijk // expected to fail
1771e22817dSNiels Sascha Reedijk }
1781e22817dSNiels Sascha Reedijk
1791e22817dSNiels Sascha Reedijk auto validClaimedPointer = ownedObject.Release();
1801e22817dSNiels Sascha Reedijk CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected released pointer to point to the same object",
1811e22817dSNiels Sascha Reedijk validClaimedPointer.get(), ownedPointer);
1821e22817dSNiels Sascha Reedijk }
1831e22817dSNiels Sascha Reedijk
1841e22817dSNiels Sascha Reedijk
1851e22817dSNiels Sascha Reedijk /* static */ void
AddTests(BTestSuite & parent)1861e22817dSNiels Sascha Reedijk ExclusiveBorrowTest::AddTests(BTestSuite& parent)
1871e22817dSNiels Sascha Reedijk {
1881e22817dSNiels Sascha Reedijk CppUnit::TestSuite& suite = *new CppUnit::TestSuite("ExclusiveBorrowTest");
1891e22817dSNiels Sascha Reedijk
1901e22817dSNiels Sascha Reedijk suite.addTest(new CppUnit::TestCaller<ExclusiveBorrowTest>(
1911e22817dSNiels Sascha Reedijk "ExclusiveBorrowTest::ObjectDeleteTest", &ExclusiveBorrowTest::ObjectDeleteTest));
1921e22817dSNiels Sascha Reedijk suite.addTest(new CppUnit::TestCaller<ExclusiveBorrowTest>(
1931e22817dSNiels Sascha Reedijk "ExclusiveBorrowTest::OwnershipTest", &ExclusiveBorrowTest::OwnershipTest));
1941e22817dSNiels Sascha Reedijk suite.addTest(new CppUnit::TestCaller<ExclusiveBorrowTest>(
1951e22817dSNiels Sascha Reedijk "ExclusiveBorrowTest::PolymorphismTest", &ExclusiveBorrowTest::PolymorphismTest));
1961e22817dSNiels Sascha Reedijk suite.addTest(new CppUnit::TestCaller<ExclusiveBorrowTest>(
1971e22817dSNiels Sascha Reedijk "ExclusiveBorrowTest::ReleaseTest", &ExclusiveBorrowTest::ReleaseTest));
1981e22817dSNiels Sascha Reedijk
1991e22817dSNiels Sascha Reedijk parent.addTest("ExclusiveBorrowTest", &suite);
2001e22817dSNiels Sascha Reedijk }
201