|
8 | 8 | #include <BoostTestTargetConfig.h> |
9 | 9 | #include <thread> |
10 | 10 |
|
| 11 | +#include "test-thread.hpp" |
| 12 | + |
11 | 13 | using namespace icinga; |
12 | 14 |
|
13 | 15 | BOOST_AUTO_TEST_SUITE(base_io_engine) |
@@ -157,4 +159,56 @@ BOOST_AUTO_TEST_CASE(timeout_due_scope) |
157 | 159 | BOOST_CHECK_EQUAL(called, 0); |
158 | 160 | } |
159 | 161 |
|
| 162 | +BOOST_AUTO_TEST_CASE(base_io_engine_coroutine_resume_continuation) |
| 163 | +{ |
| 164 | + for (int i = 0; i < 150; ++i) { |
| 165 | + boost::asio::io_context io; |
| 166 | + boost::asio::io_context::strand strand{io}; |
| 167 | + |
| 168 | + auto dummyWork = [&strand] { |
| 169 | + BOOST_TEST(strand.running_in_this_thread() == true, "Doing some dummy work in the strand"); |
| 170 | + }; |
| 171 | + |
| 172 | + boost::asio::steady_timer timer(io); |
| 173 | + timer.expires_after(std::chrono::seconds(10)); |
| 174 | + |
| 175 | + std::atomic_bool testFailed{false}; |
| 176 | + IoEngine::SpawnCoroutine(strand, [&](boost::asio::yield_context yc) { |
| 177 | + BOOST_TEST(strand.running_in_this_thread() == true, "Coroutine started"); |
| 178 | + boost::system::error_code ec; |
| 179 | + timer.async_wait(yc[ec]); |
| 180 | + testFailed.store(strand.running_in_this_thread() == false); |
| 181 | + BOOST_TEST(strand.running_in_this_thread() == true, "Coroutine resumed after timer expired/cancelled: running_in_this_thread -> " << strand.running_in_this_thread()); |
| 182 | + }); |
| 183 | + |
| 184 | + boost::asio::post(strand, [&] { |
| 185 | + BOOST_TEST(strand.running_in_this_thread() == true, "Posting to strand from outside coroutine"); |
| 186 | + timer.cancel_one(); // Wake up the coroutine. |
| 187 | + boost::asio::post(strand, dummyWork); |
| 188 | + BOOST_TEST(strand.running_in_this_thread() == true, "End of post to strand from outside coroutine"); |
| 189 | + }); |
| 190 | + |
| 191 | + TestThread mockThread{[&io] { |
| 192 | + try{ |
| 193 | + io.run(); |
| 194 | + } catch (const std::exception& ex) { |
| 195 | + BOOST_FAIL("Exception in mock thread: " << ex.what()); |
| 196 | + } catch (...) { |
| 197 | + BOOST_FAIL("Unknown exception in mock thread"); |
| 198 | + } |
| 199 | + }}; |
| 200 | + try { |
| 201 | + io.run(); |
| 202 | + } catch (const std::exception& ex) { |
| 203 | + BOOST_FAIL("Exception in main thread: " << ex.what()); |
| 204 | + } catch (...) { |
| 205 | + BOOST_FAIL("Unknown exception in main thread"); |
| 206 | + } |
| 207 | + REQUIRE_JOINS_WITHIN(mockThread, 5s); |
| 208 | + if (testFailed.load()) { |
| 209 | + BOOST_FAIL("Test failed"); |
| 210 | + } |
| 211 | + } |
| 212 | +} |
| 213 | + |
160 | 214 | BOOST_AUTO_TEST_SUITE_END() |
0 commit comments