artdaq  v3_09_00
CommandableFragmentGenerator_t.cc
1 #define TRACE_NAME "CommandableFragmentGenerator_t"
2 
3 #define BOOST_TEST_MODULE CommandableFragmentGenerator_t
4 #include <boost/test/auto_unit_test.hpp>
5 
6 #include "artdaq-core/Data/ContainerFragment.hh"
7 #include "artdaq-core/Data/Fragment.hh"
8 #include "artdaq/DAQrate/RequestSender.hh"
9 #include "artdaq/Generators/CommandableFragmentGenerator.hh"
10 
11 #define TRACE_REQUIRE_EQUAL(l, r) \
12  do \
13  { \
14  if ((l) == (r)) \
15  { \
16  TLOG(TLVL_DEBUG) << __LINE__ << ": Checking if " << #l << " (" << (l) << ") equals " << #r << " (" << (r) << ")...YES!"; \
17  } \
18  else \
19  { \
20  TLOG(TLVL_ERROR) << __LINE__ << ": Checking if " << #l << " (" << (l) << ") equals " << #r << " (" << (r) << ")...NO!"; \
21  } \
22  BOOST_REQUIRE_EQUAL((l), (r)); \
23  } while (false)
24 
25 #define TRACE_REQUIRE(b) \
26  do \
27  { \
28  if (b) \
29  { \
30  TLOG(TLVL_DEBUG) << __LINE__ << ": Checking if " << #b << " (" << (b) << ") is true...YES!"; \
31  } \
32  else \
33  { \
34  TLOG(TLVL_ERROR) << __LINE__ << ": Checking if " << #b << " (" << (b) << ") is true...NO!"; \
35  } \
36  BOOST_REQUIRE((b)); \
37  } while (false)
38 
39 namespace artdaqtest {
40 class CommandableFragmentGeneratorTest;
41 }
42 
47 {
48 public:
52  explicit CommandableFragmentGeneratorTest(const fhicl::ParameterSet& ps);
53 
55 
56 private:
61 
62 protected:
70  bool getNext_(artdaq::FragmentPtrs& frags) override;
71 
76  bool checkHWStatus_() override { return !hwFail_.load(); }
77 
81  void start() override;
82 
86  void stopNoMutex() override;
87 
91  void stop() override;
92 
96  void pause() override;
97 
101  void resume() override;
102 
103 public:
108  void setFireCount(size_t count) { fireCount_ = count; }
109 
113  void setHwFail() { hwFail_ = true; }
114 
122  void setEnabledIds(uint64_t bitmask) { enabled_ids_ = bitmask; }
123 
128  void setTimestamp(artdaq::Fragment::timestamp_t ts) { ts_ = ts; }
129 
134  artdaq::Fragment::timestamp_t getTimestamp() { return ts_; }
135 
136 
137 private:
138  std::atomic<size_t> fireCount_;
139  std::atomic<bool> hwFail_;
140  artdaq::Fragment::timestamp_t ts_;
141  std::atomic<bool> hw_stop_;
142  std::atomic<uint64_t> enabled_ids_;
143 };
144 
146  : CommandableFragmentGenerator(ps)
147  , fireCount_(1)
148  , hwFail_(false)
149  , ts_(0)
150  , hw_stop_(false)
151  , enabled_ids_(-1)
152 {
153  metricMan->initialize(ps.get<fhicl::ParameterSet>("metrics", fhicl::ParameterSet()));
154  metricMan->do_start();
155 }
156 
158 {
159  while (fireCount_ > 0)
160  {
161  ++ts_;
162  for (auto& id : fragmentIDs())
163  {
164  if (id < 64 && ((enabled_ids_ & (0x1 << id)) != 0))
165  {
166  TLOG(TLVL_DEBUG) << "Adding Fragment with ID " << id << ", SeqID " << ev_counter() << ", and timestamp " << ts_;
167  frags.emplace_back(new artdaq::Fragment(ev_counter(), id, artdaq::Fragment::FirstUserFragmentType, ts_));
168  }
169  }
170  fireCount_--;
171  ev_counter_inc();
172  }
173 
174  return !hw_stop_;
175 }
176 
178 
180 
182 
184 
186 
187 BOOST_AUTO_TEST_SUITE(CommandableFragmentGenerator_t)
188 
189 BOOST_AUTO_TEST_CASE(Simple)
190 {
191  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
192  TLOG(TLVL_INFO) << "Simple test case BEGIN";
193  fhicl::ParameterSet ps;
194  ps.put<int>("board_id", 1);
195  ps.put<int>("fragment_id", 1);
197  artdaq::FragmentPtrs fps;
198  auto sts = testGen.getNext(fps);
199  TRACE_REQUIRE_EQUAL(sts, true);
200  TRACE_REQUIRE_EQUAL(fps.size(), 1u);
201  TRACE_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
202  TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
203  TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
204  TLOG(TLVL_INFO) << "Simple test case END";
205 }
206 
207 BOOST_AUTO_TEST_CASE(MultipleIDs)
208 {
209  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
210  TLOG(TLVL_INFO) << "MultipleIDs test case BEGIN";
211  fhicl::ParameterSet ps;
212  ps.put<int>("board_id", 1);
213  ps.put<std::vector<int>>("fragment_ids", {1, 2, 3});
214 
216  artdaq::FragmentPtrs fps;
217  auto sts = testGen.getNext(fps);
218 
219  std::map<artdaq::Fragment::fragment_id_t, size_t> ids;
220  TRACE_REQUIRE_EQUAL(sts, true);
221  TRACE_REQUIRE_EQUAL(fps.size(), 3u);
222  while (fps.size() > 0)
223  {
224  ids[fps.front()->fragmentID()]++;
225  TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
226  TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
227  fps.pop_front();
228  }
229 
230  TRACE_REQUIRE_EQUAL(ids[1], 1);
231  TRACE_REQUIRE_EQUAL(ids[2], 1);
232  TRACE_REQUIRE_EQUAL(ids[3], 1);
233  ids.clear();
234 
235  fps.clear();
236 
237  testGen.setEnabledIds(0x6); // 0110b, ID 3 disabled
238  testGen.setFireCount(1);
239 
240  sts = testGen.getNext(fps);
241 
242  TRACE_REQUIRE_EQUAL(sts, true);
243  TRACE_REQUIRE_EQUAL(fps.size(), 2u);
244  while (!fps.empty())
245  {
246  ids[fps.front()->fragmentID()]++;
247  TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 2);
248  TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 2);
249  fps.pop_front();
250  }
251  TRACE_REQUIRE_EQUAL(ids[1], 1);
252  TRACE_REQUIRE_EQUAL(ids[2], 1);
253  TRACE_REQUIRE_EQUAL(ids[3], 0);
254 
255  TLOG(TLVL_INFO) << "MultipleIDs test case END";
256 }
257 
258 BOOST_AUTO_TEST_CASE(HardwareFailure_NonThreaded)
259 {
260  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
261  TLOG(TLVL_INFO) << "HardwareFailure_NonThreaded test case BEGIN";
262  fhicl::ParameterSet ps;
263  ps.put<int>("board_id", 1);
264  ps.put<int>("fragment_id", 1);
265  ps.put<bool>("separate_data_thread", false);
266  ps.put<bool>("separate_monitoring_thread", false);
267  ps.put<int64_t>("hardware_poll_interval_us", 10);
268 
269  auto buffer = std::make_shared<artdaq::RequestBuffer>();
270  buffer->setRunning(true);
272  gen.SetRequestBuffer(buffer);
273  gen.StartCmd(1, 0xFFFFFFFF, 1);
274 
275  artdaq::FragmentPtrs fps;
276  auto sts = gen.getNext(fps);
277  TRACE_REQUIRE_EQUAL(sts, true);
278  TRACE_REQUIRE_EQUAL(fps.size(), 1u);
279  TRACE_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
280  TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
281  TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
282  fps.clear();
283 
284  gen.setFireCount(1);
285  gen.setHwFail();
286  usleep(10000);
287  sts = gen.getNext(fps);
288  TRACE_REQUIRE_EQUAL(sts, false);
289  TRACE_REQUIRE(fps.empty());
290 
291  gen.StopCmd(0xFFFFFFFF, 1);
292  gen.joinThreads();
293  TLOG(TLVL_INFO) << "HardwareFailure_NonThreaded test case END";
294 }
295 
296 BOOST_AUTO_TEST_CASE(HardwareFailure_Threaded)
297 {
298  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
299  TLOG(TLVL_INFO) << "HardwareFailure_Threaded test case BEGIN";
300  fhicl::ParameterSet ps;
301  ps.put<int>("board_id", 1);
302  ps.put<int>("fragment_id", 1);
303  ps.put<bool>("separate_monitoring_thread", true);
304  ps.put<int64_t>("hardware_poll_interval_us", 750000);
305 
306  auto buffer = std::make_shared<artdaq::RequestBuffer>();
307  buffer->setRunning(true);
309  gen.SetRequestBuffer(buffer);
310  gen.StartCmd(1, 0xFFFFFFFF, 1);
311 
312  artdaq::FragmentPtrs fps;
313  auto sts = gen.getNext(fps);
314  TRACE_REQUIRE_EQUAL(sts, true);
315  TRACE_REQUIRE_EQUAL(fps.size(), 1u);
316  TRACE_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
317  TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
318  TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
319  fps.clear();
320 
321  TLOG(TLVL_INFO) << "Setting failure bit";
322  gen.setHwFail();
323 
324  sleep(1);
325 
326  TLOG(TLVL_INFO) << "Checking that failure is reported by getNext";
327  gen.setFireCount(1);
328  sts = gen.getNext(fps);
329  TRACE_REQUIRE_EQUAL(sts, false);
330  TRACE_REQUIRE(fps.empty());
331 
332  gen.StopCmd(0xFFFFFFFF, 1);
333  gen.joinThreads();
334  TLOG(TLVL_INFO) << "HardwareFailure_Threaded test case END";
335 }
336 
337 BOOST_AUTO_TEST_SUITE_END()
bool getNext_(artdaq::FragmentPtrs &frags) override
Generate data and return it to CommandableFragmentGenerator.
void setEnabledIds(uint64_t bitmask)
Set the enabled IDs mask for the Fragment Generator.
CommandableFragmentGenerator derived class for testing.
void StopCmd(uint64_t timeout, uint64_t timestamp)
Stop the CommandableFragmentGenerator.
CommandableFragmentGeneratorTest(const fhicl::ParameterSet &ps)
CommandableFragmentGeneratorTest Constructor.
void StartCmd(int run, uint64_t timeout, uint64_t timestamp)
Start the CommandableFragmentGenerator.
bool getNext(FragmentPtrs &output) overridefinal
getNext calls either applyRequests or getNext_ to get any data that is ready to be sent to the EventB...
bool checkHWStatus_() override
Returns whether the hwFail flag has not been set.
void stopNoMutex() override
Perform immediate stop actions. No-Op.
void start() override
Perform start actions. No-Op.
CommandableFragmentGenerator is a FragmentGenerator-derived abstract class that defines the interface...
void resume() override
Perform resume actions. No-Op.
void pause() override
Perform pause actions. No-Op.
void setTimestamp(artdaq::Fragment::timestamp_t ts)
Set the timestamp to be used for the next Fragment.
artdaq::Fragment::timestamp_t getTimestamp()
Get the timestamp that will be used for the next Fragment.
void stop() override
Perform stop actions. No-Op.
void joinThreads()
Join any data-taking threads. Should be called when destructing CommandableFragmentGenerator.
void setFireCount(size_t count)
Have getNext_ generate count fragments.