New upstream version 8.1.0
This commit is contained in:
834
common/tests/TestRWLock.cpp
Normal file
834
common/tests/TestRWLock.cpp
Normal file
@@ -0,0 +1,834 @@
|
||||
#include <common/app/log/LogContext.h>
|
||||
#include <common/threading/RWLock.h>
|
||||
#include <common/toolkit/Random.h>
|
||||
#include <common/toolkit/StringTk.h>
|
||||
#include <common/toolkit/Time.h>
|
||||
|
||||
#include "TestRWLock.h"
|
||||
|
||||
// rwlock tests are disabled by default, probably due to long runtime.
|
||||
#define RWLOCK_TEST(id) TEST_F(TestRWLock, DISABLED_ ## id)
|
||||
|
||||
|
||||
/*
|
||||
* sorts all threads by the lock timestamp, make it easier to verify the execution order
|
||||
*/
|
||||
void TestRWLock::sortThreadsInLockTimestamp(TestLockThread* threads,
|
||||
Time* startTime)
|
||||
{
|
||||
bool changesDone = false;
|
||||
|
||||
do
|
||||
{
|
||||
changesDone = false;
|
||||
|
||||
for (int id = 0; id < (TestRWLock_THREAD_COUNT -1); id++)
|
||||
{
|
||||
int elapsedTimeID = threads[id].getLockTimestamp().
|
||||
elapsedSinceMS(startTime);
|
||||
int elapsedTimeNextID = threads[id + 1].getLockTimestamp().
|
||||
elapsedSinceMS(startTime);
|
||||
|
||||
if (elapsedTimeID > elapsedTimeNextID)
|
||||
{
|
||||
TestLockThread tmpTestLockThread;
|
||||
tmpTestLockThread.copy(&threads[id]);
|
||||
threads[id].copy(&threads[id + 1]);
|
||||
threads[id + 1 ].copy(&tmpTestLockThread);
|
||||
changesDone = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (changesDone);
|
||||
}
|
||||
|
||||
/*
|
||||
* analyze the run time for random thread execution, if the run time was long enough
|
||||
*/
|
||||
void TestRWLock::checkRandomRuntime(TestLockThread* threads, int runtimeMS)
|
||||
{
|
||||
int minimalRuntimeMS = 0;
|
||||
int longestSleepMS = 0;
|
||||
|
||||
for (int id = 0; id < TestRWLock_THREAD_COUNT; id++)
|
||||
{
|
||||
// ignore threads which didn't get a lock
|
||||
if (!threads[id].getLockSuccess())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (threads[id].getDoReadLock())
|
||||
{ // reader thread, find the longest sleep time
|
||||
for (int nextId = id + 1; nextId < TestRWLock_THREAD_COUNT; nextId++)
|
||||
{
|
||||
// check all reader threads which was executed at the same time
|
||||
if(threads[nextId].getDoReadLock())
|
||||
{ // next thread was a reader, find the longest sleep time
|
||||
if (threads[nextId].getLockSuccess() &&
|
||||
(longestSleepMS < threads[nextId].getSleepTimeMS()))
|
||||
{
|
||||
longestSleepMS = threads[nextId].getSleepTimeMS();
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // next thread was a writer, stop searching of longest sleep time
|
||||
id = nextId - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
minimalRuntimeMS = minimalRuntimeMS + longestSleepMS;
|
||||
}
|
||||
else
|
||||
{ // writer thread, add the the sleep time
|
||||
minimalRuntimeMS = minimalRuntimeMS + threads[id].getSleepTimeMS();
|
||||
}
|
||||
}
|
||||
|
||||
// check if the sleep time is bigger then the runtime
|
||||
if (minimalRuntimeMS > runtimeMS)
|
||||
{
|
||||
FAIL() << "Runtime is to short. A lock didn't work.";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* analyze the execution order for random thread execution
|
||||
*/
|
||||
void TestRWLock::checkRandomExecutionOrder(TestLockThread* threads)
|
||||
{
|
||||
for (int id = 1; id < (TestRWLock_THREAD_COUNT); id++)
|
||||
{
|
||||
// ignore threads which didn't get a lock
|
||||
if(!threads[id].getLockSuccess())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if the unlock was successful
|
||||
if(!threads[id].getUnlockSuccess())
|
||||
{
|
||||
FAIL() << "Test thread didn't unlock the lock.";
|
||||
}
|
||||
|
||||
// check the execution order
|
||||
if(threads[id].getDoReadLock())
|
||||
{
|
||||
checkRandomExecutionOrderReader(threads, id);
|
||||
}
|
||||
else
|
||||
{
|
||||
checkRandomExecutionOrderWriter(threads, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* analyze the execution order for random thread execution for a reader thread
|
||||
*/
|
||||
void TestRWLock::checkRandomExecutionOrderReader(TestLockThread* threads, int threadID)
|
||||
{
|
||||
for (int beforeId = threadID - 1; beforeId >= 0; beforeId--)
|
||||
{
|
||||
if(threads[beforeId].getLockSuccess())
|
||||
{
|
||||
Time unlockTimeBefore = threads[beforeId].getUnlockTimestamp();
|
||||
Time lockTime = threads[threadID].getLockTimestamp();
|
||||
|
||||
// check if the thread before was a writer and check if the thread before has unlocked
|
||||
// the rwlock before this reader thread locks the rwlock
|
||||
// if the thread before was a reader it is OK to get the lock without a unlock
|
||||
if((!threads[beforeId].getDoReadLock()) && (unlockTimeBefore > lockTime))
|
||||
{
|
||||
std::cerr << "execution order failed, time diff in micro sec: " << StringTk::uintToStr(
|
||||
unlockTimeBefore.elapsedSinceMicro(&lockTime)) << std::endl;
|
||||
FAIL() << "Test thread got the lock, but it wasn't possible to get the lock.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* analyze the execution order for random thread execution for a writer thread
|
||||
*/
|
||||
void TestRWLock::checkRandomExecutionOrderWriter(TestLockThread* threads, int threadID)
|
||||
{
|
||||
for (int beforeId = threadID - 1; beforeId >= 0; beforeId--)
|
||||
{
|
||||
if(threads[beforeId].getLockSuccess())
|
||||
{
|
||||
Time unlockTimeBefore = threads[beforeId].getUnlockTimestamp();
|
||||
Time lockTime = threads[threadID].getLockTimestamp();
|
||||
|
||||
// check if the thread before has unlocked the rwlock before this writer thread locks
|
||||
// the rwlock
|
||||
if(unlockTimeBefore > lockTime)
|
||||
{
|
||||
std::cerr << "execution order failed, time diff in micro sec: " << StringTk::uintToStr(
|
||||
unlockTimeBefore.elapsedSinceMicro(&lockTime)) << std::endl;
|
||||
FAIL() << "Test thread got the lock, but it wasn't possible to get the lock.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* tests a reader thread on a read lock, checks the basic functions of a rwlock
|
||||
*/
|
||||
RWLOCK_TEST(readerOnReader)
|
||||
{
|
||||
// creates a read lock
|
||||
RWLock lock;
|
||||
lock.readLock();
|
||||
|
||||
Time startTime;
|
||||
|
||||
// creates a read lock
|
||||
TestLockThread thread(&lock, true, false);
|
||||
thread.start();
|
||||
|
||||
// wait a few second before unlock the lock
|
||||
PThread::sleepMS(TestRWLock_SLEEP_TIME_MS);
|
||||
|
||||
lock.unlock();
|
||||
|
||||
// wait for timeout
|
||||
bool notTimedOut = thread.timedjoin(TestRWLock_SINGLE_TIMEOUT_MS);
|
||||
int runtime = startTime.elapsedMS();
|
||||
|
||||
if (!notTimedOut)
|
||||
{
|
||||
FAIL() << "Test ran into a timeout. Maybe a dead-lock";
|
||||
}
|
||||
|
||||
if (!thread.getLockSuccess())
|
||||
{
|
||||
FAIL() << "The test thread didn't get the lock, but it was possible to get the lock.";
|
||||
}
|
||||
|
||||
if (!thread.getUnlockSuccess())
|
||||
{
|
||||
FAIL() << "The test thread didn't unlock the lock.";
|
||||
}
|
||||
|
||||
if (TestRWLock_SLEEP_TIME_MS > runtime)
|
||||
{
|
||||
FAIL() << "Runtime is to short. A lock didn't work.";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* tests a reader thread on a write lock, checks the basic functions of a rwlock
|
||||
*/
|
||||
RWLOCK_TEST(readerOnWriter)
|
||||
{
|
||||
// creates a write lock
|
||||
RWLock lock;
|
||||
lock.writeLock();
|
||||
|
||||
Time startTime;
|
||||
|
||||
// creates a read lock
|
||||
TestLockThread thread(&lock, true, false);
|
||||
thread.start();
|
||||
|
||||
// wait a few second before unlock the lock
|
||||
PThread::sleepMS(TestRWLock_SLEEP_TIME_MS);
|
||||
|
||||
lock.unlock();
|
||||
|
||||
// wait for timeout
|
||||
bool notTimedOut = thread.timedjoin(2 * TestRWLock_SINGLE_TIMEOUT_MS);
|
||||
int runtime = startTime.elapsedMS();
|
||||
|
||||
if (!notTimedOut)
|
||||
{
|
||||
FAIL() << "Test ran into a timeout. Maybe a dead-lock";
|
||||
}
|
||||
|
||||
if (!thread.getLockSuccess())
|
||||
{
|
||||
FAIL() << "The test thread didn't get the lock, but it was possible to get the lock.";
|
||||
}
|
||||
|
||||
if (!thread.getUnlockSuccess())
|
||||
{
|
||||
FAIL() << "The test thread didn't unlock the lock.";
|
||||
}
|
||||
|
||||
if ((TestRWLock_SLEEP_TIME_MS * 2) > runtime)
|
||||
{
|
||||
FAIL() << "Runtime is to short. A lock didn't work.";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* tests a writer thread on a read lock, checks the basic functions of a rwlock
|
||||
*/
|
||||
RWLOCK_TEST(writerOnReader)
|
||||
{
|
||||
// creates a read lock
|
||||
RWLock lock;
|
||||
lock.readLock();
|
||||
|
||||
Time startTime;
|
||||
|
||||
// creates a write lock
|
||||
TestLockThread thread(&lock, false, false);
|
||||
thread.start();
|
||||
|
||||
// wait a few second before unlock the lock
|
||||
PThread::sleepMS(TestRWLock_SLEEP_TIME_MS);
|
||||
|
||||
lock.unlock();
|
||||
|
||||
// wait for timeout
|
||||
bool notTimedOut = thread.timedjoin(2 * TestRWLock_SINGLE_TIMEOUT_MS);
|
||||
int runtime = startTime.elapsedMS();
|
||||
|
||||
if (!notTimedOut)
|
||||
{
|
||||
FAIL() << "Test ran into a timeout. Maybe a dead-lock";
|
||||
}
|
||||
|
||||
if (!thread.getLockSuccess())
|
||||
{
|
||||
FAIL() << "The test thread didn't get the lock, but it was possible to get the lock.";
|
||||
}
|
||||
|
||||
if (!thread.getUnlockSuccess())
|
||||
{
|
||||
FAIL() << "The test thread didn't unlock the lock.";
|
||||
}
|
||||
|
||||
if ((TestRWLock_SLEEP_TIME_MS * 2) > runtime)
|
||||
{
|
||||
FAIL() << "Runtime is to short. A lock didn't work.";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* tests a writer thread on a write lock, checks the basic functions of a rwlock
|
||||
*/
|
||||
RWLOCK_TEST(writerOnWriter)
|
||||
{
|
||||
// creates a write lock
|
||||
RWLock lock;
|
||||
lock.writeLock();
|
||||
|
||||
Time startTime;
|
||||
|
||||
// creates a write lock
|
||||
TestLockThread thread(&lock, false, false);
|
||||
thread.start();
|
||||
|
||||
// wait a few second before unlock the lock
|
||||
PThread::sleepMS(TestRWLock_SLEEP_TIME_MS);
|
||||
|
||||
lock.unlock();
|
||||
|
||||
// wait for timeout
|
||||
bool notTimedOut = thread.timedjoin(2 * TestRWLock_SINGLE_TIMEOUT_MS);
|
||||
int runtime = startTime.elapsedMS();
|
||||
|
||||
if (!notTimedOut)
|
||||
{
|
||||
FAIL() << "Test ran into a timeout. Maybe a dead-lock";
|
||||
}
|
||||
|
||||
if (!thread.getLockSuccess())
|
||||
{
|
||||
FAIL() << "The test thread didn't get the lock, but it was possible to get the lock.";
|
||||
}
|
||||
|
||||
if (!thread.getUnlockSuccess())
|
||||
{
|
||||
FAIL() << "The test thread didn't unlock the lock.";
|
||||
}
|
||||
|
||||
if ((TestRWLock_SLEEP_TIME_MS * 2) > runtime)
|
||||
{
|
||||
FAIL() << "Runtime is to short. A lock didn't work.";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* tests reader threads and writer thread on a read lock, checks massive amount of lock operations
|
||||
*/
|
||||
RWLOCK_TEST(randomOnReader)
|
||||
{
|
||||
RWLock lock;
|
||||
Random randomizer;
|
||||
TestLockThread threadList[TestRWLock_THREAD_COUNT];
|
||||
|
||||
int id = 0;
|
||||
|
||||
threadList[0].init(&lock, true, false, TestRWLock_SLEEP_TIME_MS, 1);
|
||||
|
||||
// create all threads for the test
|
||||
for (id = 1; id < TestRWLock_THREAD_COUNT; id++)
|
||||
{
|
||||
bool tmpDoReadLock;
|
||||
|
||||
// random initialization: is reader or writer
|
||||
tmpDoReadLock = randomizer.getNextInRange(0, 1) == 1;
|
||||
|
||||
// random initialization: sleep time
|
||||
int tmpSleepTimeMS = randomizer.getNextInRange(
|
||||
TestRWLock_RANDOM_SLEEP_TIME_MIN_MS,
|
||||
TestRWLock_RANDOM_SLEEP_TIME_MAX_MS);
|
||||
|
||||
// random initialization: start delay time
|
||||
int tmpLockDelayMS = randomizer.getNextInRange(
|
||||
TestRWLock_RANDOM_LOCK_DELAY_MIN_MS,
|
||||
TestRWLock_RANDOM_LOCK_DELAY_MAX_MS);
|
||||
|
||||
threadList[id].init(&lock, tmpDoReadLock, false, tmpSleepTimeMS, tmpLockDelayMS);
|
||||
}
|
||||
|
||||
Time startTime;
|
||||
|
||||
// start all threads
|
||||
threadList[0].start();
|
||||
for (id = 1; id < TestRWLock_THREAD_COUNT; id++)
|
||||
{
|
||||
threadList[id].start();
|
||||
}
|
||||
|
||||
bool notTimedOut = true;
|
||||
Time startTimeout;
|
||||
|
||||
// collect all threads and check timeout
|
||||
for (id = 0; id < TestRWLock_THREAD_COUNT; id++)
|
||||
{
|
||||
int nextTimeout = TestRWLock_MULTI_TIMEOUT_MS - startTimeout.elapsedMS();
|
||||
if (nextTimeout < 500)
|
||||
{
|
||||
nextTimeout = 500;
|
||||
}
|
||||
|
||||
if (!threadList[id].timedjoin(nextTimeout))
|
||||
{
|
||||
notTimedOut = false;
|
||||
}
|
||||
}
|
||||
|
||||
int runtimeMS = startTime.elapsedMS();
|
||||
|
||||
// check the constraints
|
||||
if (!notTimedOut)
|
||||
{
|
||||
FAIL() << "Test ran into a timeout. Maybe a dead-lock";
|
||||
}
|
||||
|
||||
sortThreadsInLockTimestamp(threadList, &startTime);
|
||||
checkRandomExecutionOrder(threadList);
|
||||
checkRandomRuntime(threadList, runtimeMS);
|
||||
}
|
||||
|
||||
/*
|
||||
* tests reader threads and writer thread on a write lock, checks massive amount of lock operations
|
||||
*/
|
||||
RWLOCK_TEST(randomOnWriter)
|
||||
{
|
||||
RWLock lock;
|
||||
Random randomizer;
|
||||
TestLockThread threadList[TestRWLock_THREAD_COUNT];
|
||||
|
||||
int id = 0;
|
||||
|
||||
threadList[0].init(&lock, false, false, 5000, 1);
|
||||
|
||||
// create all threads for the test
|
||||
for (id = 1; id < TestRWLock_THREAD_COUNT; id++)
|
||||
{
|
||||
bool tmpDoReadLock;
|
||||
|
||||
// random initialization: is reader or writer
|
||||
tmpDoReadLock = randomizer.getNextInRange(0, 1) == 1;
|
||||
|
||||
// random initialization: sleep time
|
||||
int tmpSleepTimeMS = randomizer.getNextInRange(
|
||||
TestRWLock_RANDOM_SLEEP_TIME_MIN_MS,
|
||||
TestRWLock_RANDOM_SLEEP_TIME_MAX_MS);
|
||||
|
||||
// random initialization: start delay time
|
||||
int tmpLockDelayMS = randomizer.getNextInRange(
|
||||
TestRWLock_RANDOM_LOCK_DELAY_MIN_MS,
|
||||
TestRWLock_RANDOM_LOCK_DELAY_MAX_MS);
|
||||
|
||||
threadList[id].init(&lock, tmpDoReadLock, false, tmpSleepTimeMS, tmpLockDelayMS);
|
||||
}
|
||||
|
||||
Time startTime;
|
||||
|
||||
// start all threads
|
||||
threadList[0].start();
|
||||
for (id = 1; id < TestRWLock_THREAD_COUNT; id++)
|
||||
{
|
||||
threadList[id].start();
|
||||
}
|
||||
|
||||
bool notTimedOut = true;
|
||||
Time startTimeout;
|
||||
|
||||
// collect all threads and check timeout
|
||||
for (id = 0; id < TestRWLock_THREAD_COUNT; id++)
|
||||
{
|
||||
int nextTimeout = TestRWLock_MULTI_TIMEOUT_MS - startTimeout.elapsedMS();
|
||||
if (nextTimeout < 500)
|
||||
{
|
||||
nextTimeout = 500;
|
||||
}
|
||||
|
||||
if (!threadList[id].timedjoin(nextTimeout))
|
||||
{
|
||||
notTimedOut = false;
|
||||
}
|
||||
}
|
||||
|
||||
int runtimeMS = startTime.elapsedMS();
|
||||
|
||||
// check the constraints
|
||||
if (!notTimedOut)
|
||||
{
|
||||
FAIL() << "Test ran into a timeout. Maybe a dead-lock";
|
||||
}
|
||||
|
||||
sortThreadsInLockTimestamp(threadList, &startTime);
|
||||
checkRandomExecutionOrder(threadList);
|
||||
checkRandomRuntime(threadList, runtimeMS);
|
||||
}
|
||||
|
||||
/*
|
||||
* tests a tryReadLock on a read lock, checks the basic functions of a rwlock
|
||||
*/
|
||||
RWLOCK_TEST(tryReadOnReader)
|
||||
{
|
||||
// creates a read lock with try method
|
||||
RWLock lock;
|
||||
|
||||
bool success = lock.tryReadLock();
|
||||
if (!success)
|
||||
{
|
||||
FAIL() << "Couldn't get initial lock.";
|
||||
}
|
||||
|
||||
Time startTime;
|
||||
|
||||
// creates a read lock with try method
|
||||
TestLockThread thread(&lock, true, true);
|
||||
thread.start();
|
||||
|
||||
// wait a few second before unlock the lock
|
||||
PThread::sleepMS(TestRWLock_SLEEP_TIME_MS);
|
||||
|
||||
lock.unlock();
|
||||
|
||||
// wait for timeout
|
||||
bool notTimedOut = thread.timedjoin(TestRWLock_SINGLE_TIMEOUT_MS);
|
||||
int runtime = startTime.elapsedMS();
|
||||
|
||||
if (!notTimedOut)
|
||||
{
|
||||
FAIL() << "Test ran into a timeout. Maybe a dead-lock";
|
||||
}
|
||||
|
||||
if (!thread.getLockSuccess())
|
||||
{
|
||||
FAIL() << "The test thread didn't get the lock, but it was possible to get the lock.";
|
||||
}
|
||||
|
||||
if (!thread.getUnlockSuccess())
|
||||
{
|
||||
FAIL() << "The test thread didn't unlock the lock.";
|
||||
}
|
||||
|
||||
if (TestRWLock_SLEEP_TIME_MS > runtime)
|
||||
{
|
||||
FAIL() << "Runtime is to short. A lock didn't work.";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* tests a tryReadLock on a write lock, checks the basic functions of a rwlock
|
||||
*/
|
||||
RWLOCK_TEST(tryReadOnWriter)
|
||||
{
|
||||
// creates a write lock with try method
|
||||
RWLock lock;
|
||||
|
||||
bool success = lock.tryWriteLock();
|
||||
if (!success)
|
||||
{
|
||||
FAIL() << "Couldn't get initial lock.";
|
||||
}
|
||||
|
||||
Time startTime;
|
||||
|
||||
// creates a read lock with try method
|
||||
TestLockThread thread(&lock, true, true);
|
||||
thread.start();
|
||||
|
||||
// wait a few second before unlock the lock
|
||||
PThread::sleepMS(TestRWLock_SLEEP_TIME_MS);
|
||||
|
||||
lock.unlock();
|
||||
|
||||
// wait for timeout
|
||||
bool notTimedOut = thread.timedjoin(2 * TestRWLock_SINGLE_TIMEOUT_MS);
|
||||
int runtime = startTime.elapsedMS();
|
||||
|
||||
if (!notTimedOut)
|
||||
{
|
||||
FAIL() << "Test ran into a timeout. Maybe a dead-lock";
|
||||
}
|
||||
|
||||
if (thread.getLockSuccess())
|
||||
{
|
||||
FAIL() << "The test thread got the lock, but it wasn't possible to get the lock.";
|
||||
}
|
||||
|
||||
if ((TestRWLock_SLEEP_TIME_MS) > runtime)
|
||||
{
|
||||
FAIL() << "Runtime is to short. A lock didn't work.";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* tests a tryWriteLock on a read lock, checks the basic functions of a rwlock
|
||||
*/
|
||||
RWLOCK_TEST(tryWriteOnReader)
|
||||
{
|
||||
// creates a read lock with try method
|
||||
RWLock lock;
|
||||
|
||||
bool success = lock.tryReadLock();
|
||||
if (!success)
|
||||
{
|
||||
FAIL() << "Couldn't get initial lock.";
|
||||
}
|
||||
|
||||
Time startTime;
|
||||
|
||||
// creates a write lock with try method
|
||||
TestLockThread thread(&lock, false, true);
|
||||
thread.start();
|
||||
|
||||
// wait a few second before unlock the lock
|
||||
PThread::sleepMS(TestRWLock_SLEEP_TIME_MS);
|
||||
|
||||
lock.unlock();
|
||||
|
||||
// wait for timeout
|
||||
bool notTimedOut = thread.timedjoin(2 * TestRWLock_SINGLE_TIMEOUT_MS);
|
||||
int runtime = startTime.elapsedMS();
|
||||
|
||||
if (!notTimedOut)
|
||||
{
|
||||
FAIL() << "Test ran into a timeout. Maybe a dead-lock";
|
||||
}
|
||||
|
||||
if (thread.getLockSuccess())
|
||||
{
|
||||
FAIL() << "The test thread got the lock, but it wasn't possible to get the lock.";
|
||||
}
|
||||
|
||||
if ((TestRWLock_SLEEP_TIME_MS) > runtime)
|
||||
{
|
||||
FAIL() << "Runtime is to short. A lock didn't work.";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* tests a tryWriteLock on a write lock, checks the basic functions of a rwlock
|
||||
*/
|
||||
RWLOCK_TEST(tryWriteOnWriter)
|
||||
{
|
||||
// creates a write lock with try method
|
||||
RWLock lock;
|
||||
|
||||
bool success = lock.tryWriteLock();
|
||||
if (!success)
|
||||
{
|
||||
FAIL() << "Couldn't get initial lock.";
|
||||
}
|
||||
|
||||
Time startTime;
|
||||
|
||||
// creates a write lock with try method
|
||||
TestLockThread thread(&lock, false, true);
|
||||
thread.start();
|
||||
|
||||
// wait a few second before unlock the lock
|
||||
PThread::sleepMS(TestRWLock_SLEEP_TIME_MS);
|
||||
|
||||
lock.unlock();
|
||||
|
||||
// wait for timeout
|
||||
bool notTimedOut = thread.timedjoin(2 * TestRWLock_SINGLE_TIMEOUT_MS);
|
||||
int runtime = startTime.elapsedMS();
|
||||
|
||||
if (!notTimedOut)
|
||||
{
|
||||
FAIL() << "Test ran into a timeout. Maybe a dead-lock";
|
||||
}
|
||||
|
||||
if (thread.getLockSuccess())
|
||||
{
|
||||
FAIL() << "The test thread got the lock, but it wasn't possible to get the lock.";
|
||||
}
|
||||
|
||||
if ((TestRWLock_SLEEP_TIME_MS) > runtime)
|
||||
{
|
||||
FAIL() << "Runtime is to short. A lock didn't work.";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* tests tryReadLock and tryWriteLock on a read lock, checks massive amount of lock operations
|
||||
*/
|
||||
RWLOCK_TEST(randomTryOnReader)
|
||||
{
|
||||
RWLock lock;
|
||||
Random randomizer;
|
||||
TestLockThread threadList[TestRWLock_THREAD_COUNT];
|
||||
|
||||
int id = 0;
|
||||
|
||||
threadList[0].init(&lock, true, true, 5000, 1);
|
||||
|
||||
// create all threads for the test
|
||||
for (id = 1; id < TestRWLock_THREAD_COUNT; id++)
|
||||
{
|
||||
bool tmpDoReadLock;
|
||||
|
||||
// random initialization: is reader or writer
|
||||
tmpDoReadLock = randomizer.getNextInRange(0, 1) == 1;
|
||||
|
||||
// random initialization: sleep time
|
||||
int tmpSleepTimeMS = randomizer.getNextInRange(
|
||||
TestRWLock_RANDOM_SLEEP_TIME_MIN_MS,
|
||||
TestRWLock_RANDOM_SLEEP_TIME_MAX_MS);
|
||||
|
||||
// random initialization: start delay time
|
||||
int tmpLockDelayMS = randomizer.getNextInRange(
|
||||
TestRWLock_RANDOM_LOCK_DELAY_MIN_MS,
|
||||
TestRWLock_RANDOM_LOCK_DELAY_MAX_MS);
|
||||
|
||||
threadList[id].init(&lock, tmpDoReadLock, true, tmpSleepTimeMS, tmpLockDelayMS);
|
||||
}
|
||||
|
||||
Time startTime;
|
||||
|
||||
// start all threads
|
||||
threadList[0].start();
|
||||
for (id = 1; id < TestRWLock_THREAD_COUNT; id++)
|
||||
{
|
||||
threadList[id].start();
|
||||
}
|
||||
|
||||
bool notTimedOut = true;
|
||||
Time startTimeout;
|
||||
|
||||
// collect all threads and check timeout
|
||||
for (id = 0; id < TestRWLock_THREAD_COUNT; id++)
|
||||
{
|
||||
int nextTimeout = TestRWLock_MULTI_TIMEOUT_MS - startTimeout.elapsedMS();
|
||||
if (nextTimeout < 500)
|
||||
{
|
||||
nextTimeout = 500;
|
||||
}
|
||||
|
||||
if (!threadList[id].timedjoin(nextTimeout))
|
||||
{
|
||||
notTimedOut = false;
|
||||
}
|
||||
}
|
||||
|
||||
int runtimeMS = startTime.elapsedMS();
|
||||
|
||||
// check the constraints
|
||||
if (!notTimedOut)
|
||||
{
|
||||
FAIL() << "Test ran into a timeout. Maybe a dead-lock";
|
||||
}
|
||||
|
||||
sortThreadsInLockTimestamp(threadList, &startTime);
|
||||
checkRandomExecutionOrder(threadList);
|
||||
checkRandomRuntime(threadList, runtimeMS);
|
||||
}
|
||||
|
||||
/*
|
||||
* tests tryReadLock and tryWriteLock on a write lock, checks massive amount of lock operations
|
||||
*/
|
||||
RWLOCK_TEST(randomTryOnWriter)
|
||||
{
|
||||
RWLock lock;
|
||||
Random randomizer;
|
||||
TestLockThread threadList[TestRWLock_THREAD_COUNT];
|
||||
|
||||
int id = 0;
|
||||
|
||||
threadList[0].init(&lock, false, true, 5000, 1);
|
||||
|
||||
// create all threads for the test
|
||||
for (id = 1; id < TestRWLock_THREAD_COUNT; id++)
|
||||
{
|
||||
bool tmpDoReadLock;
|
||||
|
||||
// random initialization: is reader or writer
|
||||
tmpDoReadLock = randomizer.getNextInRange(0, 1) == 1;
|
||||
|
||||
// random initialization: sleep time
|
||||
int tmpSleepTimeMS = randomizer.getNextInRange(
|
||||
TestRWLock_RANDOM_SLEEP_TIME_MIN_MS,
|
||||
TestRWLock_RANDOM_SLEEP_TIME_MAX_MS);
|
||||
|
||||
// random initialization: start delay time
|
||||
int tmpLockDelayMS = randomizer.getNextInRange(
|
||||
TestRWLock_RANDOM_LOCK_DELAY_MIN_MS,
|
||||
TestRWLock_RANDOM_LOCK_DELAY_MAX_MS);
|
||||
|
||||
threadList[id].init(&lock, tmpDoReadLock, true, tmpSleepTimeMS, tmpLockDelayMS);
|
||||
}
|
||||
|
||||
Time startTime;
|
||||
|
||||
// start all threads
|
||||
threadList[0].start();
|
||||
for (id = 1; id < TestRWLock_THREAD_COUNT; id++)
|
||||
{
|
||||
threadList[id].start();
|
||||
}
|
||||
|
||||
bool notTimedOut = true;
|
||||
Time startTimeout;
|
||||
|
||||
// collect all threads and check timeout
|
||||
for (id = 0; id < TestRWLock_THREAD_COUNT; id++)
|
||||
{
|
||||
int nextTimeout = TestRWLock_MULTI_TIMEOUT_MS - startTimeout.elapsedMS();
|
||||
if (nextTimeout < 500)
|
||||
{
|
||||
nextTimeout = 500;
|
||||
}
|
||||
|
||||
if (!threadList[id].timedjoin(nextTimeout))
|
||||
{
|
||||
notTimedOut = false;
|
||||
}
|
||||
}
|
||||
|
||||
int runtimeMS = startTime.elapsedMS();
|
||||
|
||||
// check the constraints
|
||||
if (!notTimedOut)
|
||||
{
|
||||
FAIL() << "Test ran into a timeout. Maybe a dead-lock";
|
||||
}
|
||||
|
||||
sortThreadsInLockTimestamp(threadList, &startTime);
|
||||
checkRandomExecutionOrder(threadList);
|
||||
checkRandomRuntime(threadList, runtimeMS);
|
||||
}
|
||||
Reference in New Issue
Block a user