artdaq  v3_12_02
CommandableFragmentGenerator_t.cc
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 
49 {
50 public:
54  explicit CommandableFragmentGeneratorTest(const fhicl::ParameterSet& ps);
55 
57 
58 private:
63 
64 protected:
72  bool getNext_(artdaq::FragmentPtrs& frags) override;
73 
78  bool checkHWStatus_() override { return !hwFail_.load(); }
79 
83  void start() override;
84 
88  void stopNoMutex() override;
89 
93  void stop() override;
94 
98  void pause() override;
99 
103  void resume() override;
104 
105 public:
110  void setFireCount(size_t count) { fireCount_ = count; }
111 
115  void setHwFail() { hwFail_ = true; }
116 
124  void setEnabledIds(uint64_t bitmask) { enabled_ids_ = bitmask; }
125 
130  void setTimestamp(artdaq::Fragment::timestamp_t ts) { ts_ = ts; }
131 
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 
147  : CommandableFragmentGenerator(ps)
148  , fireCount_(1)
149  , hwFail_(false)
150  , ts_(0)
151  , hw_stop_(false)
152  , enabled_ids_(-1)
153 {
154  metricMan->initialize(ps.get<fhicl::ParameterSet>("metrics", fhicl::ParameterSet()));
155  metricMan->do_start();
156 }
157 
159 {
160  while (fireCount_ > 0)
161  {
162  ++ts_;
163  for (auto& id : fragmentIDs())
164  {
165  if (id < 64 && ((enabled_ids_ & (0x1 << id)) != 0))
166  {
167  TLOG(TLVL_DEBUG) << "Adding Fragment with ID " << id << ", SeqID " << ev_counter() << ", and timestamp " << ts_;
168  frags.emplace_back(new artdaq::Fragment(ev_counter(), id, artdaq::Fragment::FirstUserFragmentType, ts_));
169  }
170  }
171  fireCount_--;
172  ev_counter_inc();
173  }
174 
175  return !hw_stop_;
176 }
177 
179 
181 
183 
185 
187 
188 BOOST_AUTO_TEST_SUITE(CommandableFragmentGenerator_t)
189 
190 BOOST_AUTO_TEST_CASE(Simple)
191 {
192  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
193  TLOG(TLVL_INFO) << "Simple test case BEGIN";
194  fhicl::ParameterSet ps;
195  ps.put<int>("board_id", 1);
196  ps.put<int>("fragment_id", 1);
198 
199  testGen.StartCmd(1, 1, 1);
200 
201  artdaq::FragmentPtrs fps;
202  auto sts = testGen.getNext(fps);
203  TRACE_REQUIRE_EQUAL(sts, true);
204  TRACE_REQUIRE_EQUAL(fps.size(), 1u);
205  TRACE_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
206  TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
207  TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
208  TLOG(TLVL_INFO) << "Simple test case END";
209 }
210 
211 BOOST_AUTO_TEST_CASE(WaitForStart)
212 {
213  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
214  TLOG(TLVL_INFO) << "WaitForStart test case BEGIN";
215  fhicl::ParameterSet ps;
216  ps.put<int>("board_id", 1);
217  ps.put<int>("fragment_id", 1);
219 
220  artdaq::FragmentPtrs fps;
221  auto sts = testGen.getNext(fps);
222  TRACE_REQUIRE_EQUAL(sts, false);
223  TRACE_REQUIRE_EQUAL(fps.size(), 0u);
224 
225  usleep(10000);
226  sts = testGen.getNext(fps);
227  TRACE_REQUIRE_EQUAL(sts, false);
228  TRACE_REQUIRE_EQUAL(fps.size(), 0u);
229 
230  testGen.StartCmd(2, 1, 1);
231 
232  sts = testGen.getNext(fps);
233  TRACE_REQUIRE_EQUAL(sts, true);
234  TRACE_REQUIRE_EQUAL(fps.size(), 1u);
235  TRACE_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
236  TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
237  TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
238  TLOG(TLVL_INFO) << "WaitForStart test case END";
239 }
240 
241 BOOST_AUTO_TEST_CASE(StateMachine)
242 {
243  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
244  TLOG(TLVL_INFO) << "StateMachine test case BEGIN";
245  fhicl::ParameterSet ps;
246  ps.put<int>("board_id", 1);
247  ps.put<int>("fragment_id", 1);
249 
250  artdaq::FragmentPtrs fps;
251  auto sts = testGen.getNext(fps);
252  TRACE_REQUIRE_EQUAL(sts, false);
253  TRACE_REQUIRE_EQUAL(fps.size(), 0u);
254 
255  usleep(10000);
256  sts = testGen.getNext(fps);
257  TRACE_REQUIRE_EQUAL(sts, false);
258  TRACE_REQUIRE_EQUAL(fps.size(), 0u);
259 
260  testGen.StartCmd(2, 1, 1);
261 
262  sts = testGen.getNext(fps);
263  TRACE_REQUIRE_EQUAL(sts, true);
264  TRACE_REQUIRE_EQUAL(fps.size(), 1u);
265  TRACE_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
266  TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
267  TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
268  fps.clear();
269 
270  testGen.setFireCount(1);
271  testGen.PauseCmd(1, 1);
272  sts = testGen.getNext(fps);
273  TRACE_REQUIRE_EQUAL(sts, false);
274  TRACE_REQUIRE_EQUAL(fps.size(), 0u);
275 
276  testGen.ResumeCmd(1, 1);
277 
278  sts = testGen.getNext(fps);
279  TRACE_REQUIRE_EQUAL(sts, true);
280  TRACE_REQUIRE_EQUAL(fps.size(), 1u);
281  TRACE_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
282  TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 2);
283  TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 2);
284  fps.clear();
285 
286  testGen.StopCmd(1, 1);
287  sts = testGen.getNext(fps);
288  TRACE_REQUIRE_EQUAL(sts, false);
289  TRACE_REQUIRE_EQUAL(fps.size(), 0u);
290 
291  testGen.StartCmd(2, 1, 1);
292  sts = testGen.getNext(fps);
293  TRACE_REQUIRE_EQUAL(sts, true);
294  TRACE_REQUIRE_EQUAL(fps.size(), 0u);
295 
296  testGen.setFireCount(1);
297  sts = testGen.getNext(fps);
298  TRACE_REQUIRE_EQUAL(sts, true);
299  TRACE_REQUIRE_EQUAL(fps.size(), 1u);
300  TRACE_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
301  TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 3);
302  TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
303  fps.clear();
304 
305  TLOG(TLVL_INFO) << "StateMachine test case END";
306 }
307 
308 BOOST_AUTO_TEST_CASE(MultipleIDs)
309 {
310  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
311  TLOG(TLVL_INFO) << "MultipleIDs test case BEGIN";
312  fhicl::ParameterSet ps;
313  ps.put<int>("board_id", 1);
314  ps.put<std::vector<int>>("fragment_ids", {1, 2, 3});
315  ps.put<int>("generated_fragments_per_event", 3);
316 
318  testGen.StartCmd(3, 1, 1);
319 
320  artdaq::FragmentPtrs fps;
321  auto sts = testGen.getNext(fps);
322 
323  std::map<artdaq::Fragment::fragment_id_t, size_t> ids;
324  TRACE_REQUIRE_EQUAL(sts, true);
325  TRACE_REQUIRE_EQUAL(fps.size(), 3u);
326  while (fps.size() > 0)
327  {
328  ids[fps.front()->fragmentID()]++;
329  TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
330  TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
331  fps.pop_front();
332  }
333 
334  TRACE_REQUIRE_EQUAL(ids[1], 1);
335  TRACE_REQUIRE_EQUAL(ids[2], 1);
336  TRACE_REQUIRE_EQUAL(ids[3], 1);
337  ids.clear();
338 
339  fps.clear();
340 
341  testGen.setEnabledIds(0x6); // 0110b, ID 3 disabled
342  testGen.setFireCount(1);
343 
344  sts = testGen.getNext(fps);
345 
346  TRACE_REQUIRE_EQUAL(sts, true);
347  TRACE_REQUIRE_EQUAL(fps.size(), 2u);
348  while (!fps.empty())
349  {
350  ids[fps.front()->fragmentID()]++;
351  TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 2);
352  TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 2);
353  fps.pop_front();
354  }
355  TRACE_REQUIRE_EQUAL(ids[1], 1);
356  TRACE_REQUIRE_EQUAL(ids[2], 1);
357  TRACE_REQUIRE_EQUAL(ids[3], 0);
358 
359  TLOG(TLVL_INFO) << "MultipleIDs test case END";
360 }
361 
362 BOOST_AUTO_TEST_CASE(HardwareFailure_NonThreaded)
363 {
364  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
365  TLOG(TLVL_INFO) << "HardwareFailure_NonThreaded test case BEGIN";
366  fhicl::ParameterSet ps;
367  ps.put<int>("board_id", 1);
368  ps.put<int>("fragment_id", 1);
369  ps.put<bool>("separate_data_thread", false);
370  ps.put<bool>("separate_monitoring_thread", false);
371  ps.put<int64_t>("hardware_poll_interval_us", 10);
372 
373  auto buffer = std::make_shared<artdaq::RequestBuffer>();
374  buffer->setRunning(true);
376  gen.SetRequestBuffer(buffer);
377  gen.StartCmd(4, 0xFFFFFFFF, 1);
378 
379  artdaq::FragmentPtrs fps;
380  auto sts = gen.getNext(fps);
381  TRACE_REQUIRE_EQUAL(sts, true);
382  TRACE_REQUIRE_EQUAL(fps.size(), 1u);
383  TRACE_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
384  TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
385  TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
386  fps.clear();
387 
388  gen.setFireCount(1);
389  gen.setHwFail();
390  usleep(10000);
391  sts = gen.getNext(fps);
392  TRACE_REQUIRE_EQUAL(sts, false);
393  TRACE_REQUIRE(fps.empty());
394 
395  gen.StopCmd(0xFFFFFFFF, 1);
396  gen.joinThreads();
397  TLOG(TLVL_INFO) << "HardwareFailure_NonThreaded test case END";
398 }
399 
400 BOOST_AUTO_TEST_CASE(HardwareFailure_Threaded)
401 {
402  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
403  TLOG(TLVL_INFO) << "HardwareFailure_Threaded test case BEGIN";
404  fhicl::ParameterSet ps;
405  ps.put<int>("board_id", 1);
406  ps.put<int>("fragment_id", 1);
407  ps.put<bool>("separate_monitoring_thread", true);
408  ps.put<int64_t>("hardware_poll_interval_us", 750000);
409 
410  auto buffer = std::make_shared<artdaq::RequestBuffer>();
411  buffer->setRunning(true);
413  gen.SetRequestBuffer(buffer);
414  gen.StartCmd(5, 0xFFFFFFFF, 1);
415 
416  artdaq::FragmentPtrs fps;
417  auto sts = gen.getNext(fps);
418  TRACE_REQUIRE_EQUAL(sts, true);
419  TRACE_REQUIRE_EQUAL(fps.size(), 1u);
420  TRACE_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
421  TRACE_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
422  TRACE_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
423  fps.clear();
424 
425  TLOG(TLVL_INFO) << "Setting failure bit";
426  gen.setHwFail();
427 
428  sleep(1);
429 
430  TLOG(TLVL_INFO) << "Checking that failure is reported by getNext";
431  gen.setFireCount(1);
432  sts = gen.getNext(fps);
433  TRACE_REQUIRE_EQUAL(sts, false);
434  TRACE_REQUIRE(fps.empty());
435 
436  gen.StopCmd(0xFFFFFFFF, 1);
437  gen.joinThreads();
438  TLOG(TLVL_INFO) << "HardwareFailure_Threaded test case END";
439 }
440 
441 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.