#include "../lib/Core.hpp" #include #include #include #include #include #include #include #include class TestEventLoop { private: std::unique_ptr loop_; std::thread thread_; public: TestEventLoop() { thread_ = std::thread([this]() { loop_ = std::make_unique(); loop_->loop(); }); std::this_thread::sleep_for(std::chrono::milliseconds(10)); } ~TestEventLoop() { if (loop_) { loop_->quit(); } if (thread_.joinable()) { thread_.join(); } } reactor::EventLoop* getLoop() { return loop_.get(); } }; void test_timer_basic() { std::cout << "Testing basic timer functionality...\n"; TestEventLoop test_loop; auto loop = test_loop.getLoop(); bool timer_fired = false; [[maybe_unused]] auto timer_id = loop->runAfter(reactor::Duration(50), [&timer_fired]() { timer_fired = true; }); std::this_thread::sleep_for(std::chrono::milliseconds(100)); assert(timer_fired); std::cout << "✓ Basic timer passed\n"; } void test_timer_cancellation() { std::cout << "Testing timer cancellation...\n"; TestEventLoop test_loop; auto loop = test_loop.getLoop(); bool timer_fired = false; auto timer_id = loop->runAfter(reactor::Duration(100), [&timer_fired]() { timer_fired = true; }); loop->cancel(timer_id); std::this_thread::sleep_for(std::chrono::milliseconds(150)); assert(!timer_fired); std::cout << "✓ Timer cancellation passed\n"; } void test_repeating_timer() { std::cout << "Testing repeating timer...\n"; TestEventLoop test_loop; auto loop = test_loop.getLoop(); int count = 0; auto timer_id = loop->runEvery(reactor::Duration(20), [&count]() { count++; }); std::this_thread::sleep_for(std::chrono::milliseconds(85)); loop->cancel(timer_id); assert(count >= 3 && count <= 5); std::cout << "✓ Repeating timer passed (count: " << count << ")\n"; } void test_run_in_loop() { std::cout << "Testing runInLoop functionality...\n"; TestEventLoop test_loop; auto loop = test_loop.getLoop(); bool task_executed = false; loop->runInLoop([&task_executed]() { task_executed = true; }); std::this_thread::sleep_for(std::chrono::milliseconds(50)); assert(task_executed); std::cout << "✓ runInLoop passed\n"; } void test_queue_in_loop() { std::cout << "Testing queueInLoop functionality...\n"; TestEventLoop test_loop; auto loop = test_loop.getLoop(); std::vector execution_order; loop->queueInLoop([&execution_order]() { execution_order.push_back(1); }); loop->queueInLoop([&execution_order]() { execution_order.push_back(2); }); loop->runInLoop([&execution_order]() { execution_order.push_back(3); }); std::this_thread::sleep_for(std::chrono::milliseconds(50)); assert(execution_order.size() == 3); assert(execution_order[0] == 1 || execution_order[0] == 2 || execution_order[0] == 3); std::cout << "✓ queueInLoop passed\n"; } void test_channel_basic() { std::cout << "Testing basic channel functionality...\n"; TestEventLoop test_loop; auto loop = test_loop.getLoop(); int event_fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); assert(event_fd >= 0); auto channel = std::make_unique(loop, event_fd); bool read_callback_called = false; channel->setReadCallback([&read_callback_called]() { read_callback_called = true; }); channel->enableReading(); uint64_t val = 1; write(event_fd, &val, sizeof(val)); std::this_thread::sleep_for(std::chrono::milliseconds(50)); assert(read_callback_called); channel->disableAll(); channel->remove(); close(event_fd); std::cout << "✓ Basic channel passed\n"; } void test_channel_write_events() { std::cout << "Testing channel write events...\n"; TestEventLoop test_loop; auto loop = test_loop.getLoop(); int event_fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); assert(event_fd >= 0); auto channel = std::make_unique(loop, event_fd); bool write_callback_called = false; channel->setWriteCallback([&write_callback_called]() { write_callback_called = true; }); channel->enableWriting(); std::this_thread::sleep_for(std::chrono::milliseconds(50)); assert(write_callback_called); channel->disableAll(); channel->remove(); close(event_fd); std::cout << "✓ Channel write events passed\n"; } void test_multiple_timers() { std::cout << "Testing multiple timers...\n"; TestEventLoop test_loop; auto loop = test_loop.getLoop(); std::vector timer_states(5, false); for (int i = 0; i < 5; ++i) { loop->runAfter(reactor::Duration(10 + i * 20), [&timer_states, i]() { timer_states[i] = true; }); } std::this_thread::sleep_for(std::chrono::milliseconds(120)); for (bool state : timer_states) { assert(state); } std::cout << "✓ Multiple timers passed\n"; } void test_timer_precision() { std::cout << "Testing timer precision...\n"; TestEventLoop test_loop; auto loop = test_loop.getLoop(); auto start_time = std::chrono::steady_clock::now(); bool timer_fired = false; loop->runAfter(reactor::Duration(100), [&timer_fired, start_time]() { auto end_time = std::chrono::steady_clock::now(); auto duration = std::chrono::duration_cast(end_time - start_time); timer_fired = true; assert(duration.count() >= 90 && duration.count() <= 150); }); std::this_thread::sleep_for(std::chrono::milliseconds(150)); assert(timer_fired); std::cout << "✓ Timer precision passed\n"; } void test_event_loop_thread_safety() { std::cout << "Testing event loop thread safety...\n"; TestEventLoop test_loop; auto loop = test_loop.getLoop(); std::atomic counter{0}; constexpr int num_tasks = 100; std::vector threads; for (int t = 0; t < 4; ++t) { threads.emplace_back([loop, &counter, num_tasks]() { for (int i = 0; i < num_tasks; ++i) { loop->queueInLoop([&counter]() { counter++; }); } }); } for (auto& thread : threads) { thread.join(); } std::this_thread::sleep_for(std::chrono::milliseconds(100)); assert(counter == 4 * num_tasks); std::cout << "✓ Event loop thread safety passed\n"; } int main() { std::cout << "=== Core Tests ===\n"; test_timer_basic(); test_timer_cancellation(); test_repeating_timer(); test_run_in_loop(); test_queue_in_loop(); test_channel_basic(); test_channel_write_events(); test_multiple_timers(); test_timer_precision(); test_event_loop_thread_safety(); std::cout << "All core tests passed! ✓\n"; return 0; }