#include "vdm/util/thread_pool.hpp" #include #include #include #include #include #include #include "vtest.hpp" using vdm::ThreadPool; VT_TEST(pool_runs_submitted_task_and_returns_value) { ThreadPool pool(2); auto f = pool.submit([](int a, int b) { return a + b; }, 20, 22); VT_CHECK_EQ(f.get(), 42); } VT_TEST(pool_default_size_is_at_least_one) { ThreadPool pool; VT_CHECK(pool.size() >= 1); } VT_TEST(pool_runs_many_tasks_across_workers) { ThreadPool pool(4); constexpr int kN = 500; std::atomic sum{0}; std::vector> fs; fs.reserve(kN); for (int i = 0; i < kN; ++i) fs.push_back(pool.submit([&sum, i] { sum += i; })); for (auto &f : fs) f.get(); VT_CHECK_EQ(sum.load(), kN * (kN - 1) / 2); } VT_TEST(pool_propagates_exceptions_through_future) { ThreadPool pool(1); auto f = pool.submit([]() -> int { throw std::runtime_error("boom"); }); bool threw = false; try { f.get(); } catch (const std::runtime_error &) { threw = true; } VT_CHECK(threw); } VT_TEST(pool_drains_queued_tasks_on_destruction) { std::atomic done{0}; { ThreadPool pool(2); for (int i = 0; i < 50; ++i) pool.submit([&done] { std::this_thread::sleep_for(std::chrono::milliseconds(1)); ++done; }); // pool dtor here: must let all 50 finish } VT_CHECK_EQ(done.load(), 50); } VT_TEST(pool_future_from_void_task_is_waitable) { ThreadPool pool(2); std::atomic ran{false}; auto f = pool.submit([&ran] { ran = true; }); f.get(); VT_CHECK(ran.load()); }