diff --git a/base/base_tests/base_tests.pro b/base/base_tests/base_tests.pro index 305bd49355..25cb544cb3 100644 --- a/base/base_tests/base_tests.pro +++ b/base/base_tests/base_tests.pro @@ -37,6 +37,7 @@ SOURCES += \ string_format_test.cpp \ regexp_test.cpp \ scheduled_task_test.cpp \ + thread_pool_tests.cpp HEADERS += diff --git a/base/base_tests/thread_pool_tests.cpp b/base/base_tests/thread_pool_tests.cpp new file mode 100644 index 0000000000..d42e3b00ea --- /dev/null +++ b/base/base_tests/thread_pool_tests.cpp @@ -0,0 +1,122 @@ +#include "../../testing/testing.hpp" + +#include "../mutex.hpp" +#include "../thread.hpp" +#include "../thread_pool.hpp" +#include "../condition.hpp" + +#include "../../std/vector.hpp" +#include "../../std/bind.hpp" + +namespace +{ + threads::Mutex g_mutex; + const int TASK_COUNT = 10; + class CanceledTask : public threads::IRoutine + { + public: + CanceledTask() + { + Cancel(); + } + + virtual void Do() + { + TEST_EQUAL(true, false, ()); + } + }; + + void JoinFinishFunction(threads::IRoutine * routine, + int & finishCounter, + threads::Condition & cond) + { + cond.Lock(); + finishCounter++; + cond.Unlock(); + + delete routine; + cond.Signal(); + } +} + +UNIT_TEST(ThreadPool_CanceledTaskTest) +{ + int finishCounter = 0; + threads::Condition cond; + threads::ThreadPool pool(4, bind(&JoinFinishFunction, _1, ref(finishCounter), ref(cond))); + + for (int i = 0; i < TASK_COUNT; ++i) + pool.AddTask(new CanceledTask()); + + pool.Stop(); + + TEST_EQUAL(finishCounter, TASK_COUNT, ()); +} + +namespace +{ + class CancelTestTask : public threads::IRoutine + { + public: + CancelTestTask(bool isWaitDoCall) + : m_waitDoCall(isWaitDoCall) + , m_doCalled(false) + { + } + + ~CancelTestTask() + { + TEST_EQUAL(m_waitDoCall, m_doCalled, ()); + } + + virtual void Do() + { + TEST_EQUAL(m_waitDoCall, true, ()); + m_doCalled = true; + threads::Sleep(100); + } + + private: + bool m_waitDoCall; + bool m_doCalled; + }; +} + +UNIT_TEST(ThreadPool_ExecutionTaskTest) +{ + vector tasks; + for (int i = 0; i < TASK_COUNT - 1; ++i) + tasks.push_back(new CancelTestTask(true)); + tasks.push_back(new CancelTestTask(false)); + + int finishCounter = 0; + threads::Condition cond; + threads::ThreadPool pool(4, bind(&JoinFinishFunction, _1, ref(finishCounter), ref(cond))); + + for (size_t i = 0; i < tasks.size(); ++i) + pool.AddTask(tasks[i]); + + tasks.back()->Cancel(); + tasks.clear(); + + while(true) + { + cond.Lock(); + + if (finishCounter == TASK_COUNT) + break; + + cond.Wait(); + cond.Unlock(); + } +} + +UNIT_TEST(ThreadPool_EmptyTest) +{ + int finishCouter = 0; + threads::Condition cond; + threads::ThreadPool pool(4, bind(&JoinFinishFunction, _1, ref(finishCouter), ref(cond))); + + threads::Sleep(100); + pool.Stop(); +}