artdaq  v2_03_00
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Pages
raw_event_queue_reader_t.cc
1 #include "artdaq/ArtModules/detail/RawEventQueueReader.hh"
2 
3 #include "art/Framework/Core/FileBlock.h"
4 //#include "art/Framework/Core/RootDictionaryManager.h"
5 #include "art/Framework/IO/Sources/SourceHelper.h"
6 #include "art/Framework/Principal/Event.h"
7 #include "art/Framework/Principal/EventPrincipal.h"
8 #include "art/Framework/Principal/Handle.h"
9 #include "art/Framework/Principal/RunPrincipal.h"
10 #include "art/Framework/Principal/SubRunPrincipal.h"
11 #include "art/Persistency/Provenance/BranchIDListHelper.h"
12 #include "art/Persistency/Provenance/MasterProductRegistry.h"
13 #include "art/Persistency/Provenance/ProductMetaData.h"
14 #include "canvas/Persistency/Provenance/EventID.h"
15 #include "canvas/Persistency/Provenance/FileFormatVersion.h"
16 #include "canvas/Persistency/Provenance/ModuleDescription.h"
17 #include "canvas/Persistency/Provenance/Parentage.h"
18 #include "canvas/Persistency/Provenance/ProcessConfiguration.h"
19 #include "canvas/Persistency/Provenance/RunID.h"
20 #include "canvas/Persistency/Provenance/SubRunID.h"
21 #include "canvas/Persistency/Provenance/Timestamp.h"
22 #include "canvas/Utilities/Exception.h"
23 #include "canvas/Utilities/GetPassID.h"
24 #include "art/Version/GetReleaseVersion.h"
25 #include "artdaq-core/Core/GlobalQueue.hh"
26 #include "artdaq-core/Data/Fragment.hh"
27 #include "fhiclcpp/make_ParameterSet.h"
28 
29 #define BOOST_TEST_MODULE ( raw_event_queue_reader_t )
30 #include "boost/test/auto_unit_test.hpp"
31 
32 #include <iostream>
33 #include <memory>
34 #include <string>
35 
40 {
41 public:
46 
50  typedef std::map<std::string, art::BranchKey> BKmap_t;
51 
53  std::map<std::string, std::unique_ptr<art::ProcessConfiguration>> processConfigurations_;
54 
64  art::ProcessConfiguration*
65  fake_single_module_process(std::string const& tag,
66  std::string const& processName,
67  fhicl::ParameterSet const& moduleParams,
68  std::string const& release = art::getReleaseVersion(),
69  std::string const& pass = art::getPassID());
70 
78  std::unique_ptr<art::BranchDescription>
79  fake_single_process_branch(std::string const& tag,
80  std::string const& processName,
81  std::string const& productInstanceName = std::string());
82 
86  void finalize();
87 
88  art::MasterProductRegistry productRegistry_;
89  //art::RootDictionaryManager rdm_;
90 };
91 
93  :
94  branchKeys_()
95  , processConfigurations_()
96  , productRegistry_()//,
97 // rdm_()
98 {
99  // We can only insert products registered in the MasterProductRegistry.
100  productRegistry_.addProduct(fake_single_process_branch("hlt", "HLT"));
101  productRegistry_.addProduct(fake_single_process_branch("prod", "PROD"));
102  productRegistry_.addProduct(fake_single_process_branch("test", "TEST"));
103  productRegistry_.addProduct(fake_single_process_branch("user", "USER"));
104  productRegistry_.addProduct(fake_single_process_branch("rick", "USER2", "rick"));
105 }
106 
107 void
109 {
110  productRegistry_.setFrozen();
111  art::BranchIDListHelper::updateRegistries(productRegistry_);
112  art::ProductMetaData::create_instance(productRegistry_);
113 }
114 
115 art::ProcessConfiguration*
117 fake_single_module_process(std::string const& tag,
118  std::string const& processName,
119  fhicl::ParameterSet const& moduleParams,
120  std::string const& release,
121  std::string const& pass)
122 {
123  fhicl::ParameterSet processParams;
124  processParams.put(processName, moduleParams);
125  processParams.put<std::string>("process_name",
126  processName);
127  auto emplace_pair =
128  processConfigurations_.emplace(tag,
129  std::make_unique<art::ProcessConfiguration>(processName, processParams.id(), release, pass));
130  return emplace_pair.first->second.get();
131 }
132 
133 std::unique_ptr<art::BranchDescription>
135 fake_single_process_branch(std::string const& tag,
136  std::string const& processName,
137  std::string const& productInstanceName)
138 {
139  std::string moduleLabel = processName + "dummyMod";
140  std::string moduleClass("DummyModule");
141  fhicl::ParameterSet modParams;
142  modParams.put<std::string>("module_type", moduleClass);
143  modParams.put<std::string>("module_label", moduleLabel);
144  art::ProcessConfiguration* process =
145  fake_single_module_process(tag, processName, modParams);
146  art::ModuleDescription mod(modParams.id(),
147  moduleClass,
148  moduleLabel,
149  *process);
150  art::TypeID dummyType(typeid(int));
151  art::BranchDescription* result =
152  new art::BranchDescription(art::TypeLabel(art::InEvent,
153  dummyType,
154  productInstanceName),
155  mod);
156  branchKeys_.insert(std::make_pair(tag, art::BranchKey(*result)));
157  return std::unique_ptr<art::BranchDescription>(result);
158 }
159 
164 {
169  {
170  static bool once(true);
171  if (once)
172  {
173  (void)reader(); // Force initialization.
174  art::ModuleDescription md(fhicl::ParameterSet().id(),
175  "_NAMEERROR_",
176  "_LABELERROR_",
177  *gf().processConfigurations_["daq"]);
178  // These _xERROR_ strings should never appear in branch names; they
179  // are here as tracers to help identify any failures in coding.
180  helper().registerProducts(gf().productRegistry_, md);
181  gf().finalize();
182  once = false;
183  }
184  }
185 
191  {
192  static MPRGlobalTestFixture mpr;
193  return mpr;
194  }
195 
200  art::ProductRegistryHelper& helper()
201  {
202  static art::ProductRegistryHelper s_helper;
203  return s_helper;
204  }
205 
210  art::SourceHelper& source_helper()
211  {
212  static std::unique_ptr<art::SourceHelper>
213  s_source_helper;
214  if (!s_source_helper)
215  {
216  fhicl::ParameterSet sourceParams;
217  std::string moduleType{ "DummySource" };
218  std::string moduleLabel{ "daq" };
219  sourceParams.put<std::string>("module_type", moduleType);
220  sourceParams.put<std::string>("module_label", moduleLabel);
221  auto pc_ptr = gf().fake_single_module_process(moduleLabel,
222  "TEST",
223  sourceParams);
224  art::ModuleDescription md(sourceParams.id(),
225  moduleType,
226  moduleLabel,
227  *pc_ptr);
228  s_source_helper = std::make_unique<art::SourceHelper>(md);
229  }
230  return *s_source_helper;
231  }
232 
238  {
239  fhicl::ParameterSet pset;
241  s_reader(pset,
242  helper(),
243  source_helper(),
244  gf().productRegistry_);
245  static bool reader_initialized = false;
246  if (!reader_initialized)
247  {
248  s_reader.fragment_type_map_[1] = "ABCDEF";
249  helper().reconstitutes<artdaq::Fragments, art::InEvent>("daq", "ABCDEF");
250  reader_initialized = true;
251  }
252  return s_reader;
253  }
254 };
255 
256 BOOST_FIXTURE_TEST_SUITE(raw_event_queue_reader_t, REQRTestFixture)
257 
258 namespace
259 {
268  std::unique_ptr<art::RunPrincipal>&& run,
269  std::unique_ptr<art::SubRunPrincipal>&& subrun,
270  art::EventID const& eventid)
271  {
272  BOOST_REQUIRE(run || subrun == nullptr); // Sanity check.
273  std::shared_ptr<artdaq::RawEvent> event(new artdaq::RawEvent(eventid.run(), eventid.subRun(), eventid.event()));
274  std::vector<artdaq::Fragment::value_type> fakeData{ 1, 2, 3, 4 };
275  artdaq::FragmentPtr
276  tmpFrag(artdaq::Fragment::dataFrag(eventid.event(),
277  0,
278  fakeData.begin(),
279  fakeData.end()));
280  tmpFrag->setUserType(1);
281  event->insertFragment(std::move(tmpFrag));
282  event->markComplete();
283  artdaq::getGlobalQueue().enqNowait(event);
284  art::EventPrincipal* newevent = nullptr;
285  art::SubRunPrincipal* newsubrun = nullptr;
286  art::RunPrincipal* newrun = nullptr;
287  bool rc = reader.readNext(run.get(), subrun.get(), newrun, newsubrun, newevent);
288  BOOST_REQUIRE(rc);
289  if (run.get() && run->run() == eventid.run())
290  {
291  BOOST_CHECK(newrun == nullptr);
292  }
293  else
294  {
295  BOOST_CHECK(newrun);
296  BOOST_CHECK(newrun->id() == eventid.runID());
297  }
298  if (!newrun && subrun.get() && subrun->subRun() == eventid.subRun())
299  {
300  BOOST_CHECK(newsubrun == nullptr);
301  }
302  else
303  {
304  BOOST_CHECK(newsubrun);
305  BOOST_CHECK(newsubrun->id() == eventid.subRunID());
306  }
307  BOOST_CHECK(newevent);
308  BOOST_CHECK(newevent->id() == eventid);
309  art::Event e(*newevent, art::ModuleDescription());
310  art::Handle<std::vector<artdaq::Fragment>> h;
311  e.getByLabel("daq", "ABCDEF", h);
312  BOOST_CHECK(h.isValid());
313  BOOST_CHECK(h->size() == 1);
314  BOOST_CHECK(std::equal(fakeData.begin(),
315  fakeData.end(),
316  h->front().dataBegin()));
317  delete(newrun);
318  delete(newsubrun);
319  delete(newevent);
320  }
321 }
322 
323 BOOST_AUTO_TEST_CASE(nonempty_event)
324 {
325  art::EventID eventid(2112, 1, 3);
326  art::Timestamp now;
327  basic_test(reader(),
328  std::unique_ptr<art::RunPrincipal>(source_helper().makeRunPrincipal(eventid.run(), now)),
329  std::unique_ptr<art::SubRunPrincipal>(source_helper().makeSubRunPrincipal(eventid.run(), eventid.subRun(), now)),
330  eventid);
331 }
332 
333 BOOST_AUTO_TEST_CASE(first_event)
334 {
335  art::EventID eventid(2112, 1, 3);
336  art::Timestamp now;
337  basic_test(reader(),
338  nullptr,
339  nullptr,
340  eventid);
341 }
342 
343 BOOST_AUTO_TEST_CASE(new_subrun)
344 {
345  art::EventID eventid(2112, 1, 3);
346  art::Timestamp now;
347  basic_test(reader(),
348  std::unique_ptr<art::RunPrincipal>(source_helper().makeRunPrincipal(eventid.run(), now)),
349  std::unique_ptr<art::SubRunPrincipal>(source_helper().makeSubRunPrincipal(eventid.run(), 0, now)),
350  eventid);
351 }
352 
353 BOOST_AUTO_TEST_CASE(new_run)
354 {
355  art::EventID eventid(2112, 1, 3);
356  art::Timestamp now;
357  basic_test(reader(),
358  std::unique_ptr<art::RunPrincipal>(source_helper().makeRunPrincipal(eventid.run() - 1, now)),
359  std::unique_ptr<art::SubRunPrincipal>(source_helper().makeSubRunPrincipal(eventid.run() - 1,
360  eventid.subRun(),
361  now)),
362  eventid);
363 }
364 
365 BOOST_AUTO_TEST_CASE(end_of_data)
366 {
367  // Tell 'reader' the name of the file we are to read. This is pretty
368  // much irrelevant for RawEventQueueReader, but we'll stick to the
369  // interface demanded by Source<T>...
370  std::string const fakeFileName("no such file exists");
371  art::FileBlock* pFile = nullptr;
372  reader().readFile(fakeFileName, pFile);
373  BOOST_CHECK(pFile);
374  BOOST_CHECK(pFile->fileFormatVersion() == art::FileFormatVersion(1, "RawEvent2011"));
375  BOOST_CHECK(pFile->tree() == nullptr);
376 
377  BOOST_CHECK(!pFile->fastClonable());
378  // Test the end-of-data handling. Reading an end-of-data should result in readNext() returning false,
379  // and should return null pointers for new-run, -subrun and -event.
380  // Prepare our 'previous run/subrun/event'..
381  art::RunID runid(2112);
382  art::SubRunID subrunid(2112, 1);
383  art::EventID eventid(2112, 1, 3);
384  art::Timestamp now;
385  std::unique_ptr<art::RunPrincipal> run(source_helper().makeRunPrincipal(runid.run(), now));
386  std::unique_ptr<art::SubRunPrincipal> subrun(source_helper().makeSubRunPrincipal(runid.run(), subrunid.subRun(), now));
387  std::unique_ptr<art::EventPrincipal> event(source_helper().makeEventPrincipal(runid.run(),
388  subrunid.subRun(),
389  eventid.event(),
390  now));
391  artdaq::getGlobalQueue().enqNowait(std::shared_ptr<artdaq::RawEvent>(nullptr)); // insert end-of-data marker
392  art::EventPrincipal* newevent = nullptr;
393  art::SubRunPrincipal* newsubrun = nullptr;
394  art::RunPrincipal* newrun = nullptr;
395  bool rc = reader().readNext(run.get(), subrun.get(), newrun, newsubrun, newevent);
396  BOOST_CHECK(!rc);
397  BOOST_CHECK(newrun == nullptr);
398  BOOST_CHECK(newsubrun == nullptr);
399  BOOST_CHECK(newevent == nullptr);
400 }
401 
402 BOOST_AUTO_TEST_SUITE_END()
bool readNext(art::RunPrincipal *const &inR, art::SubRunPrincipal *const &inSR, art::RunPrincipal *&outR, art::SubRunPrincipal *&outSR, art::EventPrincipal *&outE)
Dequeue a RawEvent and declare its Fragment contents to art, creating Run, SubRun, and EventPrincipal objects as necessary.
std::map< std::string, std::unique_ptr< art::ProcessConfiguration > > processConfigurations_
Configurations.
art::ProductRegistryHelper & helper()
Get an art::ProductRegistryHelper, creating a static instance if necessary.
void finalize()
Finalizes the ProductRegistry.
The RawEventQueueReader is a class which implements the methods needed by art::Source.
art::MasterProductRegistry productRegistry_
MasterProductRegistry instance.
void basic_test(artdaq::detail::RawEventQueueReader &reader, std::unique_ptr< art::RunPrincipal > &&run, std::unique_ptr< art::SubRunPrincipal > &&subrun, art::EventID const &eventid)
Run a basic checkout of the RawEventQueueReader.
art::ProcessConfiguration * fake_single_module_process(std::string const &tag, std::string const &processName, fhicl::ParameterSet const &moduleParams, std::string const &release=art::getReleaseVersion(), std::string const &pass=art::getPassID())
Create the ProcessConfiguration for a single module art process.
std::unique_ptr< art::BranchDescription > fake_single_process_branch(std::string const &tag, std::string const &processName, std::string const &productInstanceName=std::string())
Create a BranchDescription for a process.
MasterProductRegistry Test Fixture.
RawEventQueueReader Test Fixture.
REQRTestFixture()
REQRTestFixture Constructor.
std::map< std::string, art::BranchKey > BKmap_t
BKmap_t associates a string with a art::BranchKey.
MPRGlobalTestFixture()
MPRGlobalTestFixture Constructor.
art::SourceHelper & source_helper()
Get an art::SourceHelper object, creating a static instance if necessary.
std::map< Fragment::type_t, std::string > fragment_type_map_
The Fragment type names that this RawEventQueueReader knows about.
artdaq::detail::RawEventQueueReader & reader()
Get an artdaq::detail::RawEventQueueReader object, creating a static instance if necessary.
MPRGlobalTestFixture & gf()
Get a MPRGlobalTestFixture, creating a static instance if necessary.
BKmap_t branchKeys_
Keys in this test fixture.