artdaq  v3_11_00
CommandableFragmentGenerator_t.cc
1 #define TRACE_NAME "CommandableFragmentGenerator_t"
2 
3 #define BOOST_TEST_MODULE CommandableFragmentGenerator_t
4 #include <boost/test/unit_test.hpp>
5 
6 #include "artdaq-core/Data/ContainerFragment.hh"
7 #include "artdaq-core/Data/Fragment.hh"
8 #include "artdaq/Generators/CommandableFragmentGenerator.hh"
9 
10 #define TRACE_REQUIRE_EQUAL(l, r) \
11  do \
12  { \
13  if ((l) == (r)) \
14  { \
15  TLOG(TLVL_DEBUG) << __LINE__ << ": Checking if " << #l << " (" << (l) << ") equals " << #r << " (" << (r) << ")...YES!"; \
16  } \
17  else \
18  { \
19  TLOG(TLVL_ERROR) << __LINE__ << ": Checking if " << #l << " (" << (l) << ") equals " << #r << " (" << (r) << ")...NO!"; \
20  } \
21  BOOST_REQUIRE_EQUAL((l), (r)); \
22  } while (false)
23 
24 #define TRACE_REQUIRE(b) \
25  do \
26  { \
27  if (b) \
28  { \
29  TLOG(TLVL_DEBUG) << __LINE__ << ": Checking if " << #b << " (" << (b) << ") is true...YES!"; \
30  } \
31  else \
32  { \
33  TLOG(TLVL_ERROR) << __LINE__ << ": Checking if " << #b << " (" << (b) << ") is true...NO!"; \
34  } \
35  BOOST_REQUIRE((b)); \
36  } while (false)
37 
38 namespace artdaqtest {
39 class CommandableFragmentGeneratorTest;
40 }
41 
46 {
47 public:
51  explicit CommandableFragmentGeneratorTest(const fhicl::ParameterSet& ps);
52 
54 
55 private:
60 
61 protected:
69  bool getNext_(artdaq::FragmentPtrs& frags) override;
70 
75  bool checkHWStatus_() override { return !hwFail_.load(); }
76 
80  void start() override;
81 
85  void stopNoMutex() override;
86 
90  void stop() override;
91 
95  void pause() override;
96 
100  void resume() override;
101 
102 public:
107  void setFireCount(size_t count) { fireCount_ = count; }
108 
112  void setHwFail() { hwFail_ = true; }
113 
121  void setEnabledIds(uint64_t bitmask) { enabled_ids_ = bitmask; }
122 
127  void setTimestamp(artdaq::Fragment::timestamp_t ts) { ts_ = ts; }
128 
133  artdaq::Fragment::timestamp_t getTimestamp() { return ts_; }
134 
135 private:
136  std::atomic<size_t> fireCount_;
137  std::atomic<bool> hwFail_;
138  artdaq::Fragment::timestamp_t ts_;
139  std::atomic<bool> hw_stop_;
140  std::atomic<uint64_t> enabled_ids_;
141 };
142 
144  : CommandableFragmentGenerator(ps)
145  , fireCount_(1)
146  , hwFail_(false)
147  , ts_(0)
148  , hw_stop_(false)
149  , enabled_ids_(-1)
150 {
151  metricMan->initialize(ps.get<fhicl::ParameterSet>("metrics", fhicl::ParameterSet()));
152  metricMan->do_start();
153 }
154 
156 {
157  while (fireCount_ > 0)
158  {
159  ++ts_;
160  for (auto& id : fragmentIDs())
161  {
162  if (id < 64 && ((enabled_ids_ & (0x1 << id)) != 0))
163  {
164  TLOG(TLVL_DEBUG) << "Adding Fragment with ID " << id << ", SeqID " << ev_counter() << ", and timestamp " << ts_;
165  frags.emplace_back(new artdaq::Fragment(ev_counter(), id, artdaq::Fragment::FirstUserFragmentType, ts_));
166  }
167  }
168  fireCount_--;
169  ev_counter_inc();
170  }
171 
172  return !hw_stop_;
173 }
174 
176 
178 
180 
182 
184 
185 BOOST_AUTO_TEST_SUITE(CommandableFragmentGenerator_t)
186 
187 BOOST_AUTO_TEST_CASE(Simple)
188 {
189  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
190  TLOG(TLVL_INFO) << "Simple test case BEGIN";
191  fhicl::ParameterSet ps;
192  ps.put<int>("board_id", 1);
193  ps.put<int>("fragment_id", 1);
195 
196  testGen.StartCmd(1, 1, 1);
197 
198  artdaq::FragmentPtrs fps;
199  auto sts = testGen.getNext(fps);
200  TRACE_REQUIRE_EQUAL(sts, true);
201  TRACE_REQUIRE_EQUAL(fps.size(), 1u);
202  TRACE_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
203  TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
204  TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
205  TLOG(TLVL_INFO) << "Simple test case END";
206 }
207 
208 BOOST_AUTO_TEST_CASE(WaitForStart)
209 {
210  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
211  TLOG(TLVL_INFO) << "WaitForStart test case BEGIN";
212  fhicl::ParameterSet ps;
213  ps.put<int>("board_id", 1);
214  ps.put<int>("fragment_id", 1);
216 
217  artdaq::FragmentPtrs fps;
218  auto sts = testGen.getNext(fps);
219  TRACE_REQUIRE_EQUAL(sts, false);
220  TRACE_REQUIRE_EQUAL(fps.size(), 0u);
221 
222  usleep(10000);
223  sts = testGen.getNext(fps);
224  TRACE_REQUIRE_EQUAL(sts, false);
225  TRACE_REQUIRE_EQUAL(fps.size(), 0u);
226 
227  testGen.StartCmd(2, 1, 1);
228 
229  sts = testGen.getNext(fps);
230  TRACE_REQUIRE_EQUAL(sts, true);
231  TRACE_REQUIRE_EQUAL(fps.size(), 1u);
232  TRACE_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
233  TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
234  TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
235  TLOG(TLVL_INFO) << "WaitForStart test case END";
236 }
237 
238 BOOST_AUTO_TEST_CASE(StateMachine)
239 {
240  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
241  TLOG(TLVL_INFO) << "StateMachine test case BEGIN";
242  fhicl::ParameterSet ps;
243  ps.put<int>("board_id", 1);
244  ps.put<int>("fragment_id", 1);
246 
247  artdaq::FragmentPtrs fps;
248  auto sts = testGen.getNext(fps);
249  TRACE_REQUIRE_EQUAL(sts, false);
250  TRACE_REQUIRE_EQUAL(fps.size(), 0u);
251 
252  usleep(10000);
253  sts = testGen.getNext(fps);
254  TRACE_REQUIRE_EQUAL(sts, false);
255  TRACE_REQUIRE_EQUAL(fps.size(), 0u);
256 
257  testGen.StartCmd(2, 1, 1);
258 
259  sts = testGen.getNext(fps);
260  TRACE_REQUIRE_EQUAL(sts, true);
261  TRACE_REQUIRE_EQUAL(fps.size(), 1u);
262  TRACE_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
263  TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
264  TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
265  fps.clear();
266 
267  testGen.setFireCount(1);
268  testGen.PauseCmd(1, 1);
269  sts = testGen.getNext(fps);
270  TRACE_REQUIRE_EQUAL(sts, false);
271  TRACE_REQUIRE_EQUAL(fps.size(), 0u);
272 
273  testGen.ResumeCmd(1, 1);
274 
275  sts = testGen.getNext(fps);
276  TRACE_REQUIRE_EQUAL(sts, true);
277  TRACE_REQUIRE_EQUAL(fps.size(), 1u);
278  TRACE_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
279  TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 2);
280  TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 2);
281  fps.clear();
282 
283  testGen.StopCmd(1, 1);
284  sts = testGen.getNext(fps);
285  TRACE_REQUIRE_EQUAL(sts, false);
286  TRACE_REQUIRE_EQUAL(fps.size(), 0u);
287 
288  testGen.StartCmd(2, 1, 1);
289  sts = testGen.getNext(fps);
290  TRACE_REQUIRE_EQUAL(sts, true);
291  TRACE_REQUIRE_EQUAL(fps.size(), 0u);
292 
293  testGen.setFireCount(1);
294  sts = testGen.getNext(fps);
295  TRACE_REQUIRE_EQUAL(sts, true);
296  TRACE_REQUIRE_EQUAL(fps.size(), 1u);
297  TRACE_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
298  TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 3);
299  TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
300  fps.clear();
301 
302  TLOG(TLVL_INFO) << "StateMachine test case END";
303 }
304 
305 BOOST_AUTO_TEST_CASE(MultipleIDs)
306 {
307  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
308  TLOG(TLVL_INFO) << "MultipleIDs test case BEGIN";
309  fhicl::ParameterSet ps;
310  ps.put<int>("board_id", 1);
311  ps.put<std::vector<int>>("fragment_ids", {1, 2, 3});
312  ps.put<int>("generated_fragments_per_event", 3);
313 
315  testGen.StartCmd(3, 1, 1);
316 
317  artdaq::FragmentPtrs fps;
318  auto sts = testGen.getNext(fps);
319 
320  std::map<artdaq::Fragment::fragment_id_t, size_t> ids;
321  TRACE_REQUIRE_EQUAL(sts, true);
322  TRACE_REQUIRE_EQUAL(fps.size(), 3u);
323  while (fps.size() > 0)
324  {
325  ids[fps.front()->fragmentID()]++;
326  TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
327  TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
328  fps.pop_front();
329  }
330 
331  TRACE_REQUIRE_EQUAL(ids[1], 1);
332  TRACE_REQUIRE_EQUAL(ids[2], 1);
333  TRACE_REQUIRE_EQUAL(ids[3], 1);
334  ids.clear();
335 
336  fps.clear();
337 
338  testGen.setEnabledIds(0x6); // 0110b, ID 3 disabled
339  testGen.setFireCount(1);
340 
341  sts = testGen.getNext(fps);
342 
343  TRACE_REQUIRE_EQUAL(sts, true);
344  TRACE_REQUIRE_EQUAL(fps.size(), 2u);
345  while (!fps.empty())
346  {
347  ids[fps.front()->fragmentID()]++;
348  TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 2);
349  TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 2);
350  fps.pop_front();
351  }
352  TRACE_REQUIRE_EQUAL(ids[1], 1);
353  TRACE_REQUIRE_EQUAL(ids[2], 1);
354  TRACE_REQUIRE_EQUAL(ids[3], 0);
355 
356  TLOG(TLVL_INFO) << "MultipleIDs test case END";
357 }
358 
359 BOOST_AUTO_TEST_CASE(HardwareFailure_NonThreaded)
360 {
361  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
362  TLOG(TLVL_INFO) << "HardwareFailure_NonThreaded test case BEGIN";
363  fhicl::ParameterSet ps;
364  ps.put<int>("board_id", 1);
365  ps.put<int>("fragment_id", 1);
366  ps.put<bool>("separate_data_thread", false);
367  ps.put<bool>("separate_monitoring_thread", false);
368  ps.put<int64_t>("hardware_poll_interval_us", 10);
369 
370  auto buffer = std::make_shared<artdaq::RequestBuffer>();
371  buffer->setRunning(true);
373  gen.SetRequestBuffer(buffer);
374  gen.StartCmd(4, 0xFFFFFFFF, 1);
375 
376  artdaq::FragmentPtrs fps;
377  auto sts = gen.getNext(fps);
378  TRACE_REQUIRE_EQUAL(sts, true);
379  TRACE_REQUIRE_EQUAL(fps.size(), 1u);
380  TRACE_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
381  TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
382  TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
383  fps.clear();
384 
385  gen.setFireCount(1);
386  gen.setHwFail();
387  usleep(10000);
388  sts = gen.getNext(fps);
389  TRACE_REQUIRE_EQUAL(sts, false);
390  TRACE_REQUIRE(fps.empty());
391 
392  gen.StopCmd(0xFFFFFFFF, 1);
393  gen.joinThreads();
394  TLOG(TLVL_INFO) << "HardwareFailure_NonThreaded test case END";
395 }
396 
397 BOOST_AUTO_TEST_CASE(HardwareFailure_Threaded)
398 {
399  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
400  TLOG(TLVL_INFO) << "HardwareFailure_Threaded test case BEGIN";
401  fhicl::ParameterSet ps;
402  ps.put<int>("board_id", 1);
403  ps.put<int>("fragment_id", 1);
404  ps.put<bool>("separate_monitoring_thread", true);
405  ps.put<int64_t>("hardware_poll_interval_us", 750000);
406 
407  auto buffer = std::make_shared<artdaq::RequestBuffer>();
408  buffer->setRunning(true);
410  gen.SetRequestBuffer(buffer);
411  gen.StartCmd(5, 0xFFFFFFFF, 1);
412 
413  artdaq::FragmentPtrs fps;
414  auto sts = gen.getNext(fps);
415  TRACE_REQUIRE_EQUAL(sts, true);
416  TRACE_REQUIRE_EQUAL(fps.size(), 1u);
417  TRACE_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
418  TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
419  TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
420  fps.clear();
421 
422  TLOG(TLVL_INFO) << "Setting failure bit";
423  gen.setHwFail();
424 
425  sleep(1);
426 
427  TLOG(TLVL_INFO) << "Checking that failure is reported by getNext";
428  gen.setFireCount(1);
429  sts = gen.getNext(fps);
430  TRACE_REQUIRE_EQUAL(sts, false);
431  TRACE_REQUIRE(fps.empty());
432 
433  gen.StopCmd(0xFFFFFFFF, 1);
434  gen.joinThreads();
435  TLOG(TLVL_INFO) << "HardwareFailure_Threaded test case END";
436 }
437 
438 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 SetRequestBuffer(std::shared_ptr< RequestBuffer > buffer)
Set the shared_ptr to the RequestBuffer.
void joinThreads()
Join any data-taking threads. Should be called when destructing CommandableFragmentGenerator.
void setFireCount(size_t count)
Have getNext_ generate count fragments.