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