artdaq  v3_03_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/Fragment.hh"
7 #include "artdaq-core/Data/ContainerFragment.hh"
8 #include "artdaq/Application/CommandableFragmentGenerator.hh"
9 #include "artdaq/DAQrate/RequestSender.hh"
10 
11 #define MULTICAST_MODE 0
12 
13 namespace artdaqtest
14 {
15  class CommandableFragmentGeneratorTest;
16 }
17 
23 {
24 public:
28  explicit CommandableFragmentGeneratorTest(const fhicl::ParameterSet& ps);
29 
31 
32 protected:
40  bool getNext_(artdaq::FragmentPtrs& frags) override;
41 
46  bool checkHWStatus_() override { return !hwFail_.load(); }
47 
51  void start() override;
52 
56  void stopNoMutex() override;
57 
61  void stop() override;
62 
66  void pause() override;
67 
71  void resume() override;
72 
73 public:
78  void setFireCount(size_t count) { fireCount_ = count; }
79 
83  void setHwFail() { hwFail_ = true; }
84 
88  void waitForFrags() {
89  auto start_time = std::chrono::steady_clock::now();
90  while (fireCount_ > 0) { usleep(1000); }
91  TLOG(TLVL_INFO) << "Waited " << std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - start_time).count() << " us for events to be picked up by CFG" ;
92  }
93 private:
94  std::atomic<size_t> fireCount_;
95  std::atomic<bool> hwFail_;
96  artdaq::Fragment::timestamp_t ts_;
97  std::atomic<bool> hw_stop_;
98 };
99 
101  : CommandableFragmentGenerator(ps)
102  , fireCount_(1)
103  , hwFail_(false)
104  , ts_(0)
105  , hw_stop_(false)
106 {
107  metricMan->initialize(ps);
108  metricMan->do_start();
109 }
110 
111 bool
113 {
114  while (fireCount_ > 0)
115  {
116  frags.emplace_back(new artdaq::Fragment(ev_counter(), fragment_id(), artdaq::Fragment::FirstUserFragmentType, ++ts_));
117  fireCount_--;
118  }
119 
120  return !hw_stop_;
121 }
122 
123 void
125 
126 void
128 
129 void
131 
132 void
134 
135 void
137 
138 BOOST_AUTO_TEST_SUITE(CommandableFragmentGenerator_t)
139 
140 BOOST_AUTO_TEST_CASE(Simple)
141 {
142  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
143  TLOG(TLVL_INFO) << "Simple test case BEGIN" ;
144  fhicl::ParameterSet ps;
145  ps.put<int>("board_id", 1);
146  ps.put<int>("fragment_id", 1);
148  artdaq::FragmentPtrs fps;
149  auto sts = testGen.getNext(fps);
150  BOOST_REQUIRE_EQUAL(sts, true);
151  BOOST_REQUIRE_EQUAL(fps.size(), 1u);
152  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
153  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
154  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
155  TLOG(TLVL_INFO) << "Simple test case END" ;
156 }
157 
158 BOOST_AUTO_TEST_CASE(IgnoreRequests)
159 {
160  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
161  TLOG(TLVL_INFO) << "IgnoreRequests test case BEGIN" ;
162  const int REQUEST_PORT = (seedAndRandom() % (32768 - 1024)) + 1024;
163  const int DELAY_TIME = 1;
164  fhicl::ParameterSet ps;
165  ps.put<int>("board_id", 1);
166  ps.put<int>("fragment_id", 1);
167  ps.put<int>("request_port", REQUEST_PORT);
168 #if MULTICAST_MODE
169  ps.put<std::string>("request_address", "227.18.12.29");
170 #else
171  ps.put<std::string>("request_address", "localhost");
172 #endif
173  ps.put<artdaq::Fragment::timestamp_t>("request_window_offset", 0);
174  ps.put<artdaq::Fragment::timestamp_t>("request_window_width", 0);
175  ps.put<bool>("separate_data_thread", true);
176  ps.put<bool>("separate_monitoring_thread", false);
177  ps.put<int64_t>("hardware_poll_interval_us", 0);
178  ps.put<std::string>("request_mode", "ignored");
179  ps.put("request_delay_ms", DELAY_TIME);
180  ps.put("send_requests", true);
181 
182  artdaq::RequestSender t(ps);
184  gen.StartCmd(1, 0xFFFFFFFF, 1);
185  t.AddRequest(53, 35);
186 
187  artdaq::FragmentPtrs fps;
188  auto sts = gen.getNext(fps);
189  BOOST_REQUIRE_EQUAL(sts, true);
190  BOOST_REQUIRE_EQUAL(fps.size(), 1u);
191  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
192  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
193  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
194  gen.StopCmd(0xFFFFFFFF, 1);
195  gen.joinThreads();
196  TLOG(TLVL_INFO) << "IgnoreRequests test case END" ;
197 }
198 
199 BOOST_AUTO_TEST_CASE(SingleMode)
200 {
201  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
202  TLOG(TLVL_INFO) << "SingleMode test case BEGIN" ;
203  const int REQUEST_PORT = (seedAndRandom() % (32768 - 1024)) + 1024;
204  const int DELAY_TIME = 100;
205  fhicl::ParameterSet ps;
206  ps.put<int>("board_id", 1);
207  ps.put<int>("fragment_id", 1);
208  ps.put<int>("request_port", REQUEST_PORT);
209 #if MULTICAST_MODE
210  ps.put<std::string>("request_address", "227.18.12.30");
211 #else
212  ps.put<std::string>("request_address", "localhost");
213 #endif
214  ps.put<artdaq::Fragment::timestamp_t>("request_window_offset", 0);
215  ps.put<artdaq::Fragment::timestamp_t>("request_window_width", 0);
216  ps.put<bool>("separate_data_thread", true);
217  ps.put<bool>("separate_monitoring_thread", false);
218  ps.put<int64_t>("hardware_poll_interval_us", 0);
219  ps.put<std::string>("request_mode", "single");
220  ps.put("request_delay_ms", DELAY_TIME);
221  ps.put("send_requests", true);
222 
223  artdaq::RequestSender t(ps);
224  t.AddRequest(1, 1);
225 
227  gen.StartCmd(1, 0xFFFFFFFF, 1);
228  gen.waitForFrags();
229  BOOST_REQUIRE_EQUAL(gen.ev_counter(), 1);
230 
231  artdaq::FragmentPtrs fps;
232  auto sts = gen.getNext(fps);
233  auto type = artdaq::Fragment::FirstUserFragmentType;
234  BOOST_REQUIRE_EQUAL(sts, true);
235  BOOST_REQUIRE_EQUAL(fps.size(), 1u);
236  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
237  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
238  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
239  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
240  BOOST_REQUIRE_EQUAL(gen.ev_counter(), 2);
241  fps.clear();
242 
243  t.AddRequest(2, 5);
244  sts = gen.getNext(fps);
245  BOOST_REQUIRE_EQUAL(sts, true);
246  BOOST_REQUIRE_EQUAL(fps.size(), 1u);
247  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
248  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 5);
249  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 2);
250  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
251  BOOST_REQUIRE_EQUAL(gen.ev_counter(), 3);
252  fps.clear();
253 
254  gen.setFireCount(2);
255  gen.waitForFrags();
256  t.AddRequest(4, 7);
257  sts = gen.getNext(fps);
258  BOOST_REQUIRE_EQUAL(gen.ev_counter(), 5);
259  BOOST_REQUIRE_EQUAL(sts, true);
260  BOOST_REQUIRE_EQUAL(fps.size(), 2);
261  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
262  auto ts = artdaq::Fragment::InvalidTimestamp;
263  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), ts);
264  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 3);
265  auto emptyType = artdaq::Fragment::EmptyFragmentType;
266  BOOST_REQUIRE_EQUAL(fps.front()->type(), emptyType);
267  fps.pop_front();
268  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
269  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 7);
270  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 4);
271  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
272  fps.clear();
273 
274  gen.StopCmd(0xFFFFFFFF, 1);
275  gen.joinThreads();
276  TLOG(TLVL_INFO) << "SingleMode test case END" ;
277 }
278 
279 BOOST_AUTO_TEST_CASE(BufferMode)
280 {
281  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
282  TLOG(TLVL_INFO) << "BufferMode test case BEGIN" ;
283  const int REQUEST_PORT = (seedAndRandom() % (32768 - 1024)) + 1024;
284  const int DELAY_TIME = 100;
285  fhicl::ParameterSet ps;
286  ps.put<int>("board_id", 1);
287  ps.put<int>("fragment_id", 1);
288  ps.put<int>("request_port", REQUEST_PORT);
289 #if MULTICAST_MODE
290  ps.put<std::string>("request_address", "227.18.12.31");
291 #else
292  ps.put<std::string>("request_address", "localhost");
293 #endif
294  ps.put<artdaq::Fragment::timestamp_t>("request_window_offset", 0);
295  ps.put<artdaq::Fragment::timestamp_t>("request_window_width", 0);
296  ps.put<bool>("separate_data_thread", true);
297  ps.put<bool>("separate_monitoring_thread", false);
298  ps.put<int64_t>("hardware_poll_interval_us", 0);
299  ps.put<std::string>("request_mode", "buffer");
300  ps.put("request_delay_ms", DELAY_TIME);
301  ps.put("send_requests", true);
302 
303  artdaq::RequestSender t(ps);
304  t.AddRequest(1, 1);
305 
307  gen.StartCmd(1, 0xFFFFFFFF, 1);
308  BOOST_REQUIRE_EQUAL(gen.ev_counter(), 1);
309 
310 
311  artdaq::FragmentPtrs fps;
312  auto sts = gen.getNext(fps);
313  BOOST_REQUIRE_EQUAL(sts, true);
314  BOOST_REQUIRE_EQUAL(fps.size(), 1u);
315  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
316  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
317  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
318  auto type = artdaq::Fragment::ContainerFragmentType;
319  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
320  BOOST_REQUIRE_GE(fps.front()->sizeBytes(), 2 * sizeof(artdaq::detail::RawFragmentHeader) + sizeof(artdaq::ContainerFragment::Metadata));
321  auto cf = artdaq::ContainerFragment(*fps.front());
322  BOOST_REQUIRE_EQUAL(cf.block_count(), 1);
323  BOOST_REQUIRE_EQUAL(cf.missing_data(), false);
324  type = artdaq::Fragment::FirstUserFragmentType;
325  BOOST_REQUIRE_EQUAL(cf.fragment_type(), type);
326  BOOST_REQUIRE_EQUAL(gen.ev_counter(), 2);
327  fps.clear();
328 
329  t.AddRequest(2, 5);
330  sts = gen.getNext(fps);
331  BOOST_REQUIRE_EQUAL(sts, true);
332  BOOST_REQUIRE_EQUAL(fps.size(), 1u);
333  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
334  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 5);
335  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 2);
336  type = artdaq::Fragment::ContainerFragmentType;
337  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
338  auto cf2 = artdaq::ContainerFragment(*fps.front());
339  BOOST_REQUIRE_EQUAL(cf2.block_count(), 0);
340  BOOST_REQUIRE_EQUAL(cf2.missing_data(), false);
341  type = artdaq::Fragment::EmptyFragmentType;
342  BOOST_REQUIRE_EQUAL(cf2.fragment_type(), type);
343  BOOST_REQUIRE_EQUAL(gen.ev_counter(), 3);
344  fps.clear();
345 
346  gen.setFireCount(2);
347  gen.waitForFrags();
348  t.AddRequest(4, 7);
349  sts = gen.getNext(fps);
350  BOOST_REQUIRE_EQUAL(sts, true);
351  BOOST_REQUIRE_EQUAL(fps.size(), 2);
352 
353  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
354  auto ts = artdaq::Fragment::InvalidTimestamp;
355  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), ts);
356  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 3);
357  auto emptyType = artdaq::Fragment::EmptyFragmentType;
358  BOOST_REQUIRE_EQUAL(fps.front()->type(), emptyType);
359  BOOST_REQUIRE_EQUAL(fps.front()->size(), artdaq::detail::RawFragmentHeader::num_words());
360  fps.pop_front();
361  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
362  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 7);
363  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 4);
364  type = artdaq::Fragment::ContainerFragmentType;
365  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
366  auto cf3 = artdaq::ContainerFragment(*fps.front());
367  BOOST_REQUIRE_EQUAL(cf3.block_count(), 2);
368  BOOST_REQUIRE_EQUAL(cf3.missing_data(), false);
369  type = artdaq::Fragment::FirstUserFragmentType;
370  BOOST_REQUIRE_EQUAL(cf3.fragment_type(), type);
371  fps.clear();
372  BOOST_REQUIRE_EQUAL(gen.ev_counter(), 5);
373 
374 
375  gen.StopCmd(0xFFFFFFFF, 1);
376  gen.joinThreads();
377 
378 
379  TLOG(TLVL_INFO) << "BufferMode test case END" ;
380 }
381 
382 BOOST_AUTO_TEST_CASE(CircularBufferMode)
383 {
384  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
385  TLOG(TLVL_INFO) << "CircularBufferMode test case BEGIN";
386  const int REQUEST_PORT = (seedAndRandom() % (32768 - 1024)) + 1024;
387  const int DELAY_TIME = 100;
388  fhicl::ParameterSet ps;
389  ps.put<int>("board_id", 1);
390  ps.put<int>("fragment_id", 1);
391  ps.put<int>("request_port", REQUEST_PORT);
392 #if MULTICAST_MODE
393  ps.put<std::string>("request_address", "227.18.12.31");
394 #else
395  ps.put<std::string>("request_address", "localhost");
396 #endif
397  ps.put<artdaq::Fragment::timestamp_t>("request_window_offset", 0);
398  ps.put<artdaq::Fragment::timestamp_t>("request_window_width", 0);
399  ps.put<bool>("separate_data_thread", true);
400  ps.put<bool>("circular_buffer_mode", true);
401  ps.put<int>("data_buffer_depth_fragments", 3);
402  ps.put<bool>("separate_monitoring_thread", false);
403  ps.put<int64_t>("hardware_poll_interval_us", 0);
404  ps.put<std::string>("request_mode", "buffer");
405  ps.put("request_delay_ms", DELAY_TIME);
406  ps.put("send_requests", true);
407 
408  artdaq::RequestSender t(ps);
409  t.AddRequest(1, 1);
410 
412  gen.StartCmd(1, 0xFFFFFFFF, 1);
413  BOOST_REQUIRE_EQUAL(gen.ev_counter(), 1);
414 
415 
416  artdaq::FragmentPtrs fps;
417  auto sts = gen.getNext(fps);
418  BOOST_REQUIRE_EQUAL(sts, true);
419  BOOST_REQUIRE_EQUAL(fps.size(), 1u);
420  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
421  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
422  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
423  auto type = artdaq::Fragment::ContainerFragmentType;
424  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
425  BOOST_REQUIRE_GE(fps.front()->sizeBytes(), 2 * sizeof(artdaq::detail::RawFragmentHeader) + sizeof(artdaq::ContainerFragment::Metadata));
426  auto cf = artdaq::ContainerFragment(*fps.front());
427  BOOST_REQUIRE_EQUAL(cf.block_count(), 1);
428  BOOST_REQUIRE_EQUAL(cf.missing_data(), false);
429  type = artdaq::Fragment::FirstUserFragmentType;
430  BOOST_REQUIRE_EQUAL(cf.fragment_type(), type);
431  BOOST_REQUIRE_EQUAL(gen.ev_counter(), 2);
432  fps.clear();
433 
434  t.AddRequest(2, 5);
435  sts = gen.getNext(fps);
436  BOOST_REQUIRE_EQUAL(sts, true);
437  BOOST_REQUIRE_EQUAL(fps.size(), 1u);
438  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
439  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 5);
440  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 2);
441  type = artdaq::Fragment::ContainerFragmentType;
442  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
443  auto cf2 = artdaq::ContainerFragment(*fps.front());
444  BOOST_REQUIRE_EQUAL(cf2.block_count(), 0);
445  BOOST_REQUIRE_EQUAL(cf2.missing_data(), false);
446  type = artdaq::Fragment::EmptyFragmentType;
447  BOOST_REQUIRE_EQUAL(cf2.fragment_type(), type);
448  BOOST_REQUIRE_EQUAL(gen.ev_counter(), 3);
449  fps.clear();
450 
451  gen.setFireCount(3);
452  gen.waitForFrags();
453  t.AddRequest(4, 7);
454  sts = gen.getNext(fps);
455  BOOST_REQUIRE_EQUAL(sts, true);
456  BOOST_REQUIRE_EQUAL(fps.size(), 2);
457 
458  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
459  auto ts = artdaq::Fragment::InvalidTimestamp;
460  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), ts);
461  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 3);
462  auto emptyType = artdaq::Fragment::EmptyFragmentType;
463  BOOST_REQUIRE_EQUAL(fps.front()->type(), emptyType);
464  BOOST_REQUIRE_EQUAL(fps.front()->size(), artdaq::detail::RawFragmentHeader::num_words());
465  fps.pop_front();
466  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
467  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 7);
468  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 4);
469  type = artdaq::Fragment::ContainerFragmentType;
470  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
471  auto cf3 = artdaq::ContainerFragment(*fps.front());
472  BOOST_REQUIRE_EQUAL(cf3.block_count(), 3);
473  BOOST_REQUIRE_EQUAL(cf3.missing_data(), false);
474  type = artdaq::Fragment::FirstUserFragmentType;
475  BOOST_REQUIRE_EQUAL(cf3.fragment_type(), type);
476  fps.clear();
477  BOOST_REQUIRE_EQUAL(gen.ev_counter(), 5);
478 
479 
480 
481  gen.setFireCount(5);
482  gen.waitForFrags();
483  t.AddRequest(5, 8);
484  sts = gen.getNext(fps);
485  BOOST_REQUIRE_EQUAL(sts, true);
486  BOOST_REQUIRE_EQUAL(fps.size(), 1);
487 
488  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
489  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 8);
490  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 5);
491  type = artdaq::Fragment::ContainerFragmentType;
492  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
493  auto cf4 = artdaq::ContainerFragment(*fps.front());
494  BOOST_REQUIRE_EQUAL(cf4.block_count(), 3);
495  BOOST_REQUIRE_EQUAL(cf4.missing_data(), false);
496  type = artdaq::Fragment::FirstUserFragmentType;
497  BOOST_REQUIRE_EQUAL(cf4.fragment_type(), type);
498  BOOST_REQUIRE_EQUAL(cf4.at(0)->timestamp(), 7);
499  BOOST_REQUIRE_EQUAL(cf4.at(1)->timestamp(), 8);
500  BOOST_REQUIRE_EQUAL(cf4.at(2)->timestamp(), 9);
501  fps.clear();
502  BOOST_REQUIRE_EQUAL(gen.ev_counter(), 6);
503 
504 
505  gen.StopCmd(0xFFFFFFFF, 1);
506  gen.joinThreads();
507 
508 
509  TLOG(TLVL_INFO) << "CircularBufferMode test case END";
510 }
511 
512 BOOST_AUTO_TEST_CASE(WindowMode_Function)
513 {
514  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
515  TLOG(TLVL_INFO) << "WindowMode_Function test case BEGIN" ;
516  const int REQUEST_PORT = (seedAndRandom() % (32768 - 1024)) + 1024;
517  const int DELAY_TIME = 100;
518  fhicl::ParameterSet ps;
519  ps.put<int>("board_id", 1);
520  ps.put<int>("fragment_id", 1);
521  ps.put<int>("request_port", REQUEST_PORT);
522 #if MULTICAST_MODE
523  ps.put<std::string>("request_address", "227.18.12.32");
524 #else
525  ps.put<std::string>("request_address", "localhost");
526 #endif
527  ps.put<artdaq::Fragment::timestamp_t>("request_window_offset", 0);
528  ps.put<artdaq::Fragment::timestamp_t>("request_window_width", 0);
529  ps.put<bool>("separate_data_thread", true);
530  ps.put<bool>("separate_monitoring_thread", false);
531  ps.put<int64_t>("hardware_poll_interval_us", 0);
532  ps.put<size_t>("data_buffer_depth_fragments", 5);
533  ps.put<std::string>("request_mode", "window");
534  ps.put<size_t>("missing_request_window_timeout_us", 500000);
535  ps.put<size_t>("window_close_timeout_us", 500000);
536  ps.put("request_delay_ms", DELAY_TIME);
537  ps.put("send_requests", true);
538 
539  artdaq::RequestSender t(ps);
540  t.AddRequest(1, 1);
541 
543  gen.StartCmd(1, 0xFFFFFFFF, 1);
544  BOOST_REQUIRE_EQUAL(gen.ev_counter(), 1);
545 
546  artdaq::FragmentPtrs fps;
547  auto sts = gen.getNext(fps);
548  BOOST_REQUIRE_EQUAL(gen.ev_counter(), 2);
549  BOOST_REQUIRE_EQUAL(sts, true);
550  BOOST_REQUIRE_EQUAL(fps.size(), 1u);
551  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
552  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
553  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
554  auto type = artdaq::Fragment::ContainerFragmentType;
555  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
556  BOOST_REQUIRE_GE(fps.front()->sizeBytes(), 2 * sizeof(artdaq::detail::RawFragmentHeader) + sizeof(artdaq::ContainerFragment::Metadata));
557  auto cf = artdaq::ContainerFragment(*fps.front());
558  BOOST_REQUIRE_EQUAL(cf.block_count(), 1);
559  BOOST_REQUIRE_EQUAL(cf.missing_data(), false);
560  type = artdaq::Fragment::FirstUserFragmentType;
561  BOOST_REQUIRE_EQUAL(cf.fragment_type(), type);
562  fps.clear();
563 
564  // No data for request
565  t.AddRequest(2, 2);
566  sts = gen.getNext(fps);
567  BOOST_REQUIRE_EQUAL(gen.ev_counter(), 2);
568  BOOST_REQUIRE_EQUAL(sts, true);
569  BOOST_REQUIRE_EQUAL(fps.size(), 0);
570 
571  gen.setFireCount(1);
572  gen.waitForFrags();
573  sts = gen.getNext(fps);
574  BOOST_REQUIRE_EQUAL(gen.ev_counter(), 3);
575  BOOST_REQUIRE_EQUAL(sts, true);
576  BOOST_REQUIRE_EQUAL(fps.size(), 1);
577  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
578  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 2);
579  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 2);
580  type = artdaq::Fragment::ContainerFragmentType;
581  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
582  auto cf2 = artdaq::ContainerFragment(*fps.front());
583  BOOST_REQUIRE_EQUAL(cf2.block_count(), 1);
584  BOOST_REQUIRE_EQUAL(cf2.missing_data(), false);
585  type = artdaq::Fragment::FirstUserFragmentType;
586  BOOST_REQUIRE_EQUAL(cf2.fragment_type(), type);
587  fps.clear();
588 
589  // Request Timeout
590  t.AddRequest(4, 3);
591  sts = gen.getNext(fps);
592  BOOST_REQUIRE_EQUAL(sts, true);
593  BOOST_REQUIRE_EQUAL(fps.size(), 0);
594  BOOST_REQUIRE_EQUAL(gen.ev_counter(), 3);
595 
596 
597  usleep(1500000);
598  sts = gen.getNext(fps);
599  BOOST_REQUIRE_EQUAL(sts, true);
600  BOOST_REQUIRE_EQUAL(fps.size(), 1);
601 
602  // Also, missing request timeout
603  auto list = gen.getOutOfOrderWindowList();
604  BOOST_REQUIRE_EQUAL(list.size(), 1);
605  BOOST_REQUIRE_EQUAL(list.begin()->first, 4);
606  BOOST_REQUIRE_EQUAL(gen.ev_counter(), 3);
607 
608  usleep(1500000);
609 
610 
611  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
612  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 3);
613  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 4);
614  type = artdaq::Fragment::ContainerFragmentType;
615  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
616  auto cf3 = artdaq::ContainerFragment(*fps.front());
617  BOOST_REQUIRE_EQUAL(cf3.block_count(), 0);
618  BOOST_REQUIRE_EQUAL(cf3.missing_data(), true);
619  type = artdaq::Fragment::EmptyFragmentType;
620  BOOST_REQUIRE_EQUAL(cf3.fragment_type(), type);
621  BOOST_REQUIRE_EQUAL(gen.ev_counter(), 3);
622  fps.clear();
623 
624  // Data-taking has passed request
625  gen.setFireCount(12);
626  gen.waitForFrags();
627  t.AddRequest(5, 4);
628  list = gen.getOutOfOrderWindowList(); // Out-of-order list is only updated in getNext calls
629  BOOST_REQUIRE_EQUAL(list.size(), 1);
630  sts = gen.getNext(fps);
631  list = gen.getOutOfOrderWindowList(); // Out-of-order list is only updated in getNext calls
632  BOOST_REQUIRE_EQUAL(gen.ev_counter(), 6);
633  BOOST_REQUIRE_EQUAL(list.size(), 0);
634  BOOST_REQUIRE_EQUAL(sts, true);
635  BOOST_REQUIRE_EQUAL(fps.size(), 1);
636  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
637  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 4);
638  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 5);
639  type = artdaq::Fragment::ContainerFragmentType;
640  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
641  auto cf4 = artdaq::ContainerFragment(*fps.front());
642  BOOST_REQUIRE_EQUAL(cf4.block_count(), 0);
643  BOOST_REQUIRE_EQUAL(cf4.missing_data(), true);
644  type = artdaq::Fragment::EmptyFragmentType;
645  BOOST_REQUIRE_EQUAL(cf4.fragment_type(), type);
646  fps.clear();
647 
648 
649  // Out-of-order windows
650  t.AddRequest(7, 13);
651  sts = gen.getNext(fps);
652  BOOST_REQUIRE_EQUAL(sts, true);
653  BOOST_REQUIRE_EQUAL(fps.size(), 1);
654  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
655  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 13);
656  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 7);
657  type = artdaq::Fragment::ContainerFragmentType;
658  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
659  auto cf5 = artdaq::ContainerFragment(*fps.front());
660  BOOST_REQUIRE_EQUAL(cf5.block_count(), 1);
661  BOOST_REQUIRE_EQUAL(cf5.missing_data(), false);
662  type = artdaq::Fragment::FirstUserFragmentType;
663  BOOST_REQUIRE_EQUAL(cf5.fragment_type(), type);
664  BOOST_REQUIRE_EQUAL(gen.ev_counter(), 6);
665  fps.clear();
666 
667  list = gen.getOutOfOrderWindowList();
668  BOOST_REQUIRE_EQUAL(list.size(), 1);
669  BOOST_REQUIRE_EQUAL(list.begin()->first, 7);
670 
671  t.AddRequest(6, 12);
672  sts = gen.getNext(fps);
673  BOOST_REQUIRE_EQUAL(sts, true);
674  BOOST_REQUIRE_EQUAL(fps.size(), 1);
675  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
676  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 12);
677  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 6);
678  type = artdaq::Fragment::ContainerFragmentType;
679  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
680  auto cf6 = artdaq::ContainerFragment(*fps.front());
681  BOOST_REQUIRE_EQUAL(cf6.block_count(), 1);
682  BOOST_REQUIRE_EQUAL(cf6.missing_data(), false);
683  type = artdaq::Fragment::FirstUserFragmentType;
684  BOOST_REQUIRE_EQUAL(cf6.fragment_type(), type);
685  fps.clear();
686  BOOST_REQUIRE_EQUAL(gen.ev_counter(), 8);
687 
688  list = gen.getOutOfOrderWindowList();
689  BOOST_REQUIRE_EQUAL(list.size(), 0);
690 
691  usleep(1500000);
692 
693  gen.StopCmd(0xFFFFFFFF, 1);
694  TLOG(TLVL_INFO) << "WindowMode_Function test case END" ;
695  gen.joinThreads();
696 
697 }
698 
699 // 1. Both start and end before any data in buffer "RequestBeforeBuffer"
700 // 2. Start before buffer, end in buffer "RequestStartsBeforeBuffer"
701 // 3. Start befoer buffer, end after buffer "RequestOutsideBuffer"
702 // 4. Start and end in buffer "RequestInBuffer"
703 // 5. Start in buffer, end after buffer "RequestEndsAfterBuffer"
704 // 6. Start and end after buffer "RequestAfterBuffer"
705 BOOST_AUTO_TEST_CASE(WindowMode_RequestBeforeBuffer)
706 {
707  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
708  TLOG(TLVL_INFO) << "WindowMode_RequestBeforeBuffer test case BEGIN" ;
709  const int REQUEST_PORT = (seedAndRandom() % (32768 - 1024)) + 1024;
710  const int DELAY_TIME = 100;
711  fhicl::ParameterSet ps;
712  ps.put<int>("board_id", 1);
713  ps.put<int>("fragment_id", 1);
714  ps.put<int>("request_port", REQUEST_PORT);
715 #if MULTICAST_MODE
716  ps.put<std::string>("request_address", "227.18.12.32");
717 #else
718  ps.put<std::string>("request_address", "localhost");
719 #endif
720  ps.put<artdaq::Fragment::timestamp_t>("request_window_offset", 0);
721  ps.put<artdaq::Fragment::timestamp_t>("request_window_width", 3);
722  ps.put<bool>("separate_data_thread", true);
723  ps.put<bool>("separate_monitoring_thread", false);
724  ps.put<int64_t>("hardware_poll_interval_us", 0);
725  ps.put<size_t>("data_buffer_depth_fragments", 5);
726  ps.put<std::string>("request_mode", "window");
727  ps.put("request_delay_ms", DELAY_TIME);
728  ps.put("send_requests", true);
729 
730  artdaq::RequestSender t(ps);
731 
733  gen.StartCmd(1, 0xFFFFFFFF, 1);
734 
735  artdaq::FragmentPtrs fps;
736  int sts;
737  artdaq::Fragment::type_t type;
738 
739  // 1. Both start and end before any data in buffer
740  // -- Should return ContainerFragment with MissingData bit set and zero Fragments
741  gen.setFireCount(9); // Buffer start is at ts 6, end at 10
742  gen.waitForFrags();
743  t.AddRequest(1, 1); // Requesting data from ts 1 to 3
744 
745  sts = gen.getNext(fps);
746  BOOST_REQUIRE_EQUAL(sts, true);
747  BOOST_REQUIRE_EQUAL(fps.size(), 1);
748  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
749  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
750  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
751  type = artdaq::Fragment::ContainerFragmentType;
752  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
753  auto cf4 = artdaq::ContainerFragment(*fps.front());
754  BOOST_REQUIRE_EQUAL(cf4.block_count(), 0);
755  BOOST_REQUIRE_EQUAL(cf4.missing_data(), true);
756  type = artdaq::Fragment::EmptyFragmentType;
757  BOOST_REQUIRE_EQUAL(cf4.fragment_type(), type);
758 
759  gen.StopCmd(0xFFFFFFFF, 1);
760  TLOG(TLVL_INFO) << "WindowMode_RequestBeforeBuffer test case END" ;
761 
762 }
764 {
765  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
766  TLOG(TLVL_INFO) << "WindowMode_RequestStartsBeforeBuffer test case BEGIN" ;
767  const int REQUEST_PORT = (seedAndRandom() % (32768 - 1024)) + 1024;
768  const int DELAY_TIME = 100;
769  fhicl::ParameterSet ps;
770  ps.put<int>("board_id", 1);
771  ps.put<int>("fragment_id", 1);
772  ps.put<int>("request_port", REQUEST_PORT);
773 #if MULTICAST_MODE
774  ps.put<std::string>("request_address", "227.18.12.32");
775 #else
776  ps.put<std::string>("request_address", "localhost");
777 #endif
778  ps.put<artdaq::Fragment::timestamp_t>("request_window_offset", 0);
779  ps.put<artdaq::Fragment::timestamp_t>("request_window_width", 3);
780  ps.put<bool>("separate_data_thread", true);
781  ps.put<bool>("separate_monitoring_thread", false);
782  ps.put<int64_t>("hardware_poll_interval_us", 0);
783  ps.put<size_t>("data_buffer_depth_fragments", 5);
784  ps.put<std::string>("request_mode", "window");
785  ps.put("request_delay_ms", DELAY_TIME);
786  ps.put("send_requests", true);
787 
788  artdaq::RequestSender t(ps);
789 
791  gen.StartCmd(1, 0xFFFFFFFF, 1);
792 
793  artdaq::FragmentPtrs fps;
794  int sts;
795  artdaq::Fragment::type_t type;
796 
797  gen.waitForFrags();
798  gen.setFireCount(9); // Buffer contains 6 to 10
799  gen.waitForFrags();
800 
801  // 2. Start before buffer, end in buffer
802  // -- Should return ContainerFragment with MissingData bit set and one or more Fragments
803  t.AddRequest(1, 4); // Requesting data from ts 4 to 6
804 
805  sts = gen.getNext(fps);
806  BOOST_REQUIRE_EQUAL(sts, true);
807  BOOST_REQUIRE_EQUAL(fps.size(), 1);
808  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
809  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 4);
810  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
811  type = artdaq::Fragment::ContainerFragmentType;
812  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
813  auto cf4 = artdaq::ContainerFragment(*fps.front());
814  BOOST_REQUIRE_EQUAL(cf4.block_count(), 1);
815  BOOST_REQUIRE_EQUAL(cf4.missing_data(), true);
816  type = artdaq::Fragment::FirstUserFragmentType;
817  BOOST_REQUIRE_EQUAL(cf4.fragment_type(), type);
818 
819  gen.StopCmd(0xFFFFFFFF, 1);
820  gen.joinThreads();
821  TLOG(TLVL_INFO) << "WindowMode_RequestStartsBeforeBuffer test case END" ;
822 
823 }
824 BOOST_AUTO_TEST_CASE(WindowMode_RequestOutsideBuffer)
825 {
826  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
827  TLOG(TLVL_INFO) << "WindowMode_RequestOutsideBuffer test case BEGIN" ;
828  const int REQUEST_PORT = (seedAndRandom() % (32768 - 1024)) + 1024;
829  const int DELAY_TIME = 100;
830  fhicl::ParameterSet ps;
831  ps.put<int>("board_id", 1);
832  ps.put<int>("fragment_id", 1);
833  ps.put<int>("request_port", REQUEST_PORT);
834 #if MULTICAST_MODE
835  ps.put<std::string>("request_address", "227.18.12.32");
836 #else
837  ps.put<std::string>("request_address", "localhost");
838 #endif
839  ps.put<artdaq::Fragment::timestamp_t>("request_window_offset", 0);
840  ps.put<artdaq::Fragment::timestamp_t>("request_window_width", 4);
841  ps.put<size_t>("window_close_timeout_us", 500000);
842  ps.put<bool>("separate_data_thread", true);
843  ps.put<bool>("separate_monitoring_thread", false);
844  ps.put<int64_t>("hardware_poll_interval_us", 0);
845  ps.put<size_t>("data_buffer_depth_fragments", 5);
846  ps.put<std::string>("request_mode", "window");
847  ps.put("request_delay_ms", DELAY_TIME);
848  ps.put("send_requests", true);
849 
850  artdaq::RequestSender t(ps);
851 
853  gen.StartCmd(1, 0xFFFFFFFF, 1);
854 
855  artdaq::FragmentPtrs fps;
856  int sts;
857  artdaq::Fragment::type_t type;
858 
859  gen.waitForFrags();
860  gen.setFireCount(9); // Buffer contains 6 to 10
861  gen.waitForFrags();
862 
863  // 3. Start before buffer, end after buffer
864  // -- Should not return until buffer passes end or timeout (check both cases), MissingData bit set
865 
866  t.AddRequest(1, 6); // Requesting data from ts 6 to 9, buffer will contain 10
867  sts = gen.getNext(fps);
868  BOOST_REQUIRE_EQUAL(sts, true);
869  BOOST_REQUIRE_EQUAL(fps.size(), 1);
870  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
871  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 6);
872  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
873  type = artdaq::Fragment::ContainerFragmentType;
874  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
875  auto cf = artdaq::ContainerFragment(*fps.front());
876  BOOST_REQUIRE_EQUAL(cf.block_count(), 4);
877  BOOST_REQUIRE_EQUAL(cf.missing_data(), false);
878  type = artdaq::Fragment::FirstUserFragmentType;
879  BOOST_REQUIRE_EQUAL(cf.fragment_type(), type);
880  fps.clear();
881 
882  t.AddRequest(2, 9); // Requesting data from ts 9 to 12
883  sts = gen.getNext(fps);
884  BOOST_REQUIRE_EQUAL(sts, true);
885  BOOST_REQUIRE_EQUAL(fps.size(), 0);
886 
887  gen.setFireCount(3); // Buffer start is at ts 10, end at 13
888  gen.waitForFrags();
889 
890  sts = gen.getNext(fps);
891  BOOST_REQUIRE_EQUAL(sts, true);
892  BOOST_REQUIRE_EQUAL(fps.size(), 1);
893  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
894  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 9);
895  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 2);
896  type = artdaq::Fragment::ContainerFragmentType;
897  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
898  auto cf2 = artdaq::ContainerFragment(*fps.front());
899  BOOST_REQUIRE_EQUAL(cf2.block_count(), 3);
900  BOOST_REQUIRE_EQUAL(cf2.missing_data(), true);
901  type = artdaq::Fragment::FirstUserFragmentType;
902  BOOST_REQUIRE_EQUAL(cf2.fragment_type(), type);
903  fps.clear();
904 
905 
906 
907  t.AddRequest(3, 12); // Requesting data from ts 11 to 14
908 
909  sts = gen.getNext(fps);
910  BOOST_REQUIRE_EQUAL(sts, true);
911  BOOST_REQUIRE_EQUAL(fps.size(), 0);
912 
913  usleep(550000);
914 
915  sts = gen.getNext(fps);
916  BOOST_REQUIRE_EQUAL(sts, true);
917  BOOST_REQUIRE_EQUAL(fps.size(), 1);
918  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
919  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 12);
920  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 3);
921  type = artdaq::Fragment::ContainerFragmentType;
922  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
923  auto cf4 = artdaq::ContainerFragment(*fps.front());
924  BOOST_REQUIRE_EQUAL(cf4.block_count(), 1);
925  BOOST_REQUIRE_EQUAL(cf4.missing_data(), true);
926  type = artdaq::Fragment::FirstUserFragmentType;
927  BOOST_REQUIRE_EQUAL(cf4.fragment_type(), type);
928 
929  gen.StopCmd(0xFFFFFFFF, 1);
930  gen.joinThreads();
931  TLOG(TLVL_INFO) << "WindowMode_RequestOutsideBuffer test case END" ;
932 
933 }
934 BOOST_AUTO_TEST_CASE(WindowMode_RequestInBuffer)
935 {
936  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
937  TLOG(TLVL_INFO) << "WindowMode_RequestInBuffer test case BEGIN" ;
938  const int REQUEST_PORT = (seedAndRandom() % (32768 - 1024)) + 1024;
939  const int DELAY_TIME = 100;
940  fhicl::ParameterSet ps;
941  ps.put<int>("board_id", 1);
942  ps.put<int>("fragment_id", 1);
943  ps.put<int>("request_port", REQUEST_PORT);
944 #if MULTICAST_MODE
945  ps.put<std::string>("request_address", "227.18.12.32");
946 #else
947  ps.put<std::string>("request_address", "localhost");
948 #endif
949  ps.put<artdaq::Fragment::timestamp_t>("request_window_offset", 0);
950  ps.put<artdaq::Fragment::timestamp_t>("request_window_width", 3);
951  ps.put<bool>("separate_data_thread", true);
952  ps.put<bool>("separate_monitoring_thread", false);
953  ps.put<int64_t>("hardware_poll_interval_us", 0);
954  ps.put<size_t>("data_buffer_depth_fragments", 5);
955  ps.put<std::string>("request_mode", "window");
956  ps.put("request_delay_ms", DELAY_TIME);
957  ps.put("send_requests", true);
958 
959  artdaq::RequestSender t(ps);
960 
962  gen.StartCmd(1, 0xFFFFFFFF, 1);
963 
964  artdaq::FragmentPtrs fps;
965  int sts;
966  artdaq::Fragment::type_t type;
967  gen.waitForFrags();
968 
969  // 4. Start and end in buffer
970  // -- Should return ContainerFragment with one or more Fragments
971  gen.setFireCount(5); // Buffer start is at ts 2, end at 6
972  gen.waitForFrags();
973  t.AddRequest(1, 3); // Requesting data from ts 3 to 5
974 
975  sts = gen.getNext(fps);
976  BOOST_REQUIRE_EQUAL(sts, true);
977  BOOST_REQUIRE_EQUAL(fps.size(), 1);
978  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
979  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 3);
980  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
981  type = artdaq::Fragment::ContainerFragmentType;
982  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
983  auto cf4 = artdaq::ContainerFragment(*fps.front());
984  BOOST_REQUIRE_EQUAL(cf4.block_count(), 3);
985  BOOST_REQUIRE_EQUAL(cf4.missing_data(), false);
986  type = artdaq::Fragment::FirstUserFragmentType;
987  BOOST_REQUIRE_EQUAL(cf4.fragment_type(), type);
988 
989  gen.StopCmd(0xFFFFFFFF, 1);
990  TLOG(TLVL_INFO) << "WindowMode_RequestInBuffer test case END" ;
991 
992 }
994 {
995  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
996  TLOG(TLVL_INFO) << "WindowMode_RequestEndsAfterBuffer test case BEGIN" ;
997  const int REQUEST_PORT = (seedAndRandom() % (32768 - 1024)) + 1024;
998  const int DELAY_TIME = 100;
999  fhicl::ParameterSet ps;
1000  ps.put<int>("board_id", 1);
1001  ps.put<int>("fragment_id", 1);
1002  ps.put<int>("request_port", REQUEST_PORT);
1003 #if MULTICAST_MODE
1004  ps.put<std::string>("request_address", "227.18.12.32");
1005 #else
1006  ps.put<std::string>("request_address", "localhost");
1007 #endif
1008  ps.put<artdaq::Fragment::timestamp_t>("request_window_offset", 0);
1009  ps.put<artdaq::Fragment::timestamp_t>("request_window_width", 3);
1010  ps.put<size_t>("window_close_timeout_us", 500000);
1011  ps.put<bool>("separate_data_thread", true);
1012  ps.put<bool>("separate_monitoring_thread", false);
1013  ps.put<int64_t>("hardware_poll_interval_us", 0);
1014  ps.put<size_t>("data_buffer_depth_fragments", 5);
1015  ps.put<std::string>("request_mode", "window");
1016  ps.put("request_delay_ms", DELAY_TIME);
1017  ps.put("send_requests", true);
1018 
1019  artdaq::RequestSender t(ps);
1020 
1022  gen.StartCmd(1, 0xFFFFFFFF, 1);
1023 
1024  artdaq::FragmentPtrs fps;
1025  int sts;
1026  artdaq::Fragment::type_t type;
1027  gen.waitForFrags();
1028  gen.setFireCount(5); // Buffer contains 2 to 6
1029  gen.waitForFrags();
1030 
1031  // 5. Start in buffer, end after buffer
1032  // -- Should not return until buffer passes end or timeout (check both cases). MissingData bit set if timeout
1033  t.AddRequest(1, 5); // Requesting data from ts 5 to 7
1034  sts = gen.getNext(fps);
1035  BOOST_REQUIRE_EQUAL(sts, true);
1036  BOOST_REQUIRE_EQUAL(fps.size(), 0);
1037 
1038  gen.setFireCount(2); // Buffer contains 4 to 8
1039  gen.waitForFrags();
1040  sts = gen.getNext(fps);
1041  BOOST_REQUIRE_EQUAL(sts, true);
1042  BOOST_REQUIRE_EQUAL(fps.size(), 1);
1043  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
1044  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 5);
1045  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
1046  type = artdaq::Fragment::ContainerFragmentType;
1047  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
1048  auto cf = artdaq::ContainerFragment(*fps.front());
1049  BOOST_REQUIRE_EQUAL(cf.block_count(), 3);
1050  BOOST_REQUIRE_EQUAL(cf.missing_data(), false);
1051  type = artdaq::Fragment::FirstUserFragmentType;
1052  BOOST_REQUIRE_EQUAL(cf.fragment_type(), type);
1053  fps.clear();
1054 
1055  t.AddRequest(2, 8); // Requesting data from ts 8 to 10
1056 
1057  sts = gen.getNext(fps);
1058  BOOST_REQUIRE_EQUAL(sts, true);
1059  BOOST_REQUIRE_EQUAL(fps.size(), 0);
1060 
1061  usleep(550000);
1062 
1063  sts = gen.getNext(fps);
1064  BOOST_REQUIRE_EQUAL(sts, true);
1065  BOOST_REQUIRE_EQUAL(fps.size(), 1);
1066  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
1067  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 8);
1068  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 2);
1069  type = artdaq::Fragment::ContainerFragmentType;
1070  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
1071  auto cf4 = artdaq::ContainerFragment(*fps.front());
1072  BOOST_REQUIRE_EQUAL(cf4.block_count(), 1);
1073  BOOST_REQUIRE_EQUAL(cf4.missing_data(), true);
1074  type = artdaq::Fragment::FirstUserFragmentType;
1075  BOOST_REQUIRE_EQUAL(cf4.fragment_type(), type);
1076 
1077  gen.StopCmd(0xFFFFFFFF, 1);
1078  gen.joinThreads();
1079  TLOG(TLVL_INFO) << "WindowMode_RequestEndsAfterBuffer test case END" ;
1080 
1081 }
1082 BOOST_AUTO_TEST_CASE(WindowMode_RequestAfterBuffer)
1083 {
1084  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
1085  TLOG(TLVL_INFO) << "WindowMode_RequestAfterBuffer test case BEGIN" ;
1086  const int REQUEST_PORT = (seedAndRandom() % (32768 - 1024)) + 1024;
1087  const int DELAY_TIME = 100;
1088  fhicl::ParameterSet ps;
1089  ps.put<int>("board_id", 1);
1090  ps.put<int>("fragment_id", 1);
1091  ps.put<int>("request_port", REQUEST_PORT);
1092 #if MULTICAST_MODE
1093  ps.put<std::string>("request_address", "227.18.12.32");
1094 #else
1095  ps.put<std::string>("request_address", "localhost");
1096 #endif
1097  ps.put<artdaq::Fragment::timestamp_t>("request_window_offset", 0);
1098  ps.put<artdaq::Fragment::timestamp_t>("request_window_width", 3);
1099  ps.put<size_t>("window_close_timeout_us", 500000);
1100  ps.put<bool>("separate_data_thread", true);
1101  ps.put<bool>("separate_monitoring_thread", false);
1102  ps.put<int64_t>("hardware_poll_interval_us", 0);
1103  ps.put<size_t>("data_buffer_depth_fragments", 5);
1104  ps.put<std::string>("request_mode", "window");
1105  ps.put("request_delay_ms", DELAY_TIME);
1106  ps.put("send_requests", true);
1107 
1108  artdaq::RequestSender t(ps);
1109 
1111  gen.StartCmd(1, 0xFFFFFFFF, 1);
1112 
1113  artdaq::FragmentPtrs fps;
1114  int sts;
1115  artdaq::Fragment::type_t type;
1116  gen.waitForFrags();
1117 
1118  // 6. Start and end after buffer
1119  // -- Should not return until buffer passes end or timeout (check both cases). MissingData bit set if timeout
1120  gen.setFireCount(9); // Buffer start is 6, end at 10
1121  gen.waitForFrags();
1122  t.AddRequest(1, 11); // Requesting data from ts 11 to 13
1123 
1124  sts = gen.getNext(fps);
1125  BOOST_REQUIRE_EQUAL(sts, true);
1126  BOOST_REQUIRE_EQUAL(fps.size(), 0);
1127  gen.setFireCount(1); // Buffer start is 7, end at 11
1128  gen.waitForFrags();
1129  sts = gen.getNext(fps);
1130  BOOST_REQUIRE_EQUAL(sts, true);
1131  BOOST_REQUIRE_EQUAL(fps.size(), 0);
1132 
1133  gen.setFireCount(3); // Buffer start is 10, end at 14
1134  gen.waitForFrags();
1135  sts = gen.getNext(fps);
1136  BOOST_REQUIRE_EQUAL(sts, true);
1137  BOOST_REQUIRE_EQUAL(fps.size(), 1);
1138  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
1139  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 11);
1140  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
1141  type = artdaq::Fragment::ContainerFragmentType;
1142  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
1143  auto cf = artdaq::ContainerFragment(*fps.front());
1144  BOOST_REQUIRE_EQUAL(cf.block_count(), 3);
1145  BOOST_REQUIRE_EQUAL(cf.missing_data(), false);
1146  type = artdaq::Fragment::FirstUserFragmentType;
1147  BOOST_REQUIRE_EQUAL(cf.fragment_type(), type);
1148  fps.clear();
1149 
1150  t.AddRequest(2, 16); // Requesting data from ts 15 to 17
1151  sts = gen.getNext(fps);
1152  BOOST_REQUIRE_EQUAL(sts, true);
1153  BOOST_REQUIRE_EQUAL(fps.size(), 0);
1154 
1155  usleep(550000);
1156 
1157  sts = gen.getNext(fps);
1158  BOOST_REQUIRE_EQUAL(sts, true);
1159  BOOST_REQUIRE_EQUAL(fps.size(), 1);
1160  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
1161  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 16);
1162  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 2);
1163  type = artdaq::Fragment::ContainerFragmentType;
1164  BOOST_REQUIRE_EQUAL(fps.front()->type(), type);
1165  auto cf4 = artdaq::ContainerFragment(*fps.front());
1166  BOOST_REQUIRE_EQUAL(cf4.block_count(), 0);
1167  BOOST_REQUIRE_EQUAL(cf4.missing_data(), true);
1168  type = artdaq::Fragment::EmptyFragmentType;
1169  BOOST_REQUIRE_EQUAL(cf4.fragment_type(), type);
1170 
1171  gen.StopCmd(0xFFFFFFFF, 1);
1172  gen.joinThreads();
1173  TLOG(TLVL_INFO) << "WindowMode_RequestAfterBuffer test case END" ;
1174 
1175 }
1176 
1177 BOOST_AUTO_TEST_CASE(HardwareFailure_NonThreaded)
1178 {
1179  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
1180  TLOG(TLVL_INFO) << "HardwareFailure_NonThreaded test case BEGIN" ;
1181  fhicl::ParameterSet ps;
1182  ps.put<int>("board_id", 1);
1183  ps.put<int>("fragment_id", 1);
1184  ps.put<bool>("separate_data_thread", false);
1185  ps.put<bool>("separate_monitoring_thread", false);
1186  ps.put<int64_t>("hardware_poll_interval_us", 10);
1187 
1189  gen.StartCmd(1, 0xFFFFFFFF, 1);
1190 
1191  artdaq::FragmentPtrs fps;
1192  auto sts = gen.getNext(fps);
1193  BOOST_REQUIRE_EQUAL(sts, true);
1194  BOOST_REQUIRE_EQUAL(fps.size(), 1u);
1195  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
1196  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
1197  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
1198  fps.clear();
1199 
1200  gen.setFireCount(1);
1201  gen.setHwFail();
1202  usleep(10000);
1203  sts = gen.getNext(fps);
1204  BOOST_REQUIRE_EQUAL(sts, false);
1205  BOOST_REQUIRE_EQUAL(fps.size(), 0);
1206 
1207  gen.StopCmd(0xFFFFFFFF, 1);
1208  gen.joinThreads();
1209  TLOG(TLVL_INFO) << "HardwareFailure_NonThreaded test case END" ;
1210 }
1211 
1212 BOOST_AUTO_TEST_CASE(HardwareFailure_Threaded)
1213 {
1214  artdaq::configureMessageFacility("CommandableFragmentGenerator_t");
1215  TLOG(TLVL_INFO) << "HardwareFailure_Threaded test case BEGIN" ;
1216  fhicl::ParameterSet ps;
1217  ps.put<int>("board_id", 1);
1218  ps.put<int>("fragment_id", 1);
1219  ps.put<bool>("separate_data_thread", true);
1220  ps.put<bool>("separate_monitoring_thread", true);
1221  ps.put<int64_t>("hardware_poll_interval_us", 750000);
1222 
1224  gen.StartCmd(1, 0xFFFFFFFF, 1);
1225 
1226 
1227 
1228  artdaq::FragmentPtrs fps;
1229  auto sts = gen.getNext(fps);
1230  BOOST_REQUIRE_EQUAL(sts, true);
1231  BOOST_REQUIRE_EQUAL(fps.size(), 1u);
1232  BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
1233  BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 1);
1234  BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
1235  fps.clear();
1236 
1237  gen.setHwFail();
1238  //gen.setFireCount(1);
1239  //sts = gen.getNext(fps);
1240  //BOOST_REQUIRE_EQUAL(sts, true);
1241  //BOOST_REQUIRE_EQUAL(fps.size(), 1);
1242  //BOOST_REQUIRE_EQUAL(fps.front()->fragmentID(), 1);
1243  //BOOST_REQUIRE_EQUAL(fps.front()->timestamp(), 2);
1244  //BOOST_REQUIRE_EQUAL(fps.front()->sequenceID(), 1);
1245  //fps.clear();
1246 
1247  sleep(1);
1248 
1249  gen.setFireCount(1);
1250  sts = gen.getNext(fps);
1251  BOOST_REQUIRE_EQUAL(sts, false);
1252  BOOST_REQUIRE_EQUAL(fps.size(), 0);
1253 
1254  gen.StopCmd(0xFFFFFFFF, 1);
1255  gen.joinThreads();
1256  TLOG(TLVL_INFO) << "HardwareFailure_Threaded test case END" ;
1257 }
1258 
1259 BOOST_AUTO_TEST_SUITE_END()
bool getNext_(artdaq::FragmentPtrs &frags) override
Generate data and return it to CommandableFragmentGenerator.
CommandableFragmentGenerator derived class for testing.
The RequestSender contains methods used to send data requests and Routing tokens. ...
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.
size_t ev_counter() const
Get the current value of the event counter.
std::map< Fragment::sequence_id_t, std::chrono::steady_clock::time_point > getOutOfOrderWindowList() const
Access the windows_sent_ooo_ map.
void stop() override
Perform stop actions. No-Op.
void AddRequest(Fragment::sequence_id_t seqID, Fragment::timestamp_t timestamp)
Add a request to the request list.
void waitForFrags()
Wait for all fragments generated to be read by the CommandableFragmentGenerator
void joinThreads()
Join any data-taking threads. Should be called when destructing CommandableFragmentGenerator.
void setFireCount(size_t count)
Have getNext_ generate count fragments.