Line data Source code
1 : #include <chrono> 2 : #include <gtest/gtest.h> 3 : #include <iostream> 4 : #include <openGPMP/core/threads.hpp> 5 : #include <random> 6 : #include <vector> 7 : 8 : using namespace std::chrono_literals; 9 : 10 : namespace { 11 4 : TEST(ThreadPoolTest, EnqueueSingleTask) { 12 1 : gpmp::core::ThreadPool pool(1); 13 2 : std::future<int> result = pool.enqueue([]() { return 42; }); 14 1 : ASSERT_EQ(result.get(), 42); 15 1 : } 16 : 17 4 : TEST(ThreadPoolTest, TestSingleTask) { 18 1 : gpmp::core::ThreadPool pool(2); 19 : 20 : std::future<int> result = 21 2 : pool.enqueue([](int x, int y) { return x + y; }, 3, 4); 22 : 23 1 : EXPECT_EQ(result.get(), 7); 24 1 : } 25 : 26 4 : TEST(ThreadPoolTest, EnqueueMultipleTasks) { 27 1 : gpmp::core::ThreadPool pool(4); 28 1 : std::vector<std::future<int>> results; 29 101 : for (int i = 0; i < 100; ++i) { 30 200 : results.emplace_back(pool.enqueue([i]() { return i * 2; })); 31 : } 32 101 : for (int i = 0; i < 100; ++i) { 33 100 : ASSERT_EQ(results[i].get(), i * 2); 34 : } 35 1 : } 36 : 37 4 : TEST(ThreadPoolTest, EnqueueException) { 38 1 : gpmp::core::ThreadPool pool(2); 39 : std::future<void> result = 40 2 : pool.enqueue([]() { throw std::runtime_error("test error"); }); 41 1 : ASSERT_THROW(result.get(), std::runtime_error); 42 1 : } 43 : 44 4 : TEST(ThreadPoolTest, TestException) { 45 1 : gpmp::core::ThreadPool pool(1); 46 : 47 3 : EXPECT_THROW( 48 : pool.enqueue([]() { throw std::runtime_error("test exception"); }) 49 : .get(), 50 1 : std::runtime_error); 51 1 : } 52 : 53 4 : TEST(ThreadPoolTest, TestDynamicAllocation) { 54 : // Create a new ThreadPool with 4 threads 55 1 : gpmp::core::ThreadPool *pool = new gpmp::core::ThreadPool(4); 56 : 57 : // Enqueue a task and wait for it to complete 58 2 : std::future<int> result = pool->enqueue([]() { return 42; }); 59 1 : EXPECT_EQ(result.get(), 42); 60 : 61 : // Delete the ThreadPool 62 1 : delete pool; 63 1 : } 64 : 65 4 : TEST(ThreadPoolTest, TestEnqueueOnStoppedThreadPool) { 66 : // Create a new ThreadPool with 2 threads 67 1 : gpmp::core::ThreadPool *pool = new gpmp::core::ThreadPool(2); 68 : 69 : // Stop the ThreadPool explicitly 70 1 : delete pool; // pool.~ThreadPool(); 71 : 72 : // Try to enqueue a task on the stopped ThreadPool 73 1 : EXPECT_THROW(pool->enqueue([]() { return 42; }), std::runtime_error); 74 1 : } 75 : 76 4 : TEST(ThreadPoolTest, TestEnqueueWithDifferentReturnTypes) { 77 1 : gpmp::core::ThreadPool pool(2); 78 : 79 1 : auto task1 = []() { /* do something */ }; 80 1 : auto task2 = []() -> int { return 42; }; 81 1 : auto task3 = []() -> std::string { return "hello world"; }; 82 : 83 1 : auto res1 = pool.enqueue(task1); 84 1 : auto res2 = pool.enqueue(task2); 85 1 : auto res3 = pool.enqueue(task3); 86 : 87 1 : res1.wait(); 88 1 : EXPECT_EQ(res2.get(), 42); 89 2 : EXPECT_EQ(res3.get(), "hello world"); 90 1 : } 91 : 92 4 : TEST(ThreadPoolTest, TestEnqueueWithDifferentArgumentTypes) { 93 1 : gpmp::core::ThreadPool pool(2); 94 : 95 1 : auto task1 = [](int x, int y) { /* do something */ }; 96 1 : auto task2 = [](const std::string &str) { /* do something */ }; 97 1 : auto task3 = [](bool flag, float value) { /* do something */ }; 98 : 99 1 : auto res1 = pool.enqueue(task1, 2, 3); 100 1 : auto res2 = pool.enqueue(task2, "hello world"); 101 1 : auto res3 = pool.enqueue(task3, true, 3.14f); 102 : 103 1 : res1.wait(); 104 1 : res2.wait(); 105 1 : res3.wait(); 106 1 : } 107 : 108 4 : TEST(ThreadPoolTest, TestEnqueueWithLargeNumberOfTasks) { 109 1 : const int numTasks = 1000; 110 1 : gpmp::core::ThreadPool pool(4); 111 : 112 1001 : for (int i = 0; i < numTasks; ++i) { 113 1000 : auto task = []() { /* do something */ }; 114 1000 : auto task2 = pool.enqueue(task); 115 1000 : task2.wait(); 116 1000 : } 117 1 : } 118 : 119 4 : TEST(ThreadPoolTest, DispatchFunction) { 120 1 : gpmp::core::ThreadPool pool(2); 121 : gpmp::core::ThreadDispatch dispatch; 122 : 123 : // fefine a lambda function to be dispatched to the thread pool 124 1 : auto task = []() -> int { return 42; }; 125 : 126 : // dispatch the task to the thread pool using 127 : // ThreadDispatch::dispatch() 128 1 : auto future_result = dispatch.dispatch(pool, task); 129 : 130 : // wait for the task to complete and get the result 131 1 : auto result = future_result.get(); 132 : 133 : // check if the result is correct 134 1 : EXPECT_EQ(result, 42); 135 1 : } 136 : 137 4 : TEST(ThreadPoolTest, DispatchFunctionWithArgs) { 138 1 : gpmp::core::ThreadPool pool(2); 139 : gpmp::core::ThreadDispatch dispatch; 140 : 141 : // define a lambda function to be dispatched to the thread pool, which 142 : // takes an integer argument and returns its square 143 1 : auto task = [](int x) -> int { return x * x; }; 144 : 145 1 : auto future_result = dispatch.dispatch(pool, task, 5); 146 : 147 1 : auto result = future_result.get(); 148 : 149 1 : EXPECT_EQ(result, 25); 150 1 : } 151 : 152 : } // namespace