Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-11-23 02:06:21

0001 /*
0002  *  reftobaseprod_t.cppunit.cc
0003  *  CMSSW
0004  *
0005  *  Created by Chris Jones on 02/11/05.
0006  *
0007  */
0008 
0009 #include "cppunit/extensions/HelperMacros.h"
0010 #include <vector>
0011 #include <set>
0012 #include <list>
0013 #include <deque>
0014 #include "DataFormats/Common/interface/RefToBaseProd.h"
0015 
0016 #include "DataFormats/Common/interface/EDProductGetter.h"
0017 #include "DataFormats/Common/interface/OrphanHandle.h"
0018 #include "DataFormats/Common/interface/Wrapper.h"
0019 
0020 #include <iostream>
0021 
0022 #include "DataFormats/Common/interface/IntValues.h"
0023 #include <typeinfo>
0024 
0025 using namespace edm;
0026 using namespace test_with_dictionaries;
0027 
0028 class testRefToBaseProd : public CppUnit::TestFixture {
0029   CPPUNIT_TEST_SUITE(testRefToBaseProd);
0030 
0031   CPPUNIT_TEST(constructTest);
0032   CPPUNIT_TEST(getTest);
0033 
0034   CPPUNIT_TEST_SUITE_END();
0035 
0036 public:
0037   void setUp() {}
0038   void tearDown() {}
0039 
0040   void constructTest();
0041   void comparisonTest();
0042   void getTest();
0043 };
0044 
0045 ///registration of the test so that the runner can find it
0046 CPPUNIT_TEST_SUITE_REGISTRATION(testRefToBaseProd);
0047 
0048 namespace {
0049   struct Dummy {
0050     Dummy() {}
0051     virtual ~Dummy() {}
0052     bool operator==(Dummy const& iRHS) const { return this == &iRHS; }
0053     bool operator<(Dummy const& iRHS) const { return this->address() < iRHS.address(); }
0054     void const* address() const { return this; }
0055   };
0056 
0057   typedef std::vector<Dummy> DummyCollection;
0058 
0059   typedef std::set<Dummy> DummySet;
0060   typedef std::list<Dummy> DummyList;
0061   typedef std::deque<Dummy> DummyDeque;
0062 
0063   struct Dummy2 : public Dummy {
0064     Dummy2() {}
0065     virtual ~Dummy2() {}
0066   };
0067 
0068   typedef std::vector<Dummy2> DummyCollection2;
0069 
0070   template <typename T, typename C>
0071   void compareTo(const RefToBaseProd<T>& iProd, C const& iContainer) {
0072     unsigned int index = 0;
0073     for (auto const& item : iContainer) {
0074       CPPUNIT_ASSERT(&((*iProd.get())[index++]) == &item);
0075     }
0076     index = 0;
0077     for (auto const& item : iContainer) {
0078       CPPUNIT_ASSERT(&((*iProd)[index++]) == &item);
0079     }
0080     index = 0;
0081     for (auto const& item : iContainer) {
0082       CPPUNIT_ASSERT(&((*(iProd.operator->()))[index++]) == &item);
0083     }
0084     index = 0;
0085     for (auto const& item : iContainer) {
0086       CPPUNIT_ASSERT(&(iProd->at(index++)) == &item);
0087     }
0088   }
0089 }  // namespace
0090 
0091 void testRefToBaseProd::constructTest() {
0092   RefToBaseProd<Dummy> nulled;
0093   CPPUNIT_ASSERT(!nulled);
0094   CPPUNIT_ASSERT(nulled.isNull());
0095   CPPUNIT_ASSERT(!nulled.isNonnull());
0096   CPPUNIT_ASSERT(!nulled.isAvailable());
0097 
0098   RefToBaseProd<Dummy> nulledP;
0099   CPPUNIT_ASSERT(!nulledP);
0100   CPPUNIT_ASSERT(nulledP.isNull());
0101   CPPUNIT_ASSERT(!nulledP.isNonnull());
0102   CPPUNIT_ASSERT(!nulledP.isAvailable());
0103 
0104   ProductID const pid(1, 1);
0105 
0106   {
0107     Dummy const dummy;
0108     DummyCollection dummyContainer;
0109     dummyContainer.push_back(dummy);
0110     dummyContainer.push_back(dummy);
0111     dummyContainer.push_back(dummy);
0112     OrphanHandle<DummyCollection> handle(&dummyContainer, pid);
0113     RefToBaseProd<Dummy> dummyPtr(handle);
0114 
0115     CPPUNIT_ASSERT(!dummyPtr.isNull());
0116     CPPUNIT_ASSERT(dummyPtr.isNonnull());
0117     CPPUNIT_ASSERT(dummyPtr.isAvailable());
0118     CPPUNIT_ASSERT(dummyPtr.id() == pid);
0119     compareTo(dummyPtr, dummyContainer);
0120   }
0121 
0122   {
0123     Dummy const dummy;
0124     DummySet dummyContainer;
0125     dummyContainer.insert(dummy);
0126     dummyContainer.insert(dummy);
0127     dummyContainer.insert(dummy);
0128     OrphanHandle<DummySet> handle(&dummyContainer, pid);
0129     RefToBaseProd<Dummy> dummyPtr(handle);
0130 
0131     CPPUNIT_ASSERT(dummyPtr.id() == pid);
0132     compareTo(dummyPtr, dummyContainer);
0133   }
0134 
0135   {
0136     Dummy const dummy;
0137     DummyList dummyContainer;
0138     dummyContainer.push_back(dummy);
0139     dummyContainer.push_back(dummy);
0140     dummyContainer.push_back(dummy);
0141     OrphanHandle<DummyList> handle(&dummyContainer, pid);
0142     RefToBaseProd<Dummy> dummyPtr(handle);
0143 
0144     CPPUNIT_ASSERT(dummyPtr.id() == pid);
0145     compareTo(dummyPtr, dummyContainer);
0146   }
0147 
0148   {
0149     Dummy const dummy;
0150     DummyDeque dummyContainer;
0151     dummyContainer.push_back(dummy);
0152     dummyContainer.push_back(dummy);
0153     dummyContainer.push_back(dummy);
0154     OrphanHandle<DummyDeque> handle(&dummyContainer, pid);
0155     RefToBaseProd<Dummy> dummyPtr(handle);
0156 
0157     CPPUNIT_ASSERT(dummyPtr.id() == pid);
0158     compareTo(dummyPtr, dummyContainer);
0159   }
0160 
0161   {
0162     Dummy2 const dummy;
0163     DummyCollection2 dummyContainer;
0164     dummyContainer.push_back(dummy);
0165     dummyContainer.push_back(dummy);
0166     dummyContainer.push_back(dummy);
0167     OrphanHandle<DummyCollection2> handle(&dummyContainer, pid);
0168     RefToBaseProd<Dummy> dummyPtr(handle);
0169     RefToBaseProd<Dummy> dummyPtr2(dummyPtr);
0170 
0171     CPPUNIT_ASSERT(dummyPtr.id() == pid);
0172     compareTo(dummyPtr, dummyContainer);
0173 
0174     CPPUNIT_ASSERT(dummyPtr2.id() == pid);
0175     compareTo(dummyPtr2, dummyContainer);
0176 
0177     RefToBaseProd<Dummy> dummyPtr3(std::move(dummyPtr2));
0178     CPPUNIT_ASSERT(dummyPtr3.id() == pid);
0179     compareTo(dummyPtr3, dummyContainer);
0180   }
0181 }
0182 
0183 namespace {
0184   struct TestGetter : public edm::EDProductGetter {
0185     WrapperBase const* hold_;
0186     WrapperBase const* getIt(ProductID const&) const override { return hold_; }
0187     std::optional<std::tuple<edm::WrapperBase const*, unsigned int>> getThinnedProduct(ProductID const&,
0188                                                                                        unsigned int) const override {
0189       return std::nullopt;
0190     }
0191 
0192     void getThinnedProducts(ProductID const& pid,
0193                             std::vector<WrapperBase const*>& wrappers,
0194                             std::vector<unsigned int>& keys) const override {}
0195 
0196     edm::OptionalThinnedKey getThinnedKeyFrom(ProductID const&, unsigned int, ProductID const&) const override {
0197       return std::monostate{};
0198     }
0199 
0200     unsigned int transitionIndex_() const override { return 0U; }
0201 
0202     TestGetter() : hold_() {}
0203   };
0204 }  // namespace
0205 
0206 void testRefToBaseProd::getTest() {
0207   {
0208     typedef std::vector<IntValue> IntCollection;
0209     auto ptr = std::make_unique<IntCollection>();
0210 
0211     ptr->push_back(0);
0212     ptr->push_back(1);
0213 
0214     edm::Wrapper<IntCollection> wrapper(std::move(ptr));
0215     TestGetter tester;
0216     tester.hold_ = &wrapper;
0217 
0218     ProductID const pid(1, 1);
0219 
0220     IntCollection const* wptr = dynamic_cast<IntCollection const*>(wrapper.product());
0221 
0222     OrphanHandle<IntCollection> handle(wptr, pid);
0223 
0224     //NOTE: ROOT will touch the private variables directly and since the RefToBaseProd
0225     // has no constructor which takes RefCore, I have to play this dirty trick
0226     assert(sizeof(edm::RefCore) == sizeof(edm::RefToBaseProd<IntValue>));
0227 
0228     RefCore core(pid, nullptr, &tester, false);
0229     RefToBaseProd<IntValue>& prod = reinterpret_cast<RefToBaseProd<IntValue>&>(core);
0230     CPPUNIT_ASSERT(!prod.isNull());
0231     CPPUNIT_ASSERT(prod.isNonnull());
0232     CPPUNIT_ASSERT(prod.isAvailable());
0233 
0234     //previously making a copy before reading back would cause seg fault
0235     RefToBaseProd<IntValue> prodCopy(prod);
0236     CPPUNIT_ASSERT(!prodCopy.isNull());
0237     CPPUNIT_ASSERT(prodCopy.isNonnull());
0238     CPPUNIT_ASSERT(prodCopy.isAvailable());
0239 
0240     CPPUNIT_ASSERT(!prod.hasCache());
0241 
0242     CPPUNIT_ASSERT(0 != prod.get());
0243     CPPUNIT_ASSERT(prod.hasCache());
0244     compareTo(prod, *wptr);
0245 
0246     CPPUNIT_ASSERT(!prodCopy.hasCache());
0247 
0248     CPPUNIT_ASSERT(0 != prodCopy.get());
0249     CPPUNIT_ASSERT(prodCopy.hasCache());
0250     compareTo(prodCopy, *wptr);
0251   }
0252   {
0253     typedef std::vector<IntValue2> SDCollection;
0254     auto ptr = std::make_unique<SDCollection>();
0255 
0256     ptr->push_back(IntValue2(0));
0257     ptr->back().value_ = 0;
0258     ptr->push_back(IntValue2(1));
0259     ptr->back().value_ = 1;
0260 
0261     edm::Wrapper<SDCollection> wrapper(std::move(ptr));
0262     TestGetter tester;
0263     tester.hold_ = &wrapper;
0264 
0265     ProductID const pid(1, 1);
0266 
0267     SDCollection const* wptr = dynamic_cast<SDCollection const*>(wrapper.product());
0268 
0269     OrphanHandle<SDCollection> handle(wptr, pid);
0270 
0271     //NOTE: ROOT will touch the private variables directly and since the RefToBaseProd
0272     // has no constructor which takes RefCore, I have to play this dirty trick
0273     assert(sizeof(edm::RefCore) == sizeof(edm::RefToBaseProd<IntValue>));
0274 
0275     RefCore core(pid, nullptr, &tester, false);
0276     RefToBaseProd<IntValue>& prod = reinterpret_cast<RefToBaseProd<IntValue>&>(core);
0277 
0278     CPPUNIT_ASSERT(!prod.hasCache());
0279 
0280     CPPUNIT_ASSERT(0 != prod.get());
0281     CPPUNIT_ASSERT(prod.hasCache());
0282     compareTo(prod, *wptr);
0283   }
0284 
0285   {
0286     TestGetter tester;
0287     tester.hold_ = nullptr;
0288     ProductID const pid(1, 1);
0289 
0290     //NOTE: ROOT will touch the private variables directly and since the RefToBaseProd
0291     // has no constructor which takes RefCore, I have to play this dirty trick
0292     assert(sizeof(edm::RefCore) == sizeof(edm::RefToBaseProd<IntValue>));
0293 
0294     RefCore core(pid, nullptr, &tester, false);
0295     RefToBaseProd<IntValue>& prod = reinterpret_cast<RefToBaseProd<IntValue>&>(core);
0296 
0297     CPPUNIT_ASSERT_THROW((*prod), cms::Exception);
0298     CPPUNIT_ASSERT_THROW((prod.operator->()), cms::Exception);
0299   }
0300 }