xref: /haiku/src/tests/kits/net/netservices2/ExclusiveBorrowTest.cpp (revision 71e29bbeea760848317843508c711f2a0b446fbb)
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