ifw-daq 3.1.0
IFW Data Acquisition modules
Loading...
Searching...
No Matches
utils.hpp
Go to the documentation of this file.
1/**
2 * @file
3 * @ingroup daq_ocm_libdaq_test
4 * @copyright 2022 ESO - European Southern Observatory
5 *
6 * @brief Defines shared test utilities.
7 */
8#ifndef OCM_DAQ_TEST_UTILS_HPP_
9#define OCM_DAQ_TEST_UTILS_HPP_
10// GCOVR_EXCL_START
11#include <chrono>
12#include <thread>
13
14#include <boost/asio/io_context.hpp>
15#include <boost/asio/post.hpp>
16#include <gtest/gtest.h>
17
18/**
19 * Executes io_ctx::poll until @a pred returns true or it times out.
20 */
21template <class Predicate>
22void MakeTestProgressUntil(boost::asio::io_context& io_ctx,
23 Predicate&& pred,
24 std::chrono::milliseconds timeout = std::chrono::seconds(3)) {
25 auto until = std::chrono::steady_clock::now() + timeout;
26
27 while (std::chrono::steady_clock::now() < until) {
28 io_ctx.restart();
29 io_ctx.poll();
30 if (pred()) {
31 return;
32 }
33 }
34 FAIL() << "MakeTestProgressUntil timed out";
35}
36
37/**
38 * Test helper that progress the test by executing pending jobs and optionally wait for
39 * a future to be ready.
40 *
41 * @ingroup daq_ocm_libdaq_test
42 */
43template <class Future = void>
44void MakeTestProgress(boost::asio::io_context& io_ctx, Future* fut = nullptr) {
45 using namespace std::chrono;
46 using namespace ::testing;
47
48 auto work = std::make_unique<boost::asio::io_context::work>(io_ctx);
49
50 // Run asio in its own thread so we can independenty wait for future
51 std::thread t([&]() {
52 try {
53 io_ctx.restart();
54 io_ctx.run();
55 // The run() function blocks until all work has finished and there are no more handlers
56 // to be dispatched or until the io_context has been stopped.
57 } catch (std::exception const& e) {
58 FAIL() << "MakeTestProgress caught std::exception: " << e.what();
59 } catch (...) {
60 FAIL() << "MakeTestProgress caught unknown exception";
61 }
62 });
63 std::this_thread::yield();
64 if constexpr (!std::is_same_v<Future, void>) {
65 if (fut) {
66 EXPECT_NO_THROW(fut->wait_for(boost::chrono::seconds(3)));
67 }
68 boost::asio::post(io_ctx, [&] {
69 // remove work so that asio::io_context::run returns
70 work.reset();
71 // Explicitly stop io_ctx if future is ready. I.e. even if there are handlers pending
72 // we want to stop here since the caller might set up next step in the test.
73 io_ctx.stop();
74 });
75 t.join();
76 if (fut) {
77 ASSERT_TRUE(fut->is_ready()) << "Future is not ready after 1s, aborting";
78 }
79 } else {
80 // remove work so that asio::io_context::run returns
81 boost::asio::post(io_ctx, [&] { work.reset(); });
82 t.join();
83 }
84}
85
86// GCOVR_EXCL_STOP
87#endif // #ifndef OCM_DAQ_TEST_UTILS_HPP_
void MakeTestProgress(boost::asio::io_context &io_ctx, Future *fut=nullptr)
Test helper that progress the test by executing pending jobs and optionally wait for a future to be r...
Definition: utils.hpp:44
ASSERT_TRUE(std::holds_alternative< OlasReceiver >(spec.receivers[0]))
void MakeTestProgressUntil(boost::asio::io_context &io_ctx, Predicate &&pred, std::chrono::milliseconds timeout=std::chrono::seconds(3))
Executes io_ctx::poll until pred returns true or it times out.
Definition: utils.hpp:22