Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:53:06

0001 /*
0002  *  CMSSW
0003  */
0004 
0005 #include "DataFormats/Common/interface/DetSetVector.h"
0006 #include "DataFormats/Common/interface/Ref.h"
0007 #include "DataFormats/Common/interface/TestHandle.h"
0008 #include "DataFormats/Provenance/interface/ProductID.h"
0009 
0010 #include <algorithm>
0011 #include <cassert>
0012 #include <iterator>
0013 #include <ostream>
0014 #include <stdexcept>
0015 #include <vector>
0016 
0017 using namespace edm;
0018 
0019 //------------------------------------------------------
0020 // This is a sample VALUE class, almost the simplest possible.
0021 //------------------------------------------------------
0022 namespace {
0023   bool is_null(const void* iPtr) { return iPtr == nullptr; }
0024 }  // namespace
0025 
0026 struct Empty {};
0027 
0028 template <typename BASE>
0029 class ValueT : public BASE {
0030 public:
0031   // VALUES must be default constructible
0032   ValueT() : d_(0.0) {}
0033 
0034   // This constructor is used for testing; it is not required by the
0035   // concept VALUE.
0036   explicit ValueT(double d) : d_(d) {}
0037 
0038   // This access function is used for testing; it is not required by
0039   // the concept VALUE.
0040   double val() const { return d_; }
0041 
0042   // VALUES must be destructible
0043   ~ValueT() {}
0044 
0045   // VALUES must be LessThanComparable
0046   bool operator<(ValueT const& other) const { return d_ < other.d_; }
0047 
0048   // The private stuff below is all implementation detail, and not
0049   // required by the concept VALUE.
0050 private:
0051   double d_;
0052 };
0053 
0054 typedef edm::DoNotSortUponInsertion DNS;
0055 
0056 template <>
0057 bool ValueT<DNS>::operator<(ValueT<DNS> const& /*other*/) const {
0058   throw std::logic_error("You can't sort me!");
0059 }
0060 
0061 typedef ValueT<Empty> Value;
0062 //typedef ValueT<DNS> Value; // NoSort;
0063 
0064 //------------------------------------------------------
0065 // The stream insertion operator is not required; it is used here
0066 // for diagnostic output.
0067 //
0068 // It is inline to avoid multiple definition problems. Note that this
0069 // cc file is *not* a compilation unit; it is actually an include
0070 // file, which the build system combines with others to create a
0071 // compilation unit.
0072 //
0073 //------------------------------------------------------
0074 
0075 template <typename BASE>
0076 std::ostream& operator<<(std::ostream& os, ValueT<BASE> const& v) {
0077   os << " val: " << v.val();
0078   return os;
0079 }
0080 
0081 typedef edm::DetSetVector<Value> coll_type;
0082 typedef coll_type::detset detset;
0083 
0084 void check_outer_collection_order(coll_type const& c) {
0085   if (c.size() < 2)
0086     return;
0087   coll_type::const_iterator i = c.begin();
0088   coll_type::const_iterator e = c.end();
0089   // Invariant: sequence from prev to i is correctly ordered
0090   coll_type::const_iterator prev(i);
0091   ++i;
0092   for (; i != e; ++i, ++prev) {
0093     // We don't use CPPUNIT_ASSERT because it gives us grossly
0094     // insufficient context if a failure occurs.
0095     assert(prev->id < i->id);
0096   }
0097 }
0098 
0099 void check_inner_collection_order(detset const& d) {
0100   if (d.data.size() < 2)
0101     return;
0102   detset::const_iterator i = d.data.begin();
0103   detset::const_iterator e = d.data.end();
0104   // Invariant: sequence from prev to i is correctly ordered
0105   detset::const_iterator prev(i);
0106   ++i;
0107   for (; i != e; ++i, ++prev) {
0108     // We don't use CPPUNIT_ASSERT because it gives us grossly
0109     // insufficient context if a failure occurs.
0110     //
0111     // We don't check that *prev < *i because they might be equal.
0112     // We don't want to require an op<= or op==.
0113     assert(!(*i < *prev));
0114   }
0115 }
0116 
0117 void printDetSet(detset const& ds, std::ostream& os) {
0118   os << "size: " << ds.data.size() << '\n' << "values: ";
0119   std::copy(ds.data.begin(), ds.data.end(), std::ostream_iterator<detset::value_type>(os, " "));
0120 }
0121 
0122 void sanity_check(coll_type const& c) {
0123   check_outer_collection_order(c);
0124   for (coll_type::const_iterator i = c.begin(), e = c.end(); i != e; ++i) {
0125     //       printDetSet(*i, std::cerr);
0126     //       std::cerr << '\n';
0127     check_inner_collection_order(*i);
0128   }
0129 }
0130 
0131 void check_ids(coll_type const& c) {
0132   // Long way to get all ids...
0133   std::vector<det_id_type> all_ids;
0134   for (coll_type::const_iterator i = c.begin(), e = c.end(); i != e; ++i) {
0135     all_ids.push_back(i->id);
0136   }
0137   assert(c.size() == all_ids.size());
0138 
0139   std::vector<det_id_type> nice_ids;
0140   c.getIds(nice_ids);
0141   assert(all_ids == nice_ids);
0142 }
0143 
0144 void detsetTest() {
0145   //std::cerr << "\nStart DetSetVector_t detsetTest()\n";
0146   detset d;
0147   Value v1(1.1);
0148   Value v2(2.2);
0149   d.id = edm::det_id_type(3);
0150   d.data.push_back(v1);
0151   d.data.push_back(v2);
0152   std::sort(d.data.begin(), d.data.end());
0153   check_inner_collection_order(d);
0154   //std::cerr << "\nEnd DetSetVector_t detsetTest()\n";
0155 }
0156 
0157 namespace {
0158   template <typename T>
0159   struct DSVGetter : edm::EDProductGetter {
0160     DSVGetter() : edm::EDProductGetter(), prod_(nullptr) {}
0161     WrapperBase const* getIt(ProductID const&) const override { return prod_; }
0162 
0163     std::optional<std::tuple<edm::WrapperBase const*, unsigned int>> getThinnedProduct(ProductID const&,
0164                                                                                        unsigned int) const override {
0165       return std::nullopt;
0166     }
0167 
0168     void getThinnedProducts(ProductID const& pid,
0169                             std::vector<WrapperBase const*>& wrappers,
0170                             std::vector<unsigned int>& keys) const override {}
0171 
0172     edm::OptionalThinnedKey getThinnedKeyFrom(ProductID const&, unsigned int, ProductID const&) const override {
0173       return std::monostate{};
0174     }
0175 
0176     unsigned int transitionIndex_() const override { return 0U; }
0177 
0178     edm::Wrapper<T> const* prod_;
0179   };
0180 }  // namespace
0181 
0182 void refTest() {
0183   coll_type c;
0184   detset d3;
0185   Value v1(1.1);
0186   Value v2(2.2);
0187   d3.id = edm::det_id_type(3);
0188   d3.data.push_back(v1);
0189   d3.data.push_back(v2);
0190   c.insert(d3);
0191   detset d1;
0192   Value v1a(4.1);
0193   Value v2a(3.2);
0194   d1.id = edm::det_id_type(1);
0195   d1.data.push_back(v1a);
0196   d1.data.push_back(v2a);
0197   c.insert(d1);
0198   c.post_insert();
0199 
0200   auto pC = std::make_unique<coll_type>(c);
0201   edm::Wrapper<coll_type> wrapper(std::move(pC));
0202   DSVGetter<coll_type> theGetter;
0203   theGetter.prod_ = &wrapper;
0204 
0205   typedef edm::Ref<coll_type, detset> RefDetSet;
0206   typedef edm::Ref<coll_type, Value> RefDet;
0207 
0208   {
0209     RefDetSet refSet(edm::ProductID(1, 1), 0, &theGetter);
0210     assert(!(d1 < *refSet) && !(*refSet < d1));
0211   }
0212   {
0213     RefDetSet refSet(edm::ProductID(1, 1), 1, &theGetter);
0214     assert(!(d3 < *refSet) && !(*refSet < d3));
0215   }
0216   {
0217     RefDet refDet(edm::ProductID(1, 1), RefDet::key_type(3, 0), &theGetter);
0218     assert(!(v1 < *refDet) && !(*refDet < v1));
0219   }
0220 
0221   {
0222     TestHandle<coll_type> pc2(&c, ProductID(1, 1));
0223     RefDet refDet = makeRefToDetSetVector(pc2, det_id_type(3), c[3].data.begin());
0224     assert(!(v1 < *refDet) && !(*refDet < v1));
0225   }
0226 
0227   try {
0228     //bad detid
0229     TestHandle<coll_type> pc2(&c, ProductID(1, 1));
0230     RefDet refDet = makeRefToDetSetVector(pc2, det_id_type(12), c[3].data.begin());
0231 
0232     assert("Failed to throw required exception" == 0);
0233   } catch (edm::Exception const& x) {
0234     //std::cout <<x.what()<<std::endl;
0235     // Test we have the right exception category
0236     assert(x.categoryCode() == edm::errors::InvalidReference);
0237   }
0238 
0239   try {
0240     //bad iterator
0241     TestHandle<coll_type> pc2(&c, ProductID(1, 1));
0242     RefDet refDet = makeRefToDetSetVector(pc2, det_id_type(1), c[3].data.begin());
0243 
0244     assert("Failed to throw required exception" == 0);
0245   } catch (edm::Exception const& x) {
0246     //std::cout <<x.what()<<std::endl;
0247     // Test we have the right exception category
0248     assert(x.categoryCode() == edm::errors::InvalidReference);
0249   }
0250 }
0251 
0252 void work() {
0253   detsetTest();
0254   refTest();
0255 
0256   coll_type c1;
0257   c1.post_insert();
0258   sanity_check(c1);
0259   assert(c1.size() == 0);
0260   assert(c1.empty());
0261 
0262   coll_type c2(c1);
0263   assert(c2.size() == c1.size());
0264   sanity_check(c2);
0265   coll_type c;
0266   sanity_check(c);
0267   {
0268     detset d;
0269     Value v1(1.1);
0270     Value v2(2.2);
0271     d.id = edm::det_id_type(3);
0272     d.data.push_back(v1);
0273     d.data.push_back(v2);
0274     c.insert(d);
0275     c.post_insert();
0276   }
0277   sanity_check(c);
0278   assert(c.size() == 1);
0279   {
0280     detset d;
0281     Value v1(4.1);
0282     Value v2(3.2);
0283     d.id = edm::det_id_type(1);
0284     d.data.push_back(v1);
0285     d.data.push_back(v2);
0286     c.insert(d);
0287     c.post_insert();
0288   }
0289   sanity_check(c);
0290   assert(c.size() == 2);
0291 
0292   {
0293     detset d;
0294     Value v1(1.1);
0295     Value v2(1.2);
0296     Value v3(2.2);
0297     d.id = edm::det_id_type(10);
0298     d.data.push_back(v3);
0299     d.data.push_back(v2);
0300     d.data.push_back(v1);
0301     c.insert(d);
0302     c.post_insert();
0303   }
0304   sanity_check(c);
0305   assert(c.size() == 3);
0306 
0307   coll_type another;
0308   c.swap(another);
0309   assert(c.empty());
0310   assert(another.size() == 3);
0311   sanity_check(c);
0312   sanity_check(another);
0313 
0314   c.swap(another);
0315   assert(c.size() == 3);
0316 
0317   {
0318     // We should not find anything with ID=11
0319     coll_type::iterator i = c.find(edm::det_id_type(11));
0320     assert(i == c.end());
0321 
0322     coll_type::const_iterator ci = static_cast<coll_type const&>(c).find(edm::det_id_type(11));
0323     assert(ci == c.end());
0324   }
0325   {
0326     // We should find  ID=10
0327     coll_type::iterator i = c.find(edm::det_id_type(10));
0328     assert(i != c.end());
0329     assert(i->id == 10);
0330     assert(i->data.size() == 3);
0331   }
0332 
0333   {
0334     // We should not find ID=100; op[] should throw.
0335     try {
0336       coll_type::reference r = c[edm::det_id_type(100)];
0337       assert("Failed to throw required exception" == 0);
0338       assert(is_null(&r));  // to silence warning of unused r
0339     } catch (edm::Exception const& x) {
0340       // Test we have the right exception category
0341       assert(x.categoryCode() == edm::errors::InvalidReference);
0342     } catch (...) {
0343       assert("Failed to throw correct exception type" == 0);
0344     }
0345   }
0346 
0347   {
0348     // We should not find ID=100; op[] should throw.
0349     try {
0350       coll_type::const_reference r = static_cast<coll_type const&>(c)[edm::det_id_type(100)];
0351       assert("Failed to throw required exception" == 0);
0352       assert(is_null(&r));  // to silence warning of unused r
0353     } catch (edm::Exception const& x) {
0354       // Test we have the right exception category
0355       assert(x.categoryCode() == edm::errors::InvalidReference);
0356     } catch (...) {
0357       assert("Failed to throw correct exception type" == 0);
0358     }
0359   }
0360   {
0361     // We should find id = 3
0362     coll_type const& rc = c;
0363     coll_type::const_reference r = rc[3];
0364     assert(r.id == edm::det_id_type(3));
0365     assert(r.data.size() == 2);
0366 
0367     coll_type::reference r2 = c[3];
0368     assert(r2.id == edm::det_id_type(3));
0369     assert(r2.data.size() == 2);
0370   }
0371 
0372   {
0373     // We should not find id = 17, but a new empty DetSet should be
0374     // inserted, carrying the correct DetId.
0375     coll_type::size_type oldsize = c.size();
0376     coll_type::reference r = c.find_or_insert(edm::det_id_type(17));
0377     coll_type::size_type newsize = c.size();
0378     assert(newsize > oldsize);
0379     assert(newsize == (oldsize + 1));
0380     assert(r.id == edm::det_id_type(17));
0381     assert(r.data.size() == 0);
0382     r.data.push_back(Value(10.1));
0383     r.data.push_back(Value(9.1));
0384     r.data.push_back(Value(4.0));
0385     r.data.push_back(Value(4.0));
0386     c.post_insert();
0387     sanity_check(c);
0388   }
0389   {
0390     // Make sure we can swap in a vector.
0391     unsigned int const numDetSets = 20;
0392     unsigned int const detSetSize = 14;
0393     std::vector<detset> v;
0394     for (unsigned int i = 0; i < numDetSets; ++i) {
0395       detset d(i);
0396       for (unsigned int j = 0; j < detSetSize; ++j) {
0397         d.data.push_back(Value(100 * i + 1.0 / j));
0398       }
0399       v.push_back(d);
0400     }
0401     assert(v.size() == numDetSets);
0402     coll_type c3(v);
0403     c3.post_insert();
0404     assert(v.size() == 0);
0405     assert(c3.size() == numDetSets);
0406     sanity_check(c3);
0407 
0408     coll_type c4;
0409     c4 = c3;
0410     assert(c4.size() == numDetSets);
0411     sanity_check(c3);
0412     sanity_check(c4);
0413 
0414     check_ids(c3);
0415   }
0416 }
0417 
0418 int main() {
0419   int rc = -1;
0420   try {
0421     work();
0422     rc = 0;
0423   } catch (edm::Exception const& x) {
0424     //std::cerr << "Exception: " << x << '\n';
0425     rc = 1;
0426   } catch (std::exception& x) {
0427     //std::cerr << "standard exception: " << x.what() << '\n';
0428     rc = 3;
0429   } catch (...) {
0430     //std::cerr << "Unknown exception\n";
0431     rc = 2;
0432   }
0433   return rc;
0434 }