artdaq  v3_11_01
SharedMemoryEventManager_t.cc
1 #define TRACE_NAME "SharedMemoryEventManager_t"
2 
3 #include "artdaq-core/Core/SharedMemoryEventReceiver.hh"
4 #include "artdaq-core/Data/Fragment.hh"
5 #include "artdaq/DAQrate/SharedMemoryEventManager.hh"
6 
7 #define BOOST_TEST_MODULE SharedMemoryEventManager_t
8 #include "cetlib/quiet_unit_test.hpp"
9 #include "cetlib_except/exception.h"
10 
11 BOOST_AUTO_TEST_SUITE(SharedMemoryEventManager_test)
12 
13 artdaq::detail::RawFragmentHeader GetHeader(artdaq::FragmentPtr const& frag)
14 {
15  return *reinterpret_cast<artdaq::detail::RawFragmentHeader*>(frag->headerAddress()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
16 }
17 
18 BOOST_AUTO_TEST_CASE(Construct)
19 {
20  TLOG(TLVL_INFO) << "Test Construct BEGIN";
21  fhicl::ParameterSet pset;
22  pset.put("use_art", false);
23  pset.put("buffer_count", 2);
24  pset.put("max_event_size_bytes", 1000);
25  pset.put("expected_fragments_per_event", 2);
27 
28  BOOST_REQUIRE_EQUAL(t.runID(), 0);
29  BOOST_REQUIRE_EQUAL(t.GetSubrunForSequenceID(1), 1);
30  BOOST_REQUIRE_EQUAL(t.GetLockedBufferCount(), 0);
31  t.startRun(1);
32  BOOST_REQUIRE_EQUAL(t.runID(), 1);
33  TLOG(TLVL_INFO) << "Test Construct END";
34 }
35 
36 BOOST_AUTO_TEST_CASE(AddFragment)
37 {
38  TLOG(TLVL_INFO) << "Test AddFragment BEGIN";
39 
40  fhicl::ParameterSet pset;
41  pset.put("use_art", false);
42  pset.put("buffer_count", 2);
43  pset.put("max_event_size_bytes", 1000);
44  pset.put("expected_fragments_per_event", 2);
46  t.startRun(1);
47 
48  artdaq::FragmentPtr frag(new artdaq::Fragment(1, 0, artdaq::Fragment::FirstUserFragmentType, 0UL)), tmpFrag;
49  frag->resize(4);
50  for (auto ii = 0; ii < 4; ++ii)
51  {
52  *(frag->dataBegin() + ii) = ii;
53  }
54 
55  bool sts = t.AddFragment(std::move(frag), 1000000, tmpFrag);
56  BOOST_REQUIRE_EQUAL(sts, true);
57  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 1);
58  BOOST_REQUIRE_EQUAL(t.GetFragmentCount(1), 1);
59  TLOG(TLVL_INFO) << "Test AddFragment END";
60 }
61 
62 BOOST_AUTO_TEST_CASE(DataFlow)
63 {
64  TLOG(TLVL_INFO) << "Test DataFlow BEGIN";
65  fhicl::ParameterSet pset;
66  pset.put("use_art", false);
67  pset.put("buffer_count", 2);
68  pset.put("max_event_size_bytes", 1000);
69  pset.put("expected_fragments_per_event", 3);
71  t.startRun(1);
72 
73  artdaq::FragmentPtr frag(new artdaq::Fragment(1, 0, artdaq::Fragment::FirstUserFragmentType, 0UL)), tmpFrag;
74  frag->resize(4);
75  for (auto ii = 0; ii < 4; ++ii)
76  {
77  *(frag->dataBegin() + ii) = ii;
78  }
79 
80  auto hdr = GetHeader(frag);
81  auto fragLoc = t.WriteFragmentHeader(hdr);
82  memcpy(fragLoc, frag->dataBegin(), 4 * sizeof(artdaq::RawDataType));
83  t.DoneWritingFragment(hdr);
84  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 1);
85  BOOST_REQUIRE_EQUAL(t.GetFragmentCount(1), 1);
86 
87  frag->setFragmentID(1);
88  hdr = GetHeader(frag);
89  auto fragLoc2 = t.WriteFragmentHeader(hdr);
90  memcpy(fragLoc2, frag->dataBegin(), 4 * sizeof(artdaq::RawDataType));
91  t.DoneWritingFragment(hdr);
92  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 1);
93  BOOST_REQUIRE_EQUAL(t.GetFragmentCount(1), 2);
94  BOOST_REQUIRE_EQUAL(fragLoc + frag->size(), fragLoc2); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
95 
96  frag->setFragmentID(2);
97  hdr = GetHeader(frag);
98  auto fragLoc3 = t.WriteFragmentHeader(hdr);
99  memcpy(fragLoc3, frag->dataBegin(), 4 * sizeof(artdaq::RawDataType));
100  t.DoneWritingFragment(hdr);
101  BOOST_REQUIRE_EQUAL(fragLoc2 + frag->size(), fragLoc3); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
102  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 0);
103  BOOST_REQUIRE_EQUAL(t.GetArtEventCount(), 1);
104 
105  TLOG(TLVL_INFO) << "Test DataFlow END";
106 }
107 
108 BOOST_AUTO_TEST_CASE(EndOfData)
109 {
110  TLOG(TLVL_INFO) << "Test EndOfData BEGIN";
111  fhicl::ParameterSet pset;
112  pset.put("use_art", false);
113  pset.put("buffer_count", 2);
114  pset.put("max_event_size_bytes", 1000);
115  pset.put("expected_fragments_per_event", 1);
116  artdaq::SharedMemoryEventManager t(pset, pset);
117  t.startRun(1);
118 
119  artdaq::FragmentPtr frag(new artdaq::Fragment(1, 0, artdaq::Fragment::FirstUserFragmentType, 0UL)), tmpFrag;
120  frag->resize(4);
121  for (auto ii = 0; ii < 4; ++ii)
122  {
123  *(frag->dataBegin() + ii) = ii;
124  }
125 
126  auto hdr = GetHeader(frag);
127  auto fragLoc = t.WriteFragmentHeader(hdr);
128  memcpy(fragLoc, frag->dataBegin(), 4 * sizeof(artdaq::RawDataType));
129  t.DoneWritingFragment(hdr);
130  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 0);
131  BOOST_REQUIRE_EQUAL(t.GetArtEventCount(), 1);
132 
133  t.endOfData();
134 
135  t.startRun(2);
136 
137  frag->setSequenceID(1);
138  hdr = GetHeader(frag);
139  auto fragLoc3 = t.WriteFragmentHeader(hdr);
140 
141  std::atomic<bool> endComplete = false;
142  std::thread thread{
143  [&] { endComplete = t.endOfData(); }};
144 
145  memcpy(fragLoc3, frag->dataBegin(), 4 * sizeof(artdaq::RawDataType));
146  usleep(100000);
147  BOOST_REQUIRE_EQUAL(endComplete.load(), false);
148  t.DoneWritingFragment(hdr);
149  thread.join();
150  BOOST_REQUIRE_EQUAL(endComplete.load(), true);
151  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 0);
152  BOOST_REQUIRE_EQUAL(t.GetArtEventCount(), 1);
153 
154  frag->setSequenceID(2);
155  hdr = GetHeader(frag);
156  auto fragLoc2 = t.WriteFragmentHeader(hdr);
157  BOOST_REQUIRE_EQUAL(fragLoc2, nullptr);
158 
159  TLOG(TLVL_INFO) << "Test EndOfData END";
160 }
161 
162 BOOST_AUTO_TEST_CASE(TooManyFragments_InterleavedWrites)
163 {
164  TLOG(TLVL_INFO) << "Test TooManyFragments_InterleavedWrites BEGIN";
165  fhicl::ParameterSet pset;
166  pset.put("use_art", false);
167  pset.put("buffer_count", 2);
168  pset.put("max_event_size_bytes", 1000);
169  pset.put("expected_fragments_per_event", 3);
170  pset.put("stale_buffer_timeout_usec", 100000);
171  artdaq::SharedMemoryEventManager t(pset, pset);
172  t.startRun(1);
173 
174  artdaq::FragmentPtr frag(new artdaq::Fragment(1, 0, artdaq::Fragment::FirstUserFragmentType, 0UL)), tmpFrag;
175  frag->resize(4);
176  for (auto ii = 0; ii < 4; ++ii)
177  {
178  *(frag->dataBegin() + ii) = ii;
179  }
180 
181  auto hdr = GetHeader(frag);
182  auto fragLoc = t.WriteFragmentHeader(hdr);
183  memcpy(fragLoc, frag->dataBegin(), 4 * sizeof(artdaq::RawDataType));
184  t.DoneWritingFragment(hdr);
185  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 1);
186  BOOST_REQUIRE_EQUAL(t.GetFragmentCount(1), 1);
187 
188  frag->setFragmentID(1);
189  hdr = GetHeader(frag);
190  auto fragLoc2 = t.WriteFragmentHeader(hdr);
191  frag->setFragmentID(2);
192  hdr = GetHeader(frag);
193  auto fragLoc3 = t.WriteFragmentHeader(hdr);
194  frag->setFragmentID(3);
195  hdr = GetHeader(frag);
196  auto fragLoc4 = t.WriteFragmentHeader(hdr);
197  frag->setFragmentID(4);
198  hdr = GetHeader(frag);
199  auto fragLoc5 = t.WriteFragmentHeader(hdr);
200 
201  memcpy(fragLoc2, frag->dataBegin(), 4 * sizeof(artdaq::RawDataType));
202  t.DoneWritingFragment(hdr);
203  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 1);
204  BOOST_REQUIRE_EQUAL(fragLoc + frag->size(), fragLoc2); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
205 
206  memcpy(fragLoc3, frag->dataBegin(), 4 * sizeof(artdaq::RawDataType));
207  t.DoneWritingFragment(hdr);
208  BOOST_REQUIRE_EQUAL(fragLoc2 + frag->size(), fragLoc3); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
209  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 1);
210  BOOST_REQUIRE_EQUAL(t.GetArtEventCount(), 0);
211 
212  memcpy(fragLoc4, frag->dataBegin(), 4 * sizeof(artdaq::RawDataType));
213  t.DoneWritingFragment(hdr);
214  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 1);
215  BOOST_REQUIRE_EQUAL(t.GetArtEventCount(), 0);
216 
217  memcpy(fragLoc5, frag->dataBegin(), 4 * sizeof(artdaq::RawDataType));
218  t.DoneWritingFragment(hdr);
219  BOOST_REQUIRE_EQUAL(fragLoc4 + frag->size(), fragLoc5); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
220  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 0);
221  BOOST_REQUIRE_EQUAL(t.GetArtEventCount(), 1);
222 
223  usleep(1000000);
224  {
225  frag->setSequenceID(2);
226  frag->setFragmentID(0);
227 
228  auto hdr = GetHeader(frag);
229  auto fragLoc = t.WriteFragmentHeader(hdr);
230  memcpy(fragLoc, frag->dataBegin(), 4 * sizeof(artdaq::RawDataType));
231  t.DoneWritingFragment(hdr);
232  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 1);
233  BOOST_REQUIRE_EQUAL(t.GetFragmentCount(2), 1);
234  BOOST_REQUIRE_EQUAL(t.GetArtEventCount(), 1);
235  }
236  TLOG(TLVL_INFO) << "Test TooManyFragments_InterleavedWrites END";
237 }
238 
239 BOOST_AUTO_TEST_CASE(TooManyFragments_DiscreteWrites)
240 {
241  TLOG(TLVL_INFO) << "Test TooManyFragments_DiscreteWrites BEGIN";
242  fhicl::ParameterSet pset;
243  pset.put("use_art", false);
244  pset.put("buffer_count", 2);
245  pset.put("max_event_size_bytes", 1000);
246  pset.put("expected_fragments_per_event", 3);
247  pset.put("stale_buffer_timeout_usec", 100000);
248  artdaq::SharedMemoryEventManager t(pset, pset);
249  t.startRun(1);
250 
251  artdaq::FragmentPtr frag(new artdaq::Fragment(1, 0, artdaq::Fragment::FirstUserFragmentType, 0UL)), tmpFrag;
252  frag->resize(4);
253  for (auto ii = 0; ii < 4; ++ii)
254  {
255  *(frag->dataBegin() + ii) = ii;
256  }
257 
258  auto hdr = GetHeader(frag);
259  auto fragLoc = t.WriteFragmentHeader(hdr);
260  memcpy(fragLoc, frag->dataBegin(), 4 * sizeof(artdaq::RawDataType));
261  t.DoneWritingFragment(hdr);
262  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 1);
263  BOOST_REQUIRE_EQUAL(t.GetFragmentCount(1), 1);
264 
265  frag->setFragmentID(1);
266  hdr = GetHeader(frag);
267  auto fragLoc2 = t.WriteFragmentHeader(hdr);
268 
269  memcpy(fragLoc2, frag->dataBegin(), 4 * sizeof(artdaq::RawDataType));
270  t.DoneWritingFragment(hdr);
271  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 1);
272  BOOST_REQUIRE_EQUAL(fragLoc + frag->size(), fragLoc2); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
273 
274  frag->setFragmentID(2);
275  hdr = GetHeader(frag);
276  auto fragLoc3 = t.WriteFragmentHeader(hdr);
277  memcpy(fragLoc3, frag->dataBegin(), 4 * sizeof(artdaq::RawDataType));
278  t.DoneWritingFragment(hdr);
279  BOOST_REQUIRE_EQUAL(fragLoc2 + frag->size(), fragLoc3); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
280  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 0);
281  BOOST_REQUIRE_EQUAL(t.GetArtEventCount(), 1);
282 
283  frag->setFragmentID(3);
284  hdr = GetHeader(frag);
285  auto fragLoc4 = t.WriteFragmentHeader(hdr);
286 #if !ART_SUPPORTS_DUPLICATE_EVENTS
287  BOOST_REQUIRE_EQUAL(fragLoc4, t.GetDroppedDataAddress(hdr));
288 #endif
289  memcpy(fragLoc4, frag->dataBegin(), 4 * sizeof(artdaq::RawDataType));
290  t.DoneWritingFragment(hdr);
291 #if ART_SUPPORTS_DUPLICATE_EVENTS
292  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 1);
293  BOOST_REQUIRE_EQUAL(t.GetArtEventCount(), 1);
294 #else
295  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 0);
296  BOOST_REQUIRE_EQUAL(t.GetArtEventCount(), 1);
297 #endif
298 
299  usleep(1000000);
300  {
301  frag->setSequenceID(2);
302  frag->setFragmentID(0);
303 
304  auto hdr = GetHeader(frag);
305  auto fragLoc = t.WriteFragmentHeader(hdr);
306  memcpy(fragLoc, frag->dataBegin(), 4 * sizeof(artdaq::RawDataType));
307  t.DoneWritingFragment(hdr);
308  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 1);
309  //BOOST_REQUIRE_EQUAL(t.GetInactiveEventCount(), 0);
310  BOOST_REQUIRE_EQUAL(t.GetFragmentCount(2), 1);
311  BOOST_REQUIRE_EQUAL(t.GetArtEventCount(), 1);
312  }
313  TLOG(TLVL_INFO) << "Test TooManyFragments_DiscreteWrites END";
314 }
315 
316 //SharedMemoryEventManager should print error messages, but consume data for buffers which have timed out
317 BOOST_AUTO_TEST_CASE(ConsumeDroppedData_Active)
318 {
319  TLOG(TLVL_INFO) << "Test ConsumeDroppedData_Active BEGIN";
320  fhicl::ParameterSet pset;
321  pset.put("use_art", false);
322  pset.put("buffer_count", 20);
323  pset.put("max_event_size_bytes", 1000);
324  pset.put("expected_fragments_per_event", 2);
325  pset.put("stale_buffer_timeout_usec", 100000);
326 
327  artdaq::FragmentPtr frag(new artdaq::Fragment(1, 0, artdaq::Fragment::FirstUserFragmentType, 0UL)), tmpFrag;
328  frag->resize(4);
329  for (auto ii = 0; ii < 4; ++ii)
330  {
331  *(frag->dataBegin() + ii) = ii;
332  }
333 
334  artdaq::SharedMemoryEventManager t(pset, pset);
335  t.startRun(1);
336  {
337  auto hdr = GetHeader(frag);
338  auto fragLoc = t.WriteFragmentHeader(hdr);
339  memcpy(fragLoc, frag->dataBegin(), 4 * sizeof(artdaq::RawDataType));
340  t.DoneWritingFragment(hdr);
341  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 1);
342  //BOOST_REQUIRE_EQUAL(t.GetInactiveEventCount(), 0);
343  BOOST_REQUIRE_EQUAL(t.GetFragmentCount(1), 1);
344  BOOST_REQUIRE_EQUAL(t.GetArtEventCount(), 0);
345  }
346  {
347  frag->setSequenceID(2);
348  frag->setFragmentID(0);
349 
350  auto hdr = GetHeader(frag);
351  auto fragLoc = t.WriteFragmentHeader(hdr);
352  memcpy(fragLoc, frag->dataBegin(), 4 * sizeof(artdaq::RawDataType));
353  t.DoneWritingFragment(hdr);
354  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 2);
355  //BOOST_REQUIRE_EQUAL(t.GetInactiveEventCount(), 0);
356  BOOST_REQUIRE_EQUAL(t.GetFragmentCount(2), 1);
357  BOOST_REQUIRE_EQUAL(t.GetArtEventCount(), 0);
358 
359  frag->setFragmentID(1);
360  hdr = GetHeader(frag);
361  auto fragLoc2 = t.WriteFragmentHeader(hdr);
362  memcpy(fragLoc2, frag->dataBegin(), 4 * sizeof(artdaq::RawDataType));
363  t.DoneWritingFragment(hdr);
364  BOOST_REQUIRE_EQUAL(t.GetPendingEventCount(), 0);
365  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 1);
366  //BOOST_REQUIRE_EQUAL(t.GetInactiveEventCount(), 0);
367  //BOOST_REQUIRE_EQUAL(t.GetFragmentCount(2), 2);
368  BOOST_REQUIRE_EQUAL(t.GetArtEventCount(), 1);
369  BOOST_REQUIRE_EQUAL(fragLoc + frag->size(), fragLoc2); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
370  }
371  {
372  frag->setSequenceID(3);
373  frag->setFragmentID(0);
374 
375  auto hdr = GetHeader(frag);
376  auto fragLoc = t.WriteFragmentHeader(hdr);
377  memcpy(fragLoc, frag->dataBegin(), 4 * sizeof(artdaq::RawDataType));
378  t.DoneWritingFragment(hdr);
379  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 2);
380  //BOOST_REQUIRE_EQUAL(t.GetInactiveEventCount(), 0);
381  BOOST_REQUIRE_EQUAL(t.GetFragmentCount(3), 1);
382  BOOST_REQUIRE_EQUAL(t.GetArtEventCount(), 1);
383 
384  frag->setFragmentID(1);
385  hdr = GetHeader(frag);
386  auto fragLoc2 = t.WriteFragmentHeader(hdr);
387  memcpy(fragLoc2, frag->dataBegin(), 4 * sizeof(artdaq::RawDataType));
388  t.DoneWritingFragment(hdr);
389  BOOST_REQUIRE_EQUAL(t.GetPendingEventCount(), 0);
390  //BOOST_REQUIRE_EQUAL(t.GetInactiveEventCount(), 0);
391  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 1);
392  BOOST_REQUIRE_EQUAL(t.GetArtEventCount(), 2);
393  }
394 
395  sleep(1);
396 
397  {
398  BOOST_REQUIRE_EQUAL(t.GetArtEventCount(), 2);
399  frag->setSequenceID(4);
400  frag->setFragmentID(1);
401  auto hdr = GetHeader(frag);
402  auto fragLoc = t.WriteFragmentHeader(hdr);
403  memcpy(fragLoc, frag->dataBegin(), 4 * sizeof(artdaq::RawDataType));
404  t.DoneWritingFragment(hdr);
405  BOOST_REQUIRE_EQUAL(t.GetPendingEventCount(), 0);
406  //BOOST_REQUIRE_EQUAL(t.GetInactiveEventCount(), 0);
407  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 1);
408  BOOST_REQUIRE_EQUAL(t.GetPendingEventCount() + t.GetArtEventCount(), 3);
409 
410  frag->setFragmentID(1);
411  hdr = GetHeader(frag);
412  auto fragLoc2 = t.WriteFragmentHeader(hdr);
413  memcpy(fragLoc2, frag->dataBegin(), 4 * sizeof(artdaq::RawDataType));
414  t.DoneWritingFragment(hdr);
415  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 0);
416  BOOST_REQUIRE_EQUAL(t.GetPendingEventCount() + t.GetArtEventCount(), 4);
417  }
418  {
419  frag->setSequenceID(1);
420  frag->setFragmentID(1);
421  auto hdr = GetHeader(frag);
422  auto fragLoc2 = t.WriteFragmentHeader(hdr);
423 #if !ART_SUPPORTS_DUPLICATE_EVENTS
424  BOOST_REQUIRE_EQUAL(fragLoc2, t.GetDroppedDataAddress(hdr));
425 #endif
426  memcpy(fragLoc2, frag->dataBegin(), 4 * sizeof(artdaq::RawDataType));
427  t.DoneWritingFragment(hdr);
428  BOOST_REQUIRE_EQUAL(t.GetPendingEventCount(), 0);
429  //BOOST_REQUIRE_EQUAL(t.GetInactiveEventCount(), 0);
430  BOOST_REQUIRE_EQUAL(t.GetOpenEventCount(), 0);
431 #if ART_SUPPORTS_DUPLICATE_EVENTS
432  BOOST_REQUIRE_EQUAL(t.GetArtEventCount(), 5);
433 #else
434  BOOST_REQUIRE_EQUAL(t.GetArtEventCount(), 4);
435 #endif
436  }
437 
438  TLOG(TLVL_INFO) << "Test ConsumeDroppedData_Active END";
439 }
440 
441 BOOST_AUTO_TEST_CASE(RunNumbers)
442 {
443  TLOG(TLVL_INFO) << "Test RunNumbers BEGIN";
444  fhicl::ParameterSet pset;
445  pset.put("use_art", false);
446  pset.put("buffer_count", 2);
447  pset.put("max_event_size_bytes", 1000);
448  pset.put("expected_fragments_per_event", 2);
449  artdaq::SharedMemoryEventManager t(pset, pset);
450 
451  t.startRun(1);
452  BOOST_REQUIRE_EQUAL(t.runID(), 1);
453  BOOST_REQUIRE_EQUAL(t.GetCurrentSubrun(), 1);
454  t.rolloverSubrun();
455  BOOST_REQUIRE_EQUAL(t.runID(), 1);
456  BOOST_REQUIRE_EQUAL(t.GetCurrentSubrun(), 2);
457  t.rolloverSubrun();
458  BOOST_REQUIRE_EQUAL(t.runID(), 1);
459  BOOST_REQUIRE_EQUAL(t.GetCurrentSubrun(), 3);
460 
461  // Check repeated requests for same subrun
462  t.rolloverSubrun(3, 4);
463  t.rolloverSubrun(4, 4);
464  t.rolloverSubrun(5, 4);
465 
466  t.startRun(3);
467  BOOST_REQUIRE_EQUAL(t.runID(), 3);
468  BOOST_REQUIRE_EQUAL(t.GetCurrentSubrun(), 1);
469 
470  artdaq::SharedMemoryEventReceiver r(t.GetKey(), t.GetBroadcastKey());
471  bool errflag = false;
472 
473  t.endRun();
474  bool sts = r.ReadyForRead();
475  BOOST_REQUIRE_EQUAL(sts, true);
476  auto hdr = r.ReadHeader(errflag);
477  BOOST_REQUIRE_EQUAL(errflag, false);
478  BOOST_REQUIRE(hdr != nullptr);
479  if (hdr != nullptr)
480  { // Make static analyzer happy
481  BOOST_REQUIRE_EQUAL(hdr->is_complete, true);
482  BOOST_REQUIRE_EQUAL(hdr->run_id, 3);
483  BOOST_REQUIRE_EQUAL(hdr->subrun_id, 1);
484  }
485  auto frags = r.GetFragmentsByType(errflag, artdaq::Fragment::EndOfRunFragmentType);
486  BOOST_REQUIRE_EQUAL(errflag, false);
487  BOOST_REQUIRE_EQUAL(frags->size(), 1);
488  r.ReleaseBuffer();
489 
490  TLOG(TLVL_INFO) << "Test RunNumbers END";
491 }
492 
493 BOOST_AUTO_TEST_SUITE_END()
The SharedMemoryEventManager is a SharedMemoryManger which tracks events as they are built...