LCOV - code coverage report
Current view: top level - iomanager/unittest - StdDeQueue_test.cxx (source / functions) Coverage Total Hit
Test: code.result Lines: 61.5 % 52 32
Test Date: 2025-12-21 13:07:08 Functions: 100.0 % 4 4

            Line data    Source code
       1              : /**
       2              :  *
       3              :  * @file StdDeQueue_test.cxx StdDeQueue 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 "iomanager/queue/StdDeQueue.hpp"
      11              : 
      12              : #define BOOST_TEST_MODULE StdDeQueue_test // NOLINT
      13              : #include "boost/test/unit_test.hpp"
      14              : 
      15              : #include <chrono>
      16              : 
      17              : BOOST_AUTO_TEST_SUITE(StdDeQueue_test)
      18              : 
      19              : namespace {
      20              : 
      21              : constexpr int max_testable_capacity = 1'000'000'000; ///< The maximum capacity this test will attempt to check
      22              : 
      23              : constexpr double fractional_timeout_tolerance =
      24              :   0.5; ///< The fraction of the timeout which the timing is allowed to be off by
      25              : 
      26              : /**
      27              :  * @brief Timeout to use for tests
      28              :  *
      29              :  * Don't set the timeout to zero, otherwise the tests will fail since they'd
      30              :  * expect the push/pop functions to execute instananeously
      31              :  */
      32              : constexpr auto timeout = std::chrono::milliseconds(5);
      33              : /**
      34              :  * @brief Timeout expressed in microseconds
      35              :  */
      36              : constexpr auto timeout_in_us = std::chrono::duration_cast<std::chrono::microseconds>(timeout).count();
      37              : 
      38              : } // namespace ""
      39              : 
      40              : // This test case should run first. Make sure all other test cases depend on
      41              : // this.
      42              : 
      43            2 : BOOST_AUTO_TEST_CASE(sanity_checks)
      44              : {
      45              : 
      46            1 :   dunedaq::iomanager::StdDeQueue<int> queue("StdDeQueue", 10); ///< Queue instance for the test
      47            1 :   BOOST_REQUIRE(!queue.can_pop());
      48              : 
      49            1 :   auto start_time = std::chrono::steady_clock::now();
      50            1 :   try {
      51            1 :     queue.push(42, timeout);
      52            0 :   } catch (const dunedaq::iomanager::QueueTimeoutExpired& ex) {
      53            0 :     BOOST_TEST_REQUIRE(false, "Test failure: unexpected timeout exception throw from push");
      54            0 :   } catch (...) { // NOLINT
      55            0 :     BOOST_TEST_REQUIRE(false, "Test failure: unexpected exception (non-timeout-related) thrown");
      56            0 :   }
      57              : 
      58            1 :   auto push_time = std::chrono::steady_clock::now() - start_time;
      59              : 
      60            1 :   if (push_time > timeout) {
      61            0 :     auto push_time_in_us = std::chrono::duration_cast<std::chrono::microseconds>(push_time).count();
      62              : 
      63            0 :     BOOST_TEST_REQUIRE(false,
      64              :                        "Test failure: pushing element onto empty Queue "
      65              :                        "resulted in a timeout without an exception throw (function exited after "
      66              :                          << push_time_in_us << " microseconds, timeout is " << timeout_in_us << " microseconds)");
      67              :   }
      68              : 
      69            1 :   BOOST_REQUIRE(queue.can_pop());
      70              : 
      71            1 :   start_time = std::chrono::steady_clock::now();
      72            1 :   int popped_value = -999;
      73            1 :   try {
      74            1 :     queue.pop(popped_value, timeout);
      75            0 :   } catch (const dunedaq::iomanager::QueueTimeoutExpired& ex) {
      76            0 :     BOOST_TEST_REQUIRE(false, "Test failure: unexpected timeout exception throw from pop");
      77            0 :   } catch (...) { // NOLINT
      78            0 :     BOOST_TEST_REQUIRE(false, "Test failure: unexpected exception (non-timeout-related) thrown");
      79            0 :   }
      80            1 :   auto pop_time = std::chrono::steady_clock::now() - start_time;
      81              : 
      82            1 :   if (pop_time > timeout) {
      83            0 :     auto pop_time_in_us = std::chrono::duration_cast<std::chrono::microseconds>(pop_time).count();
      84            0 :     BOOST_TEST_REQUIRE(false,
      85              :                        "Test failure: popping element off Queue "
      86              :                        "resulted in a timeout without an exception throw (function exited after "
      87              :                          << pop_time_in_us << " microseconds, timeout is " << timeout_in_us << " microseconds)");
      88              :   }
      89              : 
      90            1 :   BOOST_REQUIRE_EQUAL(popped_value, 42);
      91            1 : }
      92              : 
      93            2 : BOOST_AUTO_TEST_CASE(empty_checks)
      94              : {
      95            1 :   dunedaq::iomanager::StdDeQueue<int> queue("StdDeQueue", 10); ///< Queue instance for the test
      96            1 :   int popped_value = -999;
      97              : 
      98            1 :   while (queue.can_pop()) {
      99              : 
     100            0 :     try {
     101            0 :       queue.pop(popped_value, timeout);
     102            0 :     } catch (const dunedaq::iomanager::QueueTimeoutExpired& ex) {
     103            0 :       BOOST_TEST(false,
     104              :                  "Timeout exception thrown in call to StdDeQueue::pop(); unable "
     105              :                  "to empty the Queue");
     106            0 :       break;
     107            0 :     }
     108              :   }
     109              : 
     110            1 :   BOOST_REQUIRE(!queue.can_pop());
     111              : 
     112              :   // pop off of an empty Queue
     113              : 
     114            1 :   auto starttime = std::chrono::steady_clock::now();
     115              : 
     116            2 :   BOOST_CHECK_THROW(queue.pop(popped_value, timeout), dunedaq::iomanager::QueueTimeoutExpired);
     117              : 
     118            1 :   auto pop_duration = std::chrono::steady_clock::now() - starttime;
     119              : 
     120            1 :   const double fraction_of_pop_timeout_used =
     121            1 :     static_cast<double>(std::chrono::duration_cast<std::chrono::nanoseconds>(pop_duration).count()) /
     122            1 :     std::chrono::duration_cast<std::chrono::nanoseconds>(timeout).count();
     123              : 
     124            1 :   BOOST_TEST_MESSAGE("Attempted pop_duration divided by timeout is " << fraction_of_pop_timeout_used);
     125              : 
     126            1 :   BOOST_CHECK_GT(fraction_of_pop_timeout_used, 1 - fractional_timeout_tolerance);
     127            1 :   BOOST_CHECK_LT(fraction_of_pop_timeout_used, 1 + fractional_timeout_tolerance);
     128            1 : }
     129              : 
     130              : BOOST_AUTO_TEST_SUITE_END()
        

Generated by: LCOV version 2.0-1