LCOV - code coverage report
Current view: top level - test/Generators - CommandableFragmentGenerator_t.cc (source / functions) Coverage Total Hit
Test: artdaq.info.cleaned Lines: 100.0 % 223 223
Test Date: 2025-09-04 00:45:34 Functions: 60.9 % 174 106

            Line data    Source code
       1              : #define BOOST_TEST_MODULE CommandableFragmentGenerator_t
       2              : #include <boost/test/unit_test.hpp>
       3              : 
       4              : #include "TRACE/tracemf.h"
       5              : #define TRACE_NAME "CommandableFragmentGenerator_t"
       6              : 
       7              : #include "artdaq-core/Data/ContainerFragment.hh"
       8              : #include "artdaq-core/Data/Fragment.hh"
       9              : #include "artdaq-core/Utilities/configureMessageFacility.hh"
      10              : #include "artdaq/DAQdata/Globals.hh"
      11              : #include "artdaq/Generators/CommandableFragmentGenerator.hh"
      12              : 
      13              : #define TRACE_REQUIRE_EQUAL(l, r)                                                                                                    \
      14              :         do                                                                                                                               \
      15              :         {                                                                                                                                \
      16              :                 if ((l) == (r))                                                                                                              \
      17              :                 {                                                                                                                            \
      18              :                         TLOG(TLVL_DEBUG) << __LINE__ << ": Checking if " << #l << " (" << (l) << ") equals " << #r << " (" << (r) << ")...YES!"; \
      19              :                 }                                                                                                                            \
      20              :                 else                                                                                                                         \
      21              :                 {                                                                                                                            \
      22              :                         TLOG(TLVL_ERROR) << __LINE__ << ": Checking if " << #l << " (" << (l) << ") equals " << #r << " (" << (r) << ")...NO!";  \
      23              :                 }                                                                                                                            \
      24              :                 BOOST_REQUIRE_EQUAL((l), (r));                                                                                               \
      25              :         } while (false)
      26              : 
      27              : #define TRACE_REQUIRE(b)                                                                                 \
      28              :         do                                                                                                   \
      29              :         {                                                                                                    \
      30              :                 if (b)                                                                                           \
      31              :                 {                                                                                                \
      32              :                         TLOG(TLVL_DEBUG) << __LINE__ << ": Checking if " << #b << " (" << (b) << ") is true...YES!"; \
      33              :                 }                                                                                                \
      34              :                 else                                                                                             \
      35              :                 {                                                                                                \
      36              :                         TLOG(TLVL_ERROR) << __LINE__ << ": Checking if " << #b << " (" << (b) << ") is true...NO!";  \
      37              :                 }                                                                                                \
      38              :                 BOOST_REQUIRE((b));                                                                              \
      39              :         } while (false)
      40              : 
      41              : namespace artdaqtest {
      42              : class CommandableFragmentGeneratorTest;
      43              : }
      44              : 
      45              : /**
      46              :  * \brief CommandableFragmentGenerator derived class for testing
      47              :  */
      48              : class artdaqtest::CommandableFragmentGeneratorTest : public artdaq::CommandableFragmentGenerator
      49              : {
      50              : public:
      51              :         /**
      52              :          * \brief CommandableFragmentGeneratorTest Constructor
      53              :          */
      54              :         explicit CommandableFragmentGeneratorTest(const fhicl::ParameterSet& ps);
      55              : 
      56            6 :         ~CommandableFragmentGeneratorTest() override { joinThreads(); };
      57              : 
      58              : private:
      59              :         CommandableFragmentGeneratorTest(CommandableFragmentGeneratorTest const&) = delete;
      60              :         CommandableFragmentGeneratorTest(CommandableFragmentGeneratorTest&&) = delete;
      61              :         CommandableFragmentGeneratorTest& operator=(CommandableFragmentGeneratorTest const&) = delete;
      62              :         CommandableFragmentGeneratorTest& operator=(CommandableFragmentGeneratorTest&&) = delete;
      63              : 
      64              : protected:
      65              :         /**
      66              :          * \brief Generate data and return it to CommandableFragmentGenerator
      67              :          * \param frags FragmentPtrs list that new Fragments should be added to
      68              :          * \return True if data was generated
      69              :          *
      70              :          * CommandableFragmentGeneratorTest merely default-constructs Fragments, emplacing them on the frags list.
      71              :          */
      72              :         bool getNext_(artdaq::FragmentPtrs& frags) override;
      73              : 
      74              :         /**
      75              :          * \brief Returns whether the hwFail flag has not been set
      76              :          * \return If hwFail has been set, false, otherwise true
      77              :          */
      78            4 :         bool checkHWStatus_() override { return !hwFail_.load(); }
      79              : 
      80              :         /**
      81              :          * \brief Perform start actions. No-Op
      82              :          */
      83              :         void start() override;
      84              : 
      85              :         /**
      86              :          * \brief Perform immediate stop actions. No-Op
      87              :          */
      88              :         void stopNoMutex() override;
      89              : 
      90              :         /**
      91              :          * \brief Perform stop actions. No-Op
      92              :          */
      93              :         void stop() override;
      94              : 
      95              :         /**
      96              :          * \brief Perform pause actions. No-Op
      97              :          */
      98              :         void pause() override;
      99              : 
     100              :         /**
     101              :          * \brief Perform resume actions. No-Op
     102              :          */
     103              :         void resume() override;
     104              : 
     105              : public:
     106              :         /**
     107              :          * \brief Have getNext_ generate count fragments
     108              :          * \param count Number of fragments to generate
     109              :          */
     110            5 :         void setFireCount(size_t count) { fireCount_ = count; }
     111              : 
     112              :         /**
     113              :          * \brief Set the hwFail flag
     114              :          */
     115            2 :         void setHwFail() { hwFail_ = true; }
     116              : 
     117              :         /**
     118              :          * \brief Set the enabled IDs mask for the Fragment Generator
     119              :          * \param bitmask Bitmask of enabled IDs for the Fragment Generator
     120              :          *
     121              :          * For testing, this bitmask allows a configured Fragment ID to not be generated by a given call to setFireCount.
     122              :          * This is used to create asymmetric response from the Fragment generator in the _MultipleIDs test cases
     123              :          */
     124            1 :         void setEnabledIds(uint64_t bitmask) { enabled_ids_ = bitmask; }
     125              : 
     126              :         /**
     127              :          * \brief Set the timestamp to be used for the next Fragment
     128              :          * \param ts Timestamp to be used for the next Fragment
     129              :          */
     130              :         void setTimestamp(artdaq::Fragment::timestamp_t ts) { ts_ = ts; }
     131              : 
     132              :         /**
     133              :          * \brief Get the timestamp that will be used for the next Fragment
     134              :          * \return The timestamp that will be used for the next Fragment
     135              :          */
     136              :         artdaq::Fragment::timestamp_t getTimestamp() { return ts_; }
     137              : 
     138              : private:
     139              :         std::atomic<size_t> fireCount_;
     140              :         std::atomic<bool> hwFail_;
     141              :         artdaq::Fragment::timestamp_t ts_;
     142              :         std::atomic<bool> hw_stop_;
     143              :         std::atomic<uint64_t> enabled_ids_;
     144              : };
     145              : 
     146            6 : artdaqtest::CommandableFragmentGeneratorTest::CommandableFragmentGeneratorTest(const fhicl::ParameterSet& ps)
     147              :     : CommandableFragmentGenerator(ps)
     148            6 :     , fireCount_(1)
     149            6 :     , hwFail_(false)
     150            6 :     , ts_(0)
     151            6 :     , hw_stop_(false)
     152           12 :     , enabled_ids_(-1)
     153              : {
     154           24 :         metricMan->initialize(ps.get<fhicl::ParameterSet>("metrics", fhicl::ParameterSet()));
     155            6 :         metricMan->do_start();
     156            6 : }
     157              : 
     158           10 : bool artdaqtest::CommandableFragmentGeneratorTest::getNext_(artdaq::FragmentPtrs& frags)
     159              : {
     160           19 :         while (fireCount_ > 0)
     161              :         {
     162            9 :                 ++ts_;
     163           22 :                 for (auto& id : fragmentIDs())
     164              :                 {
     165           13 :                         if (id < 64 && ((enabled_ids_ & (0x1 << id)) != 0))
     166              :                         {
     167           36 :                                 TLOG(TLVL_DEBUG) << "Adding Fragment with ID " << id << ", SeqID " << ev_counter() << ", and timestamp " << ts_;
     168           12 :                                 frags.emplace_back(new artdaq::Fragment(ev_counter(), id, artdaq::Fragment::FirstUserFragmentType, ts_));
     169              :                         }
     170            9 :                 }
     171            9 :                 fireCount_--;
     172            9 :                 ev_counter_inc();
     173              :         }
     174              : 
     175           10 :         return !hw_stop_;
     176              : }
     177              : 
     178            7 : void artdaqtest::CommandableFragmentGeneratorTest::start() { hw_stop_ = false; }
     179              : 
     180            3 : void artdaqtest::CommandableFragmentGeneratorTest::stopNoMutex() {}
     181              : 
     182            3 : void artdaqtest::CommandableFragmentGeneratorTest::stop() { hw_stop_ = true; }
     183              : 
     184            1 : void artdaqtest::CommandableFragmentGeneratorTest::pause() {}
     185              : 
     186            1 : void artdaqtest::CommandableFragmentGeneratorTest::resume() {}
     187              : 
     188              : BOOST_AUTO_TEST_SUITE(CommandableFragmentGenerator_t)
     189              : 
     190            2 : BOOST_AUTO_TEST_CASE(Simple)
     191              : {
     192            1 :         artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
     193            3 :         TLOG(TLVL_INFO) << "Simple test case BEGIN";
     194            1 :         fhicl::ParameterSet ps;
     195            2 :         ps.put<int>("fragment_id", 1);
     196            1 :         artdaqtest::CommandableFragmentGeneratorTest testGen(ps);
     197              : 
     198            1 :         testGen.StartCmd(1, 1, 1);
     199              : 
     200            1 :         artdaq::FragmentPtrs fps;
     201            1 :         auto sts = testGen.getNext(fps);
     202            4 :         TRACE_REQUIRE_EQUAL(sts, true);
     203            4 :         TRACE_REQUIRE_EQUAL(fps.size(), 1u);
     204            4 :         TRACE_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
     205            4 :         TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
     206            4 :         TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
     207            3 :         TLOG(TLVL_INFO) << "Simple test case END";
     208            1 : }
     209              : 
     210            2 : BOOST_AUTO_TEST_CASE(WaitForStart)
     211              : {
     212            1 :         artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
     213            3 :         TLOG(TLVL_INFO) << "WaitForStart test case BEGIN";
     214            1 :         fhicl::ParameterSet ps;
     215            2 :         ps.put<int>("fragment_id", 1);
     216            1 :         artdaqtest::CommandableFragmentGeneratorTest testGen(ps);
     217              : 
     218            1 :         artdaq::FragmentPtrs fps;
     219            1 :         auto sts = testGen.getNext(fps);
     220            4 :         TRACE_REQUIRE_EQUAL(sts, false);
     221            4 :         TRACE_REQUIRE_EQUAL(fps.size(), 0u);
     222              : 
     223            1 :         usleep(10000);
     224            1 :         sts = testGen.getNext(fps);
     225            4 :         TRACE_REQUIRE_EQUAL(sts, false);
     226            4 :         TRACE_REQUIRE_EQUAL(fps.size(), 0u);
     227              : 
     228            1 :         testGen.StartCmd(2, 1, 1);
     229              : 
     230            1 :         sts = testGen.getNext(fps);
     231            4 :         TRACE_REQUIRE_EQUAL(sts, true);
     232            4 :         TRACE_REQUIRE_EQUAL(fps.size(), 1u);
     233            4 :         TRACE_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
     234            4 :         TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
     235            4 :         TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
     236            3 :         TLOG(TLVL_INFO) << "WaitForStart test case END";
     237            1 : }
     238              : 
     239            2 : BOOST_AUTO_TEST_CASE(StateMachine)
     240              : {
     241            1 :         artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
     242            3 :         TLOG(TLVL_INFO) << "StateMachine test case BEGIN";
     243            1 :         fhicl::ParameterSet ps;
     244            2 :         ps.put<int>("fragment_id", 1);
     245            1 :         artdaqtest::CommandableFragmentGeneratorTest testGen(ps);
     246              : 
     247            1 :         artdaq::FragmentPtrs fps;
     248            1 :         auto sts = testGen.getNext(fps);
     249            4 :         TRACE_REQUIRE_EQUAL(sts, false);
     250            4 :         TRACE_REQUIRE_EQUAL(fps.size(), 0u);
     251              : 
     252            1 :         usleep(10000);
     253            1 :         sts = testGen.getNext(fps);
     254            4 :         TRACE_REQUIRE_EQUAL(sts, false);
     255            4 :         TRACE_REQUIRE_EQUAL(fps.size(), 0u);
     256              : 
     257            1 :         testGen.StartCmd(2, 1, 1);
     258              : 
     259            1 :         sts = testGen.getNext(fps);
     260            4 :         TRACE_REQUIRE_EQUAL(sts, true);
     261            4 :         TRACE_REQUIRE_EQUAL(fps.size(), 1u);
     262            4 :         TRACE_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
     263            4 :         TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
     264            4 :         TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
     265            1 :         fps.clear();
     266              : 
     267            1 :         testGen.setFireCount(1);
     268            1 :         testGen.PauseCmd(1, 1);
     269            1 :         sts = testGen.getNext(fps);
     270            4 :         TRACE_REQUIRE_EQUAL(sts, false);
     271            4 :         TRACE_REQUIRE_EQUAL(fps.size(), 0u);
     272              : 
     273            1 :         testGen.ResumeCmd(1, 1);
     274              : 
     275            1 :         sts = testGen.getNext(fps);
     276            4 :         TRACE_REQUIRE_EQUAL(sts, true);
     277            4 :         TRACE_REQUIRE_EQUAL(fps.size(), 1u);
     278            4 :         TRACE_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
     279            4 :         TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 2);
     280            4 :         TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 2);
     281            1 :         fps.clear();
     282              : 
     283            1 :         testGen.StopCmd(1, 1);
     284            1 :         sts = testGen.getNext(fps);
     285            4 :         TRACE_REQUIRE_EQUAL(sts, false);
     286            4 :         TRACE_REQUIRE_EQUAL(fps.size(), 0u);
     287              : 
     288            1 :         testGen.StartCmd(2, 1, 1);
     289            1 :         sts = testGen.getNext(fps);
     290            4 :         TRACE_REQUIRE_EQUAL(sts, true);
     291            4 :         TRACE_REQUIRE_EQUAL(fps.size(), 0u);
     292              : 
     293            1 :         testGen.setFireCount(1);
     294            1 :         sts = testGen.getNext(fps);
     295            4 :         TRACE_REQUIRE_EQUAL(sts, true);
     296            4 :         TRACE_REQUIRE_EQUAL(fps.size(), 1u);
     297            4 :         TRACE_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
     298            4 :         TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 3);
     299            4 :         TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
     300            1 :         fps.clear();
     301              : 
     302            3 :         TLOG(TLVL_INFO) << "StateMachine test case END";
     303            1 : }
     304              : 
     305            2 : BOOST_AUTO_TEST_CASE(MultipleIDs)
     306              : {
     307            1 :         artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
     308            3 :         TLOG(TLVL_INFO) << "MultipleIDs test case BEGIN";
     309            1 :         fhicl::ParameterSet ps;
     310            4 :         ps.put<std::vector<int>>("fragment_ids", {1, 2, 3});
     311            2 :         ps.put<int>("generated_fragments_per_event", 3);
     312              : 
     313            1 :         artdaqtest::CommandableFragmentGeneratorTest testGen(ps);
     314            1 :         testGen.StartCmd(3, 1, 1);
     315              : 
     316            1 :         artdaq::FragmentPtrs fps;
     317            1 :         auto sts = testGen.getNext(fps);
     318              : 
     319            1 :         std::map<artdaq::Fragment::fragment_id_t, size_t> ids;
     320            4 :         TRACE_REQUIRE_EQUAL(sts, true);
     321            4 :         TRACE_REQUIRE_EQUAL(fps.size(), 3u);
     322            4 :         while (fps.size() > 0)
     323              :         {
     324            3 :                 ids[fps.front()->fragmentID()]++;
     325           12 :                 TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
     326           12 :                 TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
     327            3 :                 fps.pop_front();
     328              :         }
     329              : 
     330            4 :         TRACE_REQUIRE_EQUAL(ids[1], 1);
     331            4 :         TRACE_REQUIRE_EQUAL(ids[2], 1);
     332            4 :         TRACE_REQUIRE_EQUAL(ids[3], 1);
     333            1 :         ids.clear();
     334              : 
     335            1 :         fps.clear();
     336              : 
     337            1 :         testGen.setEnabledIds(0x6);  // 0110b, ID 3 disabled
     338            1 :         testGen.setFireCount(1);
     339              : 
     340            1 :         sts = testGen.getNext(fps);
     341              : 
     342            4 :         TRACE_REQUIRE_EQUAL(sts, true);
     343            4 :         TRACE_REQUIRE_EQUAL(fps.size(), 2u);
     344            3 :         while (!fps.empty())
     345              :         {
     346            2 :                 ids[fps.front()->fragmentID()]++;
     347            8 :                 TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 2);
     348            8 :                 TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 2);
     349            2 :                 fps.pop_front();
     350              :         }
     351            4 :         TRACE_REQUIRE_EQUAL(ids[1], 1);
     352            4 :         TRACE_REQUIRE_EQUAL(ids[2], 1);
     353            4 :         TRACE_REQUIRE_EQUAL(ids[3], 0);
     354              : 
     355            3 :         TLOG(TLVL_INFO) << "MultipleIDs test case END";
     356            1 : }
     357              : 
     358            2 : BOOST_AUTO_TEST_CASE(HardwareFailure_NonThreaded)
     359              : {
     360            1 :         artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
     361            3 :         TLOG(TLVL_INFO) << "HardwareFailure_NonThreaded test case BEGIN";
     362            1 :         fhicl::ParameterSet ps;
     363            2 :         ps.put<int>("fragment_id", 1);
     364            2 :         ps.put<bool>("separate_data_thread", false);
     365            2 :         ps.put<bool>("separate_monitoring_thread", false);
     366            2 :         ps.put<int64_t>("hardware_poll_interval_us", 10);
     367              : 
     368            1 :         auto buffer = std::make_shared<artdaq::RequestBuffer>();
     369            1 :         buffer->setRunning(true);
     370            1 :         artdaqtest::CommandableFragmentGeneratorTest gen(ps);
     371            1 :         gen.SetRequestBuffer(buffer);
     372            1 :         gen.StartCmd(4, 0xFFFFFFFF, 1);
     373              : 
     374            1 :         artdaq::FragmentPtrs fps;
     375            1 :         auto sts = gen.getNext(fps);
     376            4 :         TRACE_REQUIRE_EQUAL(sts, true);
     377            4 :         TRACE_REQUIRE_EQUAL(fps.size(), 1u);
     378            4 :         TRACE_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
     379            4 :         TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
     380            4 :         TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
     381            1 :         fps.clear();
     382              : 
     383            1 :         gen.setFireCount(1);
     384            1 :         gen.setHwFail();
     385            1 :         usleep(10000);
     386            1 :         sts = gen.getNext(fps);
     387            4 :         TRACE_REQUIRE_EQUAL(sts, false);
     388            4 :         TRACE_REQUIRE(fps.empty());
     389              : 
     390            1 :         gen.StopCmd(0xFFFFFFFF, 1);
     391            1 :         gen.joinThreads();
     392            3 :         TLOG(TLVL_INFO) << "HardwareFailure_NonThreaded test case END";
     393            1 : }
     394              : 
     395            2 : BOOST_AUTO_TEST_CASE(HardwareFailure_Threaded)
     396              : {
     397            1 :         artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
     398            3 :         TLOG(TLVL_INFO) << "HardwareFailure_Threaded test case BEGIN";
     399            1 :         fhicl::ParameterSet ps;
     400            2 :         ps.put<int>("fragment_id", 1);
     401            2 :         ps.put<bool>("separate_monitoring_thread", true);
     402            2 :         ps.put<int64_t>("hardware_poll_interval_us", 750000);
     403              : 
     404            1 :         auto buffer = std::make_shared<artdaq::RequestBuffer>();
     405            1 :         buffer->setRunning(true);
     406            1 :         artdaqtest::CommandableFragmentGeneratorTest gen(ps);
     407            1 :         gen.SetRequestBuffer(buffer);
     408            1 :         gen.StartCmd(5, 0xFFFFFFFF, 1);
     409              : 
     410            1 :         artdaq::FragmentPtrs fps;
     411            1 :         auto sts = gen.getNext(fps);
     412            4 :         TRACE_REQUIRE_EQUAL(sts, true);
     413            4 :         TRACE_REQUIRE_EQUAL(fps.size(), 1u);
     414            4 :         TRACE_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
     415            4 :         TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
     416            4 :         TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
     417            1 :         fps.clear();
     418              : 
     419            3 :         TLOG(TLVL_INFO) << "Setting failure bit";
     420            1 :         gen.setHwFail();
     421              : 
     422            1 :         sleep(1);
     423              : 
     424            3 :         TLOG(TLVL_INFO) << "Checking that failure is reported by getNext";
     425            1 :         gen.setFireCount(1);
     426            1 :         sts = gen.getNext(fps);
     427            4 :         TRACE_REQUIRE_EQUAL(sts, false);
     428            4 :         TRACE_REQUIRE(fps.empty());
     429              : 
     430            1 :         gen.StopCmd(0xFFFFFFFF, 1);
     431            1 :         gen.joinThreads();
     432            3 :         TLOG(TLVL_INFO) << "HardwareFailure_Threaded test case END";
     433            1 : }
     434              : 
     435              : BOOST_AUTO_TEST_SUITE_END()
        

Generated by: LCOV version 2.0-1