#include "gtest/gtest.h" #include "gmock/gmock.h" #include "piexecutor.h" #include "testutil.h" using ::testing::_; using ::testing::SetArgReferee; using ::testing::DoAll; using ::testing::DeleteArg; using ::testing::Return; using ::testing::AtLeast; using ::testing::ByRef; using ::testing::Eq; using ::testing::Ge; using ::testing::Pointee; using ::testing::IsNull; using ::testing::NiceMock; typedef std::function VoidFunc; namespace std { inline bool operator ==(const VoidFunc& s, const VoidFunc& v) { // TODO VoidFunc operator == return true; } } class MockThread { public: std::function runnnable; MockThread(std::function runnnable) : runnnable(runnnable) { } MOCK_METHOD0(start, bool()); MOCK_METHOD0(stop, void()); MOCK_METHOD1(waitForStart, bool(int timeout_msecs)); MOCK_METHOD1(waitForFinish, bool(int timeout_msecs)); }; class MockDeque : public PIBlockingDequeue { public: MOCK_METHOD1(offer, bool(const VoidFunc&)); MOCK_METHOD0(take, VoidFunc()); MOCK_METHOD1(poll, VoidFunc(int)); MOCK_METHOD0(capacity, size_t()); MOCK_METHOD0(remainingCapacity, size_t()); }; typedef PIThreadPoolExecutorTemplate, MockDeque> PIThreadPoolExecutorMoc_t; class PIThreadPoolExecutorMoc : public PIThreadPoolExecutorMoc_t { public: explicit PIThreadPoolExecutorMoc(size_t corePoolSize) : PIThreadPoolExecutorMoc_t(corePoolSize) { } template explicit PIThreadPoolExecutorMoc(size_t corePoolSize, Function onBeforeStart) : PIThreadPoolExecutorMoc_t(corePoolSize, onBeforeStart) { } PIVector*>* getThreadPool() { return &threadPool; } bool isShutdown() { return isShutdown_; } MockDeque* getTaskQueue() { return &taskQueue; } }; TEST(ExecutorUnitTest, is_corePool_created) { PIThreadPoolExecutorMoc executor(THREAD_COUNT); ASSERT_EQ(THREAD_COUNT, executor.getThreadPool()->size()); } TEST(ExecutorUnitTest, is_corePool_started) { PIThreadPoolExecutorMoc executor(THREAD_COUNT, [](MockThread* thread){ EXPECT_CALL(*thread, start()) .WillOnce(Return(true)); }); EXPECT_EQ(THREAD_COUNT, executor.getThreadPool()->size()); } TEST(ExecutorUnitTest, execute_is_added_to_taskQueue) { VoidFunc voidFunc = [](){}; PIThreadPoolExecutorMoc executor(THREAD_COUNT); EXPECT_CALL(*executor.getTaskQueue(), offer(Eq(voidFunc))) .WillOnce(Return(true)); executor.execute(voidFunc); } TEST(ExecutorUnitTest, is_corePool_execute_queue_elements) { bool is_executed = false; PIThreadPoolExecutorMoc executor(1); EXPECT_EQ(executor.getThreadPool()->size(), 1); EXPECT_CALL(*executor.getTaskQueue(), poll(Ge(0))) .WillOnce(Return([&](){ is_executed = true; })); executor.getThreadPool()->at(0)->runnnable(); ASSERT_TRUE(is_executed); } TEST(ExecutorUnitTest, shutdown_is_stop_threads) { // Exclude stop calls when executor deleting auto* executor = new PIThreadPoolExecutorMoc(THREAD_COUNT, [](MockThread* thread){ testing::Mock::AllowLeak(thread); EXPECT_CALL(*thread, stop()) .WillOnce(Return()); }); testing::Mock::AllowLeak(executor); testing::Mock::AllowLeak(executor->getTaskQueue()); EXPECT_CALL(*executor->getTaskQueue(), poll(Ge(0))) .WillRepeatedly(Return(std::function())); executor->shutdown(); executor->getThreadPool()->forEach([](MockThread* thread){ thread->runnnable(); }); }