#include <Locker.h>
#include <TestSuiteAddon.h>
#include <ThreadedTestCaller.h>
#include <cppunit/TestSuite.h>
#include <cppunit/extensions/HelperMacros.h>
#include <string.h>
static const bigtime_t SNOOZE_TIME = 100000;
class SafetyLock {
public:
SafetyLock(BLocker* lock) : fLocker(lock) {}
~SafetyLock() { if (fLocker != NULL) fLocker->Unlock(); }
private:
BLocker* fLocker;
};
class LockerLockCountTest : public BThreadedTestCase {
public:
LockerLockCountTest(std::string name, bool isBenaphore);
virtual ~LockerLockCountTest();
void TestThread1();
void TestThread2();
void TestThread3();
static CppUnit::Test* suite();
private:
bool CheckLockRequests(int expected);
BLocker* fLocker;
BLocker fThread2Lock;
BLocker fThread3Lock;
bool fIsBenaphore;
};
LockerLockCountTest::LockerLockCountTest(std::string name, bool isBenaphore)
:
BThreadedTestCase(name),
fLocker(new BLocker(isBenaphore)),
fThread2Lock("thread2Lock"),
fThread3Lock("thread3Lock"),
fIsBenaphore(isBenaphore)
{
}
LockerLockCountTest::~LockerLockCountTest()
{
delete fLocker;
}
bool
LockerLockCountTest::CheckLockRequests(int expected)
{
return fLocker->CountLockRequests() == expected;
}
void
LockerLockCountTest::TestThread1()
{
SafetyLock theSafetyLock1(fLocker);
SafetyLock theSafetyLock2(&fThread2Lock);
SafetyLock theSafetyLock3(&fThread3Lock);
CPPUNIT_ASSERT(fThread2Lock.Lock());
CPPUNIT_ASSERT(fThread3Lock.Lock());
CPPUNIT_ASSERT(CheckLockRequests(fIsBenaphore ? 0 : 1));
CPPUNIT_ASSERT(fLocker->Lock());
CPPUNIT_ASSERT(CheckLockRequests(fIsBenaphore ? 1 : 2));
fThread2Lock.Unlock();
snooze(SNOOZE_TIME);
CPPUNIT_ASSERT(CheckLockRequests(fIsBenaphore ? 3 : 4));
fThread3Lock.Unlock();
snooze(SNOOZE_TIME);
CPPUNIT_ASSERT(CheckLockRequests(fIsBenaphore ? 5 : 6));
fLocker->Unlock();
snooze(SNOOZE_TIME);
CPPUNIT_ASSERT(CheckLockRequests(fIsBenaphore ? 2 : 3));
}
void
LockerLockCountTest::TestThread2()
{
SafetyLock theSafetyLock1(fLocker);
snooze(SNOOZE_TIME / 10);
CPPUNIT_ASSERT(fThread2Lock.Lock());
CPPUNIT_ASSERT(fLocker->LockWithTimeout(SNOOZE_TIME / 10) == B_TIMED_OUT);
CPPUNIT_ASSERT(fLocker->Lock());
int actual = fLocker->CountLockRequests();
if (fIsBenaphore)
CPPUNIT_ASSERT(actual == 3 || actual == 4);
else
CPPUNIT_ASSERT(actual == 4 || actual == 5);
fLocker->Unlock();
}
void
LockerLockCountTest::TestThread3()
{
SafetyLock theSafetyLock1(fLocker);
snooze(SNOOZE_TIME / 10);
CPPUNIT_ASSERT(fThread3Lock.Lock());
CPPUNIT_ASSERT(fLocker->LockWithTimeout(SNOOZE_TIME / 10) == B_TIMED_OUT);
CPPUNIT_ASSERT(fLocker->Lock());
int actual = fLocker->CountLockRequests();
if (fIsBenaphore)
CPPUNIT_ASSERT(actual == 3 || actual == 4);
else
CPPUNIT_ASSERT(actual == 4 || actual == 5);
fLocker->Unlock();
}
CppUnit::Test*
LockerLockCountTest::suite()
{
typedef BThreadedTestCaller<LockerLockCountTest> LockerLockCountTestCaller;
CppUnit::TestSuite* testSuite = new CppUnit::TestSuite("LockerLockCountTest");
LockerLockCountTest* benaphoreTest = new LockerLockCountTest("Benaphore", true);
LockerLockCountTestCaller* caller1
= new LockerLockCountTestCaller("BLocker::Benaphore Lock Count Test", benaphoreTest);
caller1->addThread("A", &LockerLockCountTest::TestThread1);
caller1->addThread("B", &LockerLockCountTest::TestThread2);
caller1->addThread("C", &LockerLockCountTest::TestThread3);
testSuite->addTest(caller1);
LockerLockCountTest* semaphoreTest = new LockerLockCountTest("Semaphore", false);
LockerLockCountTestCaller* caller2
= new LockerLockCountTestCaller("BLocker::Semaphore Lock Count Test", semaphoreTest);
caller2->addThread("A", &LockerLockCountTest::TestThread1);
caller2->addThread("B", &LockerLockCountTest::TestThread2);
caller2->addThread("C", &LockerLockCountTest::TestThread3);
testSuite->addTest(caller2);
return testSuite;
}
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(LockerLockCountTest, getTestSuiteName());