Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:03:56

0001 #include "SimpleEDProductGetter.h"
0002 
0003 #include "DataFormats/Common/interface/EDProductGetter.h"
0004 #include "DataFormats/Common/interface/Ref.h"
0005 #include "FWCore/Utilities/interface/EDMException.h"
0006 #include "Utilities/Testing/interface/CppUnit_testdriver.icpp"
0007 
0008 #include "cppunit/extensions/HelperMacros.h"
0009 
0010 #include <iostream>
0011 #include <string>
0012 #include <utility>
0013 
0014 #include <thread>
0015 #include <atomic>
0016 
0017 class TestRef : public CppUnit::TestFixture {
0018   CPPUNIT_TEST_SUITE(TestRef);
0019   CPPUNIT_TEST(default_ctor);
0020   //CPPUNIT_TEST(default_ctor_string_key);
0021   CPPUNIT_TEST(nondefault_ctor);
0022   //CPPUNIT_TEST(nondefault_ctor_2);
0023   CPPUNIT_TEST(using_wrong_productid);
0024   CPPUNIT_TEST(threading);
0025   CPPUNIT_TEST_SUITE_END();
0026 
0027 public:
0028   typedef std::vector<int> product1_t;
0029   typedef std::map<std::string, int> product2_t;
0030 
0031   typedef edm::Ref<product1_t> ref1_t;
0032   //typedef edm::Ref<product2_t, int> ref2_t;
0033 
0034   TestRef() {}
0035   ~TestRef() {}
0036   void setUp() {}
0037   void tearDown() {}
0038 
0039   void default_ctor();
0040   // void default_ctor_string_key();
0041   void default_ctor_with_active_getter();
0042   void nondefault_ctor();
0043   // void nondefault_ctor_2();
0044   void using_wrong_productid();
0045   void threading();
0046 
0047 private:
0048 };
0049 
0050 CPPUNIT_TEST_SUITE_REGISTRATION(TestRef);
0051 
0052 void TestRef::default_ctor() {
0053   ref1_t default_ref;
0054   CPPUNIT_ASSERT(default_ref.isNull());
0055   CPPUNIT_ASSERT(default_ref.isNonnull() == false);
0056   CPPUNIT_ASSERT(!default_ref);
0057   CPPUNIT_ASSERT(default_ref.productGetter() == 0);
0058   CPPUNIT_ASSERT(default_ref.id().isValid() == false);
0059   CPPUNIT_ASSERT(default_ref.isAvailable() == false);
0060 }
0061 
0062 // void TestRef::default_ctor_string_key() {
0063 //   ref2_t default_ref;
0064 //   CPPUNIT_ASSERT(default_ref.isNull());
0065 //   CPPUNIT_ASSERT(default_ref.isNonnull()==false);
0066 //   CPPUNIT_ASSERT(!default_ref);
0067 //   CPPUNIT_ASSERT(default_ref.productGetter()==0);
0068 //   CPPUNIT_ASSERT(default_ref.id().isValid()==false);
0069 //   CPPUNIT_ASSERT(default_ref.id().isAvailable()==false);
0070 // }
0071 
0072 void TestRef::nondefault_ctor() {
0073   SimpleEDProductGetter getter;
0074 
0075   edm::ProductID id(1, 201U);
0076   CPPUNIT_ASSERT(id.isValid());
0077 
0078   auto prod = std::make_unique<product1_t>();
0079   prod->push_back(1);
0080   prod->push_back(2);
0081   getter.addProduct(id, std::move(prod));
0082 
0083   ref1_t ref0(id, 0, &getter);
0084   CPPUNIT_ASSERT(ref0.isNull() == false);
0085   CPPUNIT_ASSERT(ref0.isNonnull());
0086   CPPUNIT_ASSERT(!!ref0);
0087   CPPUNIT_ASSERT(ref0.productGetter() == &getter);
0088   CPPUNIT_ASSERT(ref0.id().isValid());
0089   CPPUNIT_ASSERT(ref0.isAvailable() == true);
0090   CPPUNIT_ASSERT(*ref0 == 1);
0091 
0092   ref1_t ref1(id, 1, &getter);
0093   CPPUNIT_ASSERT(ref1.isNonnull());
0094   CPPUNIT_ASSERT(ref1.isAvailable() == true);
0095   CPPUNIT_ASSERT(*ref1 == 2);
0096 
0097   // Note that nothing stops one from making an edm::Ref into a
0098   // collection using an index that is invalid. So there is no testing
0099   // of such use to be done.
0100 }
0101 
0102 // void TestRef::nondefault_ctor_2() {
0103 //   SimpleEDProductGetter getter;
0104 
0105 //   edm::EDProductGetter::Operate op(&getter);
0106 //   edm::ProductID id(1, 201U);
0107 //   CPPUNIT_ASSERT(id.isValid());
0108 
0109 //   auto prod = std::make_unique<product2_t>();
0110 //   prod->insert(std::make_pair(std::string("a"), 1));
0111 //   prod->insert(std::make_pair(std::string("b"), 2));
0112 //   prod->insert(std::make_pair(std::string("c"), 3));
0113 //   getter.addProduct(id, prod);
0114 
0115 //   ref2_t refa(id, std::string("a"), &getter);
0116 //   CPPUNIT_ASSERT(refa.isNull()==false);
0117 //   CPPUNIT_ASSERT(refa.isNonnull());
0118 //   CPPUNIT_ASSERT(!!refa);
0119 //   CPPUNIT_ASSERT(refa.productGetter()==&getter);
0120 //   CPPUNIT_ASSERT(refa.id().isValid());
0121 //   CPPUNIT_ASSERT(*refa == 1);
0122 
0123 //   ref2_t refb(id, "b", &getter);
0124 //   CPPUNIT_ASSERT(refb.isNonnull());
0125 //   CPPUNIT_ASSERT(*refb == 2);
0126 // }
0127 
0128 void TestRef::using_wrong_productid() {
0129   SimpleEDProductGetter getter;
0130 
0131   edm::ProductID id(1, 1U);
0132   CPPUNIT_ASSERT(id.isValid());
0133 
0134   auto prod = std::make_unique<product1_t>();
0135   prod->push_back(1);
0136   prod->push_back(2);
0137   getter.addProduct(id, std::move(prod));
0138 
0139   edm::ProductID wrong_id(1, 100U);
0140   CPPUNIT_ASSERT(wrong_id.isValid());  // its valid, but not used.
0141 
0142   ref1_t ref(wrong_id, 0, &getter);
0143   CPPUNIT_ASSERT_THROW(*ref, edm::Exception);
0144   CPPUNIT_ASSERT_THROW(ref.operator->(), edm::Exception);
0145 }
0146 
0147 namespace {
0148   constexpr int kNThreads = 8;
0149   std::atomic<int> s_threadsStarting{kNThreads};
0150 }  // namespace
0151 void TestRef::threading() {
0152   SimpleEDProductGetter getter;
0153 
0154   edm::ProductID id(1, 1U);
0155   CPPUNIT_ASSERT(id.isValid());
0156 
0157   auto prod = std::make_unique<product1_t>();
0158   prod->push_back(1);
0159   prod->push_back(2);
0160   getter.addProduct(id, std::move(prod));
0161 
0162   ref1_t ref0(id, 0, &getter);
0163   ref1_t ref1(id, 1, &getter);
0164 
0165   std::vector<std::thread> threads;
0166   std::vector<std::exception_ptr> excepPtrs(kNThreads, std::exception_ptr{});
0167 
0168   for (unsigned int i = 0; i < kNThreads; ++i) {
0169     threads.emplace_back([&ref0, &ref1, i, &excepPtrs]() {
0170       --s_threadsStarting;
0171       while (0 != s_threadsStarting) {
0172       }
0173       try {
0174         CPPUNIT_ASSERT(*ref0 == 1);
0175         CPPUNIT_ASSERT(*ref1 == 2);
0176       } catch (...) {
0177         excepPtrs[i] = std::current_exception();
0178       }
0179     });
0180   }
0181   for (auto& t : threads) {
0182     t.join();
0183   }
0184 
0185   for (auto& e : excepPtrs) {
0186     if (e) {
0187       std::rethrow_exception(e);
0188     }
0189   }
0190 }