AssnsAnalyzer_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: AssnsAnalyzer
3 // Module Type: analyzer
4 // File: AssnsAnalyzer_module.cc
5 //
6 // Generated at Wed Jul 13 14:36:05 2011 by Chris Green using artmod
7 // from art v0_07_12.
8 ////////////////////////////////////////////////////////////////////////
10 
17 #include "canvas/Persistency/Common/FindMany.h"
18 #include "canvas/Persistency/Common/FindManyP.h"
19 #include "canvas/Persistency/Common/FindOne.h"
20 #include "canvas/Persistency/Common/FindOneP.h"
24 #include "cetlib/maybe_ref.h"
25 
26 #include "boost/type_traits.hpp"
27 
28 #include <initializer_list>
29 #include <iostream>
30 #include <type_traits>
31 
32 typedef size_t A_t;
33 typedef std::string B_t;
38 
39 namespace arttest {
40  class AssnsAnalyzer;
41 }
42 
44 public:
45  struct Config {
49  fhicl::Atom<bool> bCollMissing{fhicl::Name{"bCollMissing"}, false};
50  };
52  explicit AssnsAnalyzer(Parameters const& p);
53 
54 private:
55  void analyze(art::Event const& e) override;
56 
57  template <template <typename, typename> class FO>
58  void testOne(art::Event const& e) const;
59 
60  template <template <typename, typename> class FM>
61  void testMany(art::Event const& e) const;
62 
64  bool testAB_;
65  bool testBA_;
69 };
70 
71 namespace {
72 
73  // function template to allow us to dereference both maybe_ref<T>
74  // objects and objects that have an operator*.
75  template <class R, class W>
76  R const& dereference(W const& wrapper);
77 
78  // Common case, can dereference (eg Ptr<T>).
79  template <typename T, template <typename> class WRAP>
80  std::enable_if_t<boost::has_dereference<WRAP<T>>::value, T const&>
81  dereference(WRAP<T> const& wrapper)
82  {
83  return *wrapper;
84  }
85 
86  // maybe_ref<T>.
87  template <typename T, template <typename> class WRAP>
88  std::enable_if_t<std::is_same<WRAP<T>, cet::maybe_ref<T>>::value, T const&>
89  dereference(WRAP<T> const& wrapper)
90  {
91  return wrapper.ref();
92  }
93 
94  // These are the expected answers; they are global data used in
95  // check_get_one_impl.
96  char const* const X[] = {"zero", "one", "two"};
97  char const* const A[] = {"A", "B", "C"};
98  size_t const AI[] = {2, 0, 1}; // Order in Acoll
99  size_t const BI[] = {1, 2, 0}; // Order in Bcoll
100 
101  // check_get_one_impl is the common implementation for the check_get
102  // functions.
103  template <typename I, typename D, typename F, typename FV>
104  void
105  check_get_one_impl(F const& fA, FV const& fAV)
106  {
107  I item;
108  D data;
109  for (size_t i = 0; i < 3; ++i) {
110  fA.get(i, item, data);
111  BOOST_CHECK_EQUAL(dereference(item), BI[i]);
112  BOOST_CHECK_EQUAL(dereference(data).d1, AI[i]);
113  BOOST_CHECK_EQUAL(dereference(data).d2, i);
114  fAV.get(i, item);
115  BOOST_CHECK_EQUAL(dereference(item), BI[i]);
116  }
117  }
118 
119  // check_get tests that both fA and fAV both contain the
120  // expected information, as recorded in the global variables.
121  // Each looks like:
122  // template <typename T, typename D, template <typename, typename> class F>
123  // void
124  // check_get(F<T,D> const&, F<T,void> const&);
125  // with complications using enable_if to control which overload is
126  // called in a given case.
127 
128  // check_get specialized for FindOne
129  template <typename T, typename D, template <typename, typename> class FO>
130  std::enable_if_t<std::is_same<FO<T, void>, art::FindOne<T, void>>::value>
131  check_get(FO<T, D> const& fA, FO<T, void> const& fAV)
132  {
133  typedef cet::maybe_ref<typename FO<T, void>::assoc_t const> item_t;
134  typedef cet::maybe_ref<typename FO<T, D>::data_t const> data_t;
135  check_get_one_impl<item_t, data_t>(fA, fAV);
136  }
137 
138  // check_get specialized for FindOneP
139  template <typename T, typename D, template <typename, typename> class FO>
140  std::enable_if_t<std::is_same<FO<T, void>, art::FindOneP<T, void>>::value>
141  check_get(FO<T, D> const& fA, FO<T, void> const& fAV)
142  {
144  typedef cet::maybe_ref<typename FO<T, D>::data_t const> data_t;
145  check_get_one_impl<item_t, data_t>(fA, fAV);
146  }
147 
148  // check_get specialized for FindMany and FindManyP
149  template <typename T, typename D, template <typename, typename> class FM>
150  std::enable_if_t<std::is_same<FM<T, void>, art::FindMany<T, void>>::value ||
151  std::is_same<FM<T, void>, art::FindManyP<T, void>>::value>
152  check_get(FM<T, D> const& fA, FM<T, void> const& fAV)
153  {
154  typename FM<T, void>::value_type item;
155  typename FM<T, D>::dataColl_t::value_type data;
156  BOOST_CHECK_EQUAL((fAV.get(0ul, item)), 1ul);
157  BOOST_CHECK_EQUAL((fAV.get(1ul, item)), 2ul);
158  BOOST_CHECK_EQUAL((fAV.get(2ul, item)), 1ul);
159  BOOST_CHECK_EQUAL((fA.get(0ul, item, data)), 1ul);
160  BOOST_CHECK_EQUAL((fA.get(1ul, item, data)), 2ul);
161  BOOST_CHECK_EQUAL((fA.get(2ul, item, data)), 1ul);
162  }
163 } // namespace
164 
166  : art::EDAnalyzer{p}
167  , inputLabel_{p().input_label()}
168  , testAB_{p().test_AB()}
169  , testBA_{p().test_BA()}
170  , bCollMissing_{p().bCollMissing()}
171  , mapVecToken1_{consumes<AssnsAB_t>({inputLabel_, "mapvec"})}
172  , mapVecToken2_{consumes<AssnsBA_t>({inputLabel_, "mapvec"})}
173 {
174  consumes<AssnsAB_t>(inputLabel_);
175  consumes<AssnsABV_t>(inputLabel_);
176  consumes<AssnsBA_t>(inputLabel_);
177  consumes<AssnsBAV_t>(inputLabel_);
178  consumes<std::vector<A_t>>(inputLabel_);
179  consumes<std::vector<B_t>>(inputLabel_);
180  consumes<AssnsAB_t>({inputLabel_, "many"});
181  consumes<AssnsAB_t>("noModule");
182  consumes<AssnsABV_t>({inputLabel_, "many"});
183  consumes<AssnsABV_t>({inputLabel_, "manymapvec"});
184 }
185 
186 void
188 {
189  testOne<art::FindOne>(e);
190  testOne<art::FindOneP>(e);
191 
192  testMany<art::FindMany>(e);
193  testMany<art::FindManyP>(e);
194 }
195 
196 template <template <typename, typename = void> class FO>
197 void
199 {
200  // Behavior on missing bColl is different for FindOne vs FindOneP.
201  static constexpr bool isFOP =
202  std::is_same<typename FO<B_t>::value_type,
204  bool const extendedTestsOK = isFOP || (!bCollMissing_);
209  if (testAB_) {
211  BOOST_REQUIRE_EQUAL(hAB->size(), 3ul);
213  BOOST_REQUIRE_EQUAL(hABV->size(), 3ul);
214  // Check alternative accessors and range checking for Assns.
215  BOOST_CHECK_THROW((*hAB).at(3), std::out_of_range);
216  BOOST_CHECK_EQUAL(&(*hAB).data(0), &(*hAB).data((*hAB).begin()));
217  BOOST_CHECK_THROW((*hAB).data(3), std::out_of_range);
218  }
219  if (testBA_) {
221  BOOST_REQUIRE_EQUAL(hBA->size(), 3ul);
223  BOOST_REQUIRE_EQUAL(hBAV->size(), 3ul);
224  // Check alternative accessors and range checking for Assns.
225  BOOST_CHECK_THROW((*hBA).at(3), std::out_of_range);
226  BOOST_CHECK_EQUAL(&(*hBA).data(0), &(*hBA).data((*hBA).begin()));
227  BOOST_CHECK_THROW((*hBA).data(3), std::out_of_range);
228  }
229  // Construct a FO using a handle to a collection.
232  auto vhAcoll = e.getValidHandle<std::vector<A_t>>(inputLabel_);
233  // First, check we can make an FO on a non-existent label without
234  // barfing immediately.
235  FO<B_t, arttest::AssnTestData> foDead(hAcoll, e, "noModule");
236  BOOST_REQUIRE(!foDead.isValid());
237  BOOST_REQUIRE_EXCEPTION(
238  foDead.size(), art::Exception, [](art::Exception const& e) {
239  return e.categoryCode() == art::errors::LogicError &&
240  e.history().back() == "ProductNotFound";
241  });
242  BOOST_REQUIRE_EXCEPTION(
243  foDead.data(0), art::Exception, [](art::Exception const& e) {
244  return e.categoryCode() == art::errors::LogicError &&
245  e.history().back() == "ProductNotFound";
246  });
247 
248  // Now do our normal checks.
250  BOOST_REQUIRE_EQUAL(e.getByLabel(inputLabel_, hBcoll), !bCollMissing_);
251  std::unique_ptr<FO<A_t, arttest::AssnTestData>> foA;
252  std::unique_ptr<FO<A_t>> foAV;
253  if (!bCollMissing_) {
254  foA.reset(new FO<A_t, arttest::AssnTestData>{hBcoll, e, inputLabel_});
255  foAV.reset(new FO<A_t>{hBcoll, e, inputLabel_});
256  }
257  if (extendedTestsOK) {
258  FO<B_t, arttest::AssnTestData> foB(hAcoll, e, inputLabel_);
259  FO<B_t, arttest::AssnTestData> foB2(vhAcoll, e, inputLabel_);
260  FO<B_t> foBV(hAcoll, e, inputLabel_);
261  std::vector<art::Ptr<A_t>> vp;
262  vp.reserve(3);
263  for (size_t i = 0; i < 3; ++i) {
264  vp.emplace_back(hAcoll, i);
265  if (testAB_) {
266  BOOST_CHECK_EQUAL(*(*hAB)[i].first, i);
267  if (!bCollMissing_) {
268  BOOST_CHECK_EQUAL(*(*hAB)[i].second, std::string(X[i]));
269  }
270  BOOST_CHECK_EQUAL((*hAB).data(i).d1, (*hAB)[i].first.key());
271  BOOST_CHECK_EQUAL((*hAB).data(i).d2, (*hAB)[i].second.key());
272  BOOST_CHECK_EQUAL((*hAB).data(i).label, std::string(A[i]));
273  BOOST_CHECK_EQUAL(*(*hABV)[i].first, i);
274  if (!bCollMissing_) {
275  BOOST_CHECK_EQUAL(*(*hABV)[i].second, std::string(X[i]));
276  }
277  }
278  if (testBA_) {
279  if (!bCollMissing_) {
280  BOOST_CHECK_EQUAL(*(*hBA)[i].first, std::string(X[i]));
281  }
282  BOOST_CHECK_EQUAL(*(*hBA)[i].second, i);
283  BOOST_CHECK_EQUAL((*hBA).data(i).d2, (*hBA)[i].first.key());
284  BOOST_CHECK_EQUAL((*hBA).data(i).d1, (*hBA)[i].second.key());
285  BOOST_CHECK_EQUAL((*hBA).data(i).label, std::string(A[i]));
286  if (!bCollMissing_) {
287  BOOST_CHECK_EQUAL(*(*hBAV)[i].first, std::string(X[i]));
288  }
289  BOOST_CHECK_EQUAL(*(*hBAV)[i].second, i);
290  }
291  if (bCollMissing_) {
292  BOOST_CHECK(!foBV.at(i));
293  } else {
294  BOOST_CHECK_EQUAL(dereference(foBV.at(i)), std::string(X[AI[i]]));
295  BOOST_CHECK_EQUAL(dereference(foA->at(i)), BI[i]);
296  BOOST_CHECK_EQUAL(dereference(foA->data(i)).d1, AI[i]);
297  BOOST_CHECK_EQUAL(dereference(foA->data(i)).d2, i);
298  BOOST_CHECK_EQUAL(dereference(foAV->at(i)), BI[i]);
299  BOOST_CHECK_NO_THROW(check_get(*foA, *foAV));
300  }
301  for (auto const& f : {foB, foB2}) {
302  if (!bCollMissing_) {
303  BOOST_CHECK_EQUAL(dereference(f.at(i)), std::string(X[AI[i]]));
304  }
305  BOOST_CHECK_EQUAL(dereference(f.data(i)).d1, i);
306  BOOST_CHECK_EQUAL(dereference(f.data(i)).d2, BI[i]);
307  }
308  }
309  // Check FindOne on View.
310  art::View<A_t> va;
312  FO<B_t, arttest::AssnTestData> foBv(va, e, inputLabel_);
313  BOOST_REQUIRE(foB == foBv);
314  art::View<B_t> vb;
315  std::unique_ptr<FO<A_t, arttest::AssnTestData>> foAv;
316  if (!bCollMissing_) {
318  foAv.reset(new FO<A_t, arttest::AssnTestData>{vb, e, inputLabel_});
319  BOOST_REQUIRE(*foA == *foAv);
320  }
321  // Check FindOne on shuffled reference collection.
322  auto va2 = va.vals(); // Copy.
323  {
324  using std::swap;
325  swap(*va2.begin(), *(va2.begin() + 1));
326  swap(*va2.begin(), *(va2.begin() + 2));
327  }
328  BOOST_REQUIRE(va.vals() != va2);
329  FO<B_t, arttest::AssnTestData> foBv2(va2, e, inputLabel_);
330  for (size_t i = 0, e = foBv2.size(); i != e; ++i) {
331  using std::find;
332  auto it = find(va.begin(), va.end(), va2[i]);
333  BOOST_REQUIRE(it != va.end());
334  BOOST_REQUIRE(foBv.at(std::distance(va.begin(), it)) == foBv2.at(i));
335  }
336  // Check FindOne on PtrVector.
337  va.vals()[1] = 0;
339  va.fill(pva);
340  FO<B_t, arttest::AssnTestData> foBpv(pva, e, inputLabel_);
341  BOOST_CHECK_EQUAL(foBpv.at(0), foB.at(0));
342  BOOST_CHECK_EQUAL(foBpv.data(0), foB.data(0));
343  BOOST_CHECK_EQUAL(foBpv.at(1), foB.at(2)); // Knocked out the middle.
344  BOOST_CHECK_EQUAL(foBpv.data(1), foB.data(2));
346  if (!bCollMissing_) {
347  vb.vals()[1] = 0;
348  vb.fill(pvb);
349  }
350  FO<A_t, arttest::AssnTestData> foApv(pvb, e, inputLabel_);
351  // Check for range errors.
352  BOOST_CHECK_THROW(foApv.at(3), std::out_of_range);
353  BOOST_CHECK_THROW(foApv.data(3), std::out_of_range);
354 
355  if (!bCollMissing_) {
356  BOOST_CHECK_EQUAL(foApv.at(0), foA->at(0));
357  BOOST_CHECK_EQUAL(foApv.data(0), foA->data(0));
358  BOOST_CHECK_EQUAL(foApv.at(1), foA->at(2)); // Knocked out the middle.
359  BOOST_CHECK_EQUAL(foApv.data(1), foA->data(2));
360  }
361 
362  // Check FindOne looking into a map_vector.
363  BOOST_REQUIRE(hAcoll.isValid());
364  FO<B_t, arttest::AssnTestData> foBmv(hAcoll, e, mapVecToken1_);
365  if (!bCollMissing_) {
366  BOOST_CHECK_EQUAL(dereference(foBmv.at(0)), dereference(foB.at(0)));
367  BOOST_CHECK_EQUAL(dereference(foBmv.data(0)).label,
368  dereference(foB.data(0)).label);
369  BOOST_CHECK_EQUAL(dereference(foBmv.at(1)), dereference(foB.at(1)));
370  BOOST_CHECK_EQUAL(dereference(foBmv.data(1)).label,
371  dereference(foB.data(1)).label);
372  BOOST_CHECK_EQUAL(dereference(foBmv.at(2)), dereference(foB.at(2)));
373  BOOST_CHECK_EQUAL(dereference(foBmv.data(2)).label,
374  dereference(foB.data(2)).label);
375  }
376  // ... and a View into a map_vector.
377  art::View<B_t> vmvb;
378  if (!bCollMissing_) {
379  BOOST_REQUIRE(e.getView(inputLabel_, "mv", vmvb));
380  FO<A_t, arttest::AssnTestData> foAmvv(vmvb, e, mapVecToken2_);
381  for (std::size_t i = 0ul, sz = foAmvv.size(); i != sz; ++i) {
382  BOOST_REQUIRE_EQUAL(dereference(foAmvv.at(i)), i);
383  }
384  }
385  }
386 }
387 
388 template <template <typename, typename = void> class FM>
389 void
391 {
392  static constexpr bool isFMP[[gnu::unused]] =
393  std::is_same<typename FM<B_t>::value_type,
397 
398  // First, check we can make an FM on a non-existent label without
399  // barfing immediately.
400  FM<B_t, arttest::AssnTestData> fmDead(hAcoll, e, "noModule");
401  BOOST_REQUIRE(!fmDead.isValid());
402  BOOST_REQUIRE_EXCEPTION(
403  fmDead.size(), art::Exception, [](art::Exception const& e) {
404  return e.categoryCode() == art::errors::LogicError &&
405  e.history().back() == "ProductNotFound";
406  });
407  BOOST_REQUIRE_EXCEPTION(
408  fmDead.data(0), art::Exception, [](art::Exception const& e) {
409  return e.categoryCode() == art::errors::LogicError &&
410  e.history().back() == "ProductNotFound";
411  });
412 
413  // Now do our normal checks.
414  // Check FindMany.
415  FM<B_t, arttest::AssnTestData> fmB(
416  hAcoll, e, art::InputTag(inputLabel_, "many"));
417  art::Ptr<A_t> larry(hAcoll, 0), curly(hAcoll, 1), mo(hAcoll, 2);
418  FM<B_t, arttest::AssnTestData> fmB2(
419  {larry, curly, mo}, e, art::InputTag(inputLabel_, "many"));
420  for (auto const& f : {fmB, fmB2}) {
421  BOOST_REQUIRE_EQUAL(f.size(), 3ul);
422  BOOST_CHECK_EQUAL(f.at(0).size(), 1ul);
423  BOOST_CHECK_EQUAL(f.at(1).size(), 2ul);
424  BOOST_CHECK_EQUAL(f.at(2).size(), 1ul);
425  BOOST_CHECK_EQUAL(f.data(0).size(), 1ul);
426  BOOST_CHECK_EQUAL(f.data(1).size(), 2ul);
427  BOOST_CHECK_EQUAL(f.data(2).size(), 1ul);
428  }
429  FM<B_t> fmBV(hAcoll, e, art::InputTag(inputLabel_, "many"));
430  BOOST_CHECK_EQUAL(fmBV.at(0).size(), 1ul);
431  BOOST_CHECK_EQUAL(fmBV.at(1).size(), 2ul);
432  BOOST_CHECK_EQUAL(fmBV.at(2).size(), 1ul);
433  BOOST_CHECK_NO_THROW(check_get(fmB, fmBV));
434  // Check FindMany on View.
435  art::View<A_t> va;
436  BOOST_REQUIRE(e.getView(inputLabel_, va));
437  FM<B_t> fmBv(va, e, art::InputTag(inputLabel_, "many"));
438  BOOST_REQUIRE(fmBV == fmBv);
439  // Check FindMany on shuffled reference collection.
440  auto va2 = va.vals(); // Copy.
441  {
442  using std::swap;
443  swap(*va2.begin(), *(va2.begin() + 1));
444  swap(*va2.begin(), *(va2.begin() + 2));
445  }
446  BOOST_REQUIRE(va.vals() != va2);
447  FM<B_t> fmBv2(va2, e, art::InputTag(inputLabel_, "many"));
448  for (size_t i = 0, e = fmBv2.size(); i != e; ++i) {
449  using std::find;
450  auto it = find(va.begin(), va.end(), va2[i]);
451  BOOST_REQUIRE(it != va.end());
452  BOOST_REQUIRE(fmBv.at(std::distance(va.begin(), it)) == fmBv2.at(i));
453  }
454 
455  // Check FindMany on map_vector
456  FM<B_t> fmvBV(hAcoll, e, art::InputTag(inputLabel_, "manymapvec"));
457  if (!bCollMissing_) {
458  BOOST_CHECK_EQUAL(fmvBV.at(0).size(), 1ul);
459  BOOST_CHECK_EQUAL(fmvBV.at(1).size(), 2ul);
460  BOOST_CHECK_EQUAL(fmvBV.at(2).size(), 1ul);
461  BOOST_CHECK_NO_THROW(check_get(fmB, fmBV));
462  }
463 }
464 
size_type size() const
Definition: Assns.h:447
static const double second
Definition: Units.h:35
art::Assns< B_t, size_t, arttest::AssnTestData > AssnsBA_t
void analyze(art::Event const &e) override
art::Assns< A_t, B_t, arttest::AssnTestData > AssnsAB_t
std::string string
Definition: nybbler.cc:12
art::Assns< A_t, B_t > AssnsABV_t
AssnsAnalyzer(Parameters const &p)
auto end()
Definition: View.h:98
EDAnalyzer(fhicl::ParameterSet const &pset)
Definition: EDAnalyzer.h:27
void fill(PtrVector< T > &pv) const
Definition: View.h:158
fhicl::Atom< std::string > input_label
details::dereference_class< T, details::has_dereference_class< T >::value >::reference_type dereference(T &v)
Returns the value pointed by the argument, or the argument itself.
Definition: Dereference.h:254
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
Definition: DataViewImpl.h:435
auto begin()
Definition: View.h:92
const double e
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:68
History const & history() const
void swap(Handle< T > &a, Handle< T > &b)
size_t A_t
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
Definition: DataViewImpl.h:480
Definition: fwd.h:43
art::ProductToken< AssnsBA_t > mapVecToken2_
void testMany(art::Event const &e) const
auto vals() -> auto &
Definition: View.h:76
BOOST_REQUIRE(inFile)
p
Definition: test.py:228
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
std::string B_t
art::ProductToken< AssnsAB_t > mapVecToken1_
std::size_t getView(std::string const &moduleLabel, std::string const &productInstanceName, std::string const &processName, std::vector< ELEMENT const * > &result) const
Definition: DataViewImpl.h:525
void testOne(art::Event const &e) const
art::Assns< B_t, size_t > AssnsBAV_t
Definition: fwd.h:26