// // Created by fomenko on 23.09.2019. // #include "executor.h" #include "gtest/gtest.h" #include "gmock/gmock.h" using ::testing::_; using ::testing::SetArgReferee; using ::testing::DoAll; using ::testing::DeleteArg; using ::testing::Return; using ::testing::AtLeast; using ::testing::ByRef; using ::testing::Eq; typedef std::function VoidFunc; namespace std { inline bool operator ==(const VoidFunc& s, const VoidFunc& v) { // TODO VoidFunc operator == return true; } } const int THREAD_COUNT = 2; class MockThread : public AbstractThread { public: 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_METHOD2(poll, VoidFunc(int timeoutMs, const VoidFunc& defaultVal)); MOCK_METHOD0(capacity, size_t()); MOCK_METHOD0(remainingCapacity, size_t()); }; class MockThreadFactory : public PIThreadFactory { public: int callCount = 0; PIVector threads; std::function checkThreadExpectations = [](MockThread* thread){ EXPECT_CALL(*thread, start()) .WillOnce(Return(true)); EXPECT_CALL(*thread, stop()) .WillOnce(Return()); }; std::function checkThreadFunc = [](const VoidFunc& fun) { }; AbstractThread* newThread(const VoidFunc& fun) override { callCount++; auto* thread = new MockThread(); threads.push_back(thread); checkThreadExpectations(thread); checkThreadFunc(fun); return threads.back(); } }; TEST(ExecutorUnitTest, is_corePool_created) { auto* deque = new MockDeque(); auto* threadFactory = new MockThreadFactory(); PIThreadPoolExecutor executor(THREAD_COUNT, deque, threadFactory); ASSERT_EQ(THREAD_COUNT, threadFactory->callCount); } TEST(ExecutorUnitTest, is_corePool_started) { auto* deque = new MockDeque(); auto* threadFactory = new MockThreadFactory(); PIThreadPoolExecutor executor(THREAD_COUNT, deque, threadFactory); } TEST(ExecutorUnitTest, execute_is_added_to_taskQueue) { VoidFunc voidFunc = [](){}; auto* deque = new MockDeque(); EXPECT_CALL(*deque, offer(Eq(voidFunc))) .WillOnce(Return(true)); auto* threadFactory = new MockThreadFactory(); PIThreadPoolExecutor executor(THREAD_COUNT, deque, threadFactory); executor.execute([]() {}); } TEST(ExecutorUnitTest, is_corePool_execute_queue_elements) { auto* deque = new MockDeque(); auto* threadFactory = new MockThreadFactory(); threadFactory->checkThreadFunc = [](const VoidFunc& fun) { fun(); }; ON_CALL(*deque, take()) .WillByDefault(Return([](){})); EXPECT_CALL(*deque, poll(_, _)) .Times(THREAD_COUNT) .WillRepeatedly(Return([](){})); PIThreadPoolExecutor executor(THREAD_COUNT, deque, threadFactory); } TEST(ExecutorUnitTest, shutdown_is_stop_threads) { auto* deque = new MockDeque(); auto* threadFactory = new MockThreadFactory(); PIVector threadFuncs; threadFactory->checkThreadExpectations = [](MockThread* thread) { EXPECT_CALL(*thread, start()) .WillOnce(Return(true)); EXPECT_CALL(*thread, stop()) .WillRepeatedly(Return()); }; threadFactory->checkThreadFunc = [&](const VoidFunc& threadFunc) { threadFuncs.push_back(threadFunc); }; ON_CALL(*deque, take()) .WillByDefault(Return(VoidFunc())); EXPECT_CALL(*deque, poll(_, _)) .Times(THREAD_COUNT) .WillRepeatedly(Return(VoidFunc())); PIThreadPoolExecutor executor(THREAD_COUNT, deque, threadFactory); executor.shutdown(); piForeachC(VoidFunc& threadFunc, threadFuncs) threadFunc(); }