blob: ae8cae009563bf0942aab8ab53c53236857c25bf [file] [log] [blame]
/* $Id$
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version
* 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <gtest/gtest.h>
#include "capu/os/CondVar.h"
#include "capu/os/Thread.h"
class GlobalVariables
{
public:
static capu::int32_t loops;
static capu::int32_t buffer;
static capu::CondVar cv;
static capu::Mutex mutex;
};
capu::int32_t GlobalVariables::loops = 10000;
capu::CondVar GlobalVariables::cv;
capu::Mutex GlobalVariables::mutex;
capu::int32_t GlobalVariables::buffer = 0;
class ThreadCondVarConsumer : public capu::Runnable
{
public:
void run()
{
for(capu::int32_t i = 0; i < GlobalVariables::loops; i++) {
EXPECT_TRUE(GlobalVariables::mutex.lock()== capu::CAPU_OK);
while(GlobalVariables::buffer == 0) {
EXPECT_TRUE(GlobalVariables::cv.wait(&GlobalVariables::mutex)== capu::CAPU_OK);
}
GlobalVariables::buffer--;
EXPECT_TRUE(GlobalVariables::cv.signal()== capu::CAPU_OK);
EXPECT_TRUE(GlobalVariables::mutex.unlock()== capu::CAPU_OK);
}
}
};
class ThreadCondVarProducerBroadcast : public capu::Runnable
{
public:
void run()
{
for(capu::int32_t i = 0; i < GlobalVariables::loops * 3; i++) {
EXPECT_TRUE(GlobalVariables::mutex.lock()== capu::CAPU_OK);
while(GlobalVariables::buffer == 100) {
EXPECT_TRUE(GlobalVariables::cv.wait(&GlobalVariables::mutex)== capu::CAPU_OK);
}
GlobalVariables::buffer++;
EXPECT_TRUE(GlobalVariables::cv.broadcast()== capu::CAPU_OK);
EXPECT_TRUE(GlobalVariables::mutex.unlock()== capu::CAPU_OK);
}
}
};
class ThreadCondVarProducerSignal : public capu::Runnable
{
public:
void run()
{
for(capu::int32_t i = 0; i < GlobalVariables::loops; i++) {
EXPECT_TRUE(GlobalVariables::mutex.lock()== capu::CAPU_OK);
while(GlobalVariables::buffer == 100) {
EXPECT_EQ(capu::CAPU_OK, GlobalVariables::cv.wait(&GlobalVariables::mutex));
}
GlobalVariables::buffer++;
EXPECT_TRUE(GlobalVariables::cv.signal()== capu::CAPU_OK);
EXPECT_TRUE(GlobalVariables::mutex.unlock()== capu::CAPU_OK);
}
}
};
TEST(CondVar,ConstructorTest)
{
capu::CondVar *_cv = new capu::CondVar();
EXPECT_TRUE(_cv != NULL);
delete _cv;
}
TEST(CondVar,WaitTest)
{
capu::CondVar *_cv = new capu::CondVar();
EXPECT_TRUE(_cv->wait(NULL) == capu::CAPU_EINVAL);
delete _cv;
}
TEST(CondVar,WaitAndBroadcastTest)
{
ThreadCondVarConsumer consumer;
ThreadCondVarProducerBroadcast producer;
//create two thread
capu::Thread * CAPU_thread = new capu::Thread(&consumer);
CAPU_thread->start();
capu::Thread * CAPU_thread2 = new capu::Thread(&consumer);
CAPU_thread2->start();
capu::Thread * CAPU_thread3 = new capu::Thread(&consumer);
CAPU_thread3->start();
capu::Thread * CAPU_thread4 = new capu::Thread(&producer);
CAPU_thread4->start();
//wait for them to finish
CAPU_thread->join();
CAPU_thread2->join();
CAPU_thread3->join();
CAPU_thread4->join();
//expected value
EXPECT_EQ(0, GlobalVariables::buffer);
delete CAPU_thread;
delete CAPU_thread2;
delete CAPU_thread3;
delete CAPU_thread4;
}
TEST(CondVar,WaitAndSignalTest)
{
ThreadCondVarConsumer consumer;
ThreadCondVarProducerSignal producer;
//create two thread
capu::Thread * CAPU_thread = new capu::Thread(&consumer);
CAPU_thread->start();
capu::Thread * CAPU_thread2 = new capu::Thread(&producer);
CAPU_thread2->start();
//wait for them to finish
CAPU_thread->join();
CAPU_thread2->join();
//expected value
EXPECT_EQ(0, GlobalVariables::buffer);
delete CAPU_thread;
delete CAPU_thread2;
}
TEST(CondVar,TimedWaitTest)
{
capu::Mutex mutex;
capu::CondVar condvar;
mutex.lock();
//2 second wait and timeout
EXPECT_TRUE(condvar.wait(&mutex, 2000) == capu::CAPU_ETIMEOUT);
mutex.unlock();
}
//TODO add recursive mutext condvar test