LCOV - code coverage report
Current view: top level - utilities/unittest - WorkerThread_test.cxx (source / functions) Coverage Total Hit
Test: code.result Lines: 100.0 % 62 62
Test Date: 2025-12-21 13:07:08 Functions: 100.0 % 10 10

            Line data    Source code
       1              : /**
       2              :  *
       3              :  * @file WorkerThread_test.cxx WorkerThread class Unit Tests
       4              :  *
       5              :  * This is part of the DUNE DAQ Application Framework, copyright 2020.
       6              :  * Licensing/copyright details are in the COPYING file that you should have
       7              :  * received with this code.
       8              :  */
       9              : 
      10              : #include "utilities/WorkerThread.hpp"
      11              : #include "utilities/Issues.hpp"
      12              : 
      13              : #define BOOST_TEST_MODULE WorkerThread_test // NOLINT
      14              : 
      15              : #include "boost/asio/signal_set.hpp"
      16              : #include "boost/test/unit_test.hpp"
      17              : 
      18              : #include <chrono>
      19              : #include <memory>
      20              : #include <string>
      21              : 
      22              : namespace {
      23              : 
      24              : void
      25            3 : do_something(std::atomic<bool>&)
      26              : {
      27            3 :   int num_seconds = 5;
      28            3 :   BOOST_TEST_MESSAGE("This function will just sleep for " << num_seconds << " second(s) and then return");
      29            3 :   std::this_thread::sleep_for(std::chrono::seconds(num_seconds));
      30            3 : }
      31              : 
      32              : std::string test_thread_name;
      33              : std::string actual_thread_name;
      34              : 
      35              : void
      36            2 : print_name(std::atomic<bool>&)
      37              : {
      38              :   // Give WorkerThread time to set the name
      39            2 :   std::this_thread::sleep_for(std::chrono::milliseconds(1));
      40              : 
      41            2 :   char buffer[16]; // NOLINT
      42            2 :   int res = pthread_getname_np(pthread_self(), buffer, 16);
      43            2 :   BOOST_REQUIRE_EQUAL(res, 0);
      44            2 :   actual_thread_name = std::string(buffer);
      45            2 :   BOOST_TEST_MESSAGE("This function prints the current thread name, which is " + actual_thread_name);
      46            2 : }
      47              : 
      48              : } // namespace ""
      49              : 
      50            2 : BOOST_AUTO_TEST_CASE(sanity_checks)
      51              : {
      52              : 
      53            1 :   std::unique_ptr<dunedaq::utilities::WorkerThread> umth_ptr = nullptr;
      54              : 
      55            1 :   auto starttime = std::chrono::steady_clock::now();
      56            1 :   BOOST_REQUIRE_NO_THROW(umth_ptr = std::make_unique<dunedaq::utilities::WorkerThread>(do_something));
      57            1 :   auto construction_time_in_ms =
      58            1 :     std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - starttime).count();
      59            1 :   BOOST_TEST_MESSAGE("Construction time was " << construction_time_in_ms << " ms");
      60              : 
      61            1 :   starttime = std::chrono::steady_clock::now();
      62            1 :   BOOST_REQUIRE_NO_THROW(umth_ptr->start_working_thread());
      63            1 :   auto start_time_in_ms =
      64            1 :     std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - starttime).count();
      65            1 :   BOOST_TEST_MESSAGE("Time to call WorkerThread::start_working_thread() was " << start_time_in_ms << " ms");
      66              : 
      67            1 :   starttime = std::chrono::steady_clock::now();
      68            1 :   BOOST_REQUIRE_NO_THROW(umth_ptr->stop_working_thread());
      69            1 :   auto stop_time_in_ms =
      70            1 :     std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - starttime).count();
      71            1 :   BOOST_TEST_MESSAGE("Time to call WorkerThread::stop_working_thread() was " << stop_time_in_ms << " ms");
      72            1 : }
      73              : 
      74            2 : BOOST_AUTO_TEST_CASE(inappropriate_transitions, *boost::unit_test::depends_on("sanity_checks"))
      75              : {
      76              : 
      77            1 :   dunedaq::utilities::WorkerThread umth(do_something);
      78            2 :   BOOST_REQUIRE_THROW(umth.stop_working_thread(), dunedaq::utilities::ThreadingIssue);
      79              : 
      80            1 :   umth.start_working_thread();
      81              : 
      82            3 :   BOOST_REQUIRE_THROW(umth.start_working_thread(), dunedaq::utilities::ThreadingIssue);
      83              : 
      84            1 :   umth.stop_working_thread();
      85            1 : }
      86              : 
      87            2 : BOOST_AUTO_TEST_CASE(thread_name)
      88              : {
      89            1 :   dunedaq::utilities::WorkerThread umth(print_name);
      90            1 :   test_thread_name = "name test";
      91            1 :   umth.start_working_thread(test_thread_name);
      92            1 :   umth.stop_working_thread();
      93              : 
      94            1 :   BOOST_REQUIRE_EQUAL(test_thread_name, actual_thread_name);
      95              : 
      96            1 :   test_thread_name = "too long name test";
      97            1 :   umth.start_working_thread(test_thread_name);
      98            1 :   umth.stop_working_thread();
      99              : 
     100              :   // Name not changed
     101            1 :   BOOST_REQUIRE_EQUAL(actual_thread_name, "WorkerThread_te");
     102            1 : }
     103              : 
     104              : // You'll want this to test case to execute last, for reasons that are obvious
     105              : // if you look at its checks
     106              : 
     107            2 : BOOST_AUTO_TEST_CASE(abort_checks, *boost::unit_test::depends_on("inappropriate_transitions"))
     108              : {
     109              : 
     110            1 :   {
     111            1 :     dunedaq::utilities::WorkerThread umth(do_something);
     112            1 :   }
     113            1 :   BOOST_TEST(true,
     114              :              "WorkerThread without having start_working_thread() thread "
     115              :              "called destructs without aborting the program, as expected");
     116              : 
     117            1 :   auto start_time = std::chrono::steady_clock::now();
     118            1 :   {
     119            1 :     dunedaq::utilities::WorkerThread umth(do_something);
     120            1 :     umth.start_working_thread();
     121            1 :   }
     122            1 :   BOOST_TEST(true,
     123              :              "WorkerThread having start_working_thread() thread "
     124              :              "called destructs without aborting the program, as expected");
     125            1 :   BOOST_REQUIRE(
     126              :     std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count() >=
     127              :     5000);
     128            1 : }
        

Generated by: LCOV version 2.0-1