Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-05-11 03:34:16

0001 /*
0002  *  esproducer_t.cppunit.cc
0003  *  EDMProto
0004  *
0005  *  Created by Chris Jones on 4/8/05.
0006  *  Changed by Viji Sundararajan on 28-Jun-05
0007  */
0008 #include <iostream>
0009 #include "cppunit/extensions/HelperMacros.h"
0010 #include "FWCore/Framework/interface/EDConsumerBase.h"
0011 #include "FWCore/Framework/interface/ESProducer.h"
0012 #include "FWCore/Framework/test/DummyData.h"
0013 #include "FWCore/Framework/test/Dummy2Record.h"
0014 #include "FWCore/Framework/test/DummyRecord.h"
0015 #include "FWCore/Framework/test/DummyFinder.h"
0016 #include "FWCore/Framework/test/DepOn2Record.h"
0017 #include "FWCore/Framework/test/DepRecord.h"
0018 #include "FWCore/Framework/interface/ESProductResolver.h"
0019 #include "FWCore/Framework/interface/EventSetup.h"
0020 #include "FWCore/Framework/interface/EventSetupProvider.h"
0021 #include "FWCore/Framework/interface/EventSetupRecordKey.h"
0022 #include "FWCore/Framework/src/SynchronousEventSetupsController.h"
0023 #include "FWCore/Framework/interface/es_Label.h"
0024 #include "FWCore/Framework/interface/ESHandle.h"
0025 #include "FWCore/Framework/interface/ESProducts.h"
0026 #include "FWCore/Framework/interface/ESRecordsToProductResolverIndices.h"
0027 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0028 #include "FWCore/ServiceRegistry/interface/ActivityRegistry.h"
0029 #include "FWCore/Utilities/interface/do_nothing_deleter.h"
0030 #include "FWCore/Utilities/interface/Exception.h"
0031 #include "FWCore/Concurrency/interface/ThreadsController.h"
0032 #include "FWCore/Concurrency/interface/FinalWaitingTask.h"
0033 
0034 #include <memory>
0035 #include <optional>
0036 
0037 using edm::eventsetup::test::DummyData;
0038 using namespace edm::eventsetup;
0039 using edm::ESProducer;
0040 using edm::EventSetupRecordIntervalFinder;
0041 
0042 namespace {
0043   edm::ParameterSet createDummyPset() {
0044     edm::ParameterSet pset;
0045     std::vector<std::string> emptyVStrings;
0046     pset.addParameter<std::vector<std::string>>("@all_esprefers", emptyVStrings);
0047     pset.addParameter<std::vector<std::string>>("@all_essources", emptyVStrings);
0048     pset.addParameter<std::vector<std::string>>("@all_esmodules", emptyVStrings);
0049     return pset;
0050   }
0051   edm::ActivityRegistry activityRegistry;
0052 
0053   struct DummyDataConsumerBase : public edm::EDConsumerBase {
0054     void prefetch(edm::EventSetupImpl const& iImpl) const {
0055       auto const& recs = this->esGetTokenRecordIndicesVector(edm::Transition::Event);
0056       auto const& proxies = this->esGetTokenIndicesVector(edm::Transition::Event);
0057       for (size_t i = 0; i != proxies.size(); ++i) {
0058         auto rec = iImpl.findImpl(recs[i]);
0059         if (rec) {
0060           oneapi::tbb::task_group group;
0061           edm::FinalWaitingTask waitTask{group};
0062           rec->prefetchAsync(
0063               edm::WaitingTaskHolder(group, &waitTask), proxies[i], &iImpl, edm::ServiceToken{}, edm::ESParentContext{});
0064           waitTask.wait();
0065         }
0066       }
0067     }
0068   };
0069 
0070   template <typename Record>
0071   struct DummyDataConsumer : public DummyDataConsumerBase {
0072     DummyDataConsumer() : m_token{esConsumes()} {}
0073     edm::ESGetToken<DummyData, Record> m_token;
0074   };
0075 
0076   struct DummyDataConsumer2 : public DummyDataConsumerBase {
0077     DummyDataConsumer2(edm::ESInputTag const& tag1, edm::ESInputTag const& tag2, edm::ESInputTag const& tag3)
0078         : m_token1{esConsumes(tag1)}, m_token2{esConsumes(tag2)}, m_token3{esConsumes(tag3)} {}
0079     edm::ESGetToken<DummyData, DummyRecord> m_token1;
0080     edm::ESGetToken<DummyData, DummyRecord> m_token2;
0081     edm::ESGetToken<DummyData, DummyRecord> m_token3;
0082   };
0083 }  // namespace
0084 
0085 class testEsproducer : public CppUnit::TestFixture {
0086   CPPUNIT_TEST_SUITE(testEsproducer);
0087 
0088   CPPUNIT_TEST(registerTest);
0089   CPPUNIT_TEST(getFromTest);
0090   CPPUNIT_TEST(getFromLambdaTest);
0091   CPPUNIT_TEST(getfromShareTest);
0092   CPPUNIT_TEST(getfromShareTestNull);
0093   CPPUNIT_TEST(getfromUniqueTest);
0094   CPPUNIT_TEST(getfromUniqueTestNull);
0095   CPPUNIT_TEST(getfromOptionalTest);
0096   CPPUNIT_TEST(getfromOptionalTestNull);
0097   CPPUNIT_TEST(decoratorTest);
0098   CPPUNIT_TEST(dependsOnTest);
0099   CPPUNIT_TEST(labelTest);
0100   CPPUNIT_TEST_EXCEPTION(failMultipleRegistration, cms::Exception);
0101   CPPUNIT_TEST(forceCacheClearTest);
0102   CPPUNIT_TEST(productResolverProviderTest);
0103 
0104   CPPUNIT_TEST_SUITE_END();
0105 
0106 public:
0107   void setUp() { m_scheduler = std::make_unique<edm::ThreadsController>(1); }
0108   void tearDown() {}
0109 
0110   void registerTest();
0111   void getFromTest();
0112   void getFromLambdaTest();
0113   void getfromShareTest();
0114   void getfromShareTestNull();
0115   void getfromUniqueTest();
0116   void getfromUniqueTestNull();
0117   void getfromOptionalTest();
0118   void getfromOptionalTestNull();
0119   void decoratorTest();
0120   void dependsOnTest();
0121   void labelTest();
0122   void failMultipleRegistration();
0123   void forceCacheClearTest();
0124   void productResolverProviderTest();
0125 
0126 private:
0127   edm::propagate_const<std::unique_ptr<edm::ThreadsController>> m_scheduler;
0128 
0129   class Test1Producer : public ESProducer {
0130   public:
0131     Test1Producer() { setWhatProduced(this); }
0132     std::shared_ptr<DummyData> produce(const DummyRecord& /*iRecord*/) {
0133       ++data_.value_;
0134       return std::shared_ptr<DummyData>(&data_, edm::do_nothing_deleter{});
0135     }
0136 
0137   private:
0138     DummyData data_{0};
0139   };
0140 
0141   class LambdaProducer : public ESProducer {
0142   public:
0143     LambdaProducer() {
0144       setWhatProduced([data_ = DummyData()](const DummyRecord& /*iRecord*/) mutable {
0145         ++data_.value_;
0146         return std::shared_ptr<DummyData>(&data_, edm::do_nothing_deleter{});
0147       });
0148     }
0149   };
0150 
0151   class OptionalProducer : public ESProducer {
0152   public:
0153     OptionalProducer(bool produce = true) : produce_(produce) { setWhatProduced(this); }
0154     std::optional<DummyData> produce(const DummyRecord& /*iRecord*/) {
0155       ++data_.value_;
0156       if (produce_) {
0157         return data_;
0158       } else {
0159         return {};
0160       }
0161     }
0162 
0163   private:
0164     DummyData data_{0};
0165     const bool produce_;
0166   };
0167 
0168   class MultiRegisterProducer : public ESProducer {
0169   public:
0170     MultiRegisterProducer() {
0171       setWhatProduced(this);
0172       setWhatProduced(this);
0173     }
0174     std::shared_ptr<DummyData> produce(const DummyRecord& /*iRecord*/) {
0175       return std::shared_ptr<DummyData>(&data_, edm::do_nothing_deleter{});
0176     }
0177 
0178   private:
0179     DummyData data_{0};
0180   };
0181 
0182   class ShareProducer : public ESProducer {
0183   public:
0184     ShareProducer(bool produce = true) : produce_(produce) { setWhatProduced(this); }
0185     std::shared_ptr<DummyData> produce(const DummyRecord& /*iRecord*/) {
0186       ++ptr_->value_;
0187       if (produce_) {
0188         return ptr_;
0189       } else {
0190         return nullptr;
0191       }
0192     }
0193 
0194   private:
0195     std::shared_ptr<DummyData> ptr_{std::make_shared<DummyData>(0)};
0196     const bool produce_;
0197   };
0198 
0199   class UniqueProducer : public ESProducer {
0200   public:
0201     UniqueProducer(bool produce = true) : produce_(produce) { setWhatProduced(this); }
0202     std::unique_ptr<DummyData> produce(const DummyRecord&) {
0203       ++data_.value_;
0204       if (produce_) {
0205         return std::make_unique<DummyData>(data_);
0206       } else {
0207         return nullptr;
0208       }
0209     }
0210 
0211   private:
0212     DummyData data_;
0213     const bool produce_;
0214   };
0215 
0216   class LabelledProducer : public ESProducer {
0217   public:
0218     enum { kFi, kFum };
0219     typedef edm::ESProducts<edm::es::L<DummyData, kFi>, edm::es::L<DummyData, kFum>> ReturnProducts;
0220     LabelledProducer() {
0221       setWhatProduced(this, &LabelledProducer::produceMore, edm::es::label("fi", kFi)("fum", kFum));
0222       setWhatProduced(this, "foo");
0223     }
0224 
0225     std::shared_ptr<DummyData> produce(const DummyRecord& /*iRecord*/) {
0226       ++ptr_->value_;
0227       return ptr_;
0228     }
0229 
0230     ReturnProducts produceMore(const DummyRecord&) {
0231       using edm::es::L;
0232       using namespace edm;
0233       ++fi_->value_;
0234 
0235       L<DummyData, kFum> fum(std::make_shared<DummyData>());
0236       fum->value_ = fi_->value_;
0237 
0238       return edm::es::products(fum, es::l<kFi>(fi_));
0239     }
0240 
0241   private:
0242     std::shared_ptr<DummyData> ptr_{std::make_shared<DummyData>(0)};
0243     std::shared_ptr<DummyData> fi_{std::make_shared<DummyData>(0)};
0244   };
0245 };
0246 
0247 ///registration of the test so that the runner can find it
0248 CPPUNIT_TEST_SUITE_REGISTRATION(testEsproducer);
0249 
0250 void testEsproducer::registerTest() {
0251   Test1Producer testProd;
0252   EventSetupRecordKey dummyRecordKey = EventSetupRecordKey::makeKey<DummyRecord>();
0253   EventSetupRecordKey depRecordKey = EventSetupRecordKey::makeKey<DepRecord>();
0254   testProd.createKeyedResolvers(dummyRecordKey, 1);
0255   CPPUNIT_ASSERT(testProd.isUsingRecord(dummyRecordKey));
0256   CPPUNIT_ASSERT(!testProd.isUsingRecord(depRecordKey));
0257   const ESProductResolverProvider::KeyedResolvers& keyedResolvers = testProd.keyedResolvers(dummyRecordKey);
0258 
0259   CPPUNIT_ASSERT(keyedResolvers.size() == 1);
0260 }
0261 
0262 void testEsproducer::getFromTest() {
0263   SynchronousEventSetupsController controller;
0264   edm::ParameterSet pset = createDummyPset();
0265   EventSetupProvider& provider = *controller.makeProvider(pset, &activityRegistry);
0266 
0267   // This manner of adding directly to the EventSetupProvider should work OK in tests
0268   // unless there are multiple EventSetupProviders (the case with SubProcesses).
0269   // Then there would be addition work to do to get things setup properly for the
0270   // functions that check for module sharing between EventSetupProviders.
0271   provider.add(std::make_shared<Test1Producer>());
0272 
0273   auto pFinder = std::make_shared<DummyFinder>();
0274   provider.add(std::shared_ptr<EventSetupRecordIntervalFinder>(pFinder));
0275 
0276   edm::ESParentContext parentC;
0277   for (int iTime = 1; iTime != 6; ++iTime) {
0278     const edm::Timestamp time(iTime);
0279     pFinder->setInterval(edm::ValidityInterval(edm::IOVSyncValue(time), edm::IOVSyncValue(time)));
0280     controller.eventSetupForInstance(edm::IOVSyncValue(time));
0281     DummyDataConsumer<DummyRecord> consumer;
0282     consumer.updateLookup(provider.recordsToResolverIndices());
0283     consumer.prefetch(provider.eventSetupImpl());
0284     const edm::EventSetup eventSetup(provider.eventSetupImpl(),
0285                                      static_cast<unsigned int>(edm::Transition::Event),
0286                                      consumer.esGetTokenIndices(edm::Transition::Event),
0287                                      parentC);
0288     edm::ESHandle<DummyData> pDummy = eventSetup.getHandle(consumer.m_token);
0289     CPPUNIT_ASSERT(0 != pDummy.product());
0290     CPPUNIT_ASSERT(iTime == pDummy->value_);
0291   }
0292 }
0293 
0294 void testEsproducer::getFromLambdaTest() {
0295   SynchronousEventSetupsController controller;
0296   edm::ParameterSet pset = createDummyPset();
0297   EventSetupProvider& provider = *controller.makeProvider(pset, &activityRegistry);
0298 
0299   provider.add(std::make_shared<LambdaProducer>());
0300 
0301   auto pFinder = std::make_shared<DummyFinder>();
0302   provider.add(std::shared_ptr<EventSetupRecordIntervalFinder>(pFinder));
0303 
0304   edm::ESParentContext parentC;
0305   for (int iTime = 1; iTime != 6; ++iTime) {
0306     const edm::Timestamp time(iTime);
0307     pFinder->setInterval(edm::ValidityInterval(edm::IOVSyncValue(time), edm::IOVSyncValue(time)));
0308     controller.eventSetupForInstance(edm::IOVSyncValue(time));
0309     DummyDataConsumer<DummyRecord> consumer;
0310     consumer.updateLookup(provider.recordsToResolverIndices());
0311     consumer.prefetch(provider.eventSetupImpl());
0312     const edm::EventSetup eventSetup(provider.eventSetupImpl(),
0313                                      static_cast<unsigned int>(edm::Transition::Event),
0314                                      consumer.esGetTokenIndices(edm::Transition::Event),
0315                                      parentC);
0316     edm::ESHandle<DummyData> pDummy = eventSetup.getHandle(consumer.m_token);
0317     CPPUNIT_ASSERT(0 != pDummy.product());
0318     CPPUNIT_ASSERT(iTime == pDummy->value_);
0319   }
0320 }
0321 
0322 void testEsproducer::getfromShareTest() {
0323   SynchronousEventSetupsController controller;
0324   edm::ParameterSet pset = createDummyPset();
0325   EventSetupProvider& provider = *controller.makeProvider(pset, &activityRegistry);
0326 
0327   std::shared_ptr<ESProductResolverProvider> pResolverProv = std::make_shared<ShareProducer>();
0328   provider.add(pResolverProv);
0329 
0330   auto pFinder = std::make_shared<DummyFinder>();
0331   provider.add(std::shared_ptr<EventSetupRecordIntervalFinder>(pFinder));
0332 
0333   edm::ESParentContext parentC;
0334   for (int iTime = 1; iTime != 6; ++iTime) {
0335     const edm::Timestamp time(iTime);
0336     pFinder->setInterval(edm::ValidityInterval(edm::IOVSyncValue(time), edm::IOVSyncValue(time)));
0337     controller.eventSetupForInstance(edm::IOVSyncValue(time));
0338     DummyDataConsumer<DummyRecord> consumer;
0339     consumer.updateLookup(provider.recordsToResolverIndices());
0340     consumer.prefetch(provider.eventSetupImpl());
0341     const edm::EventSetup eventSetup(provider.eventSetupImpl(),
0342                                      static_cast<unsigned int>(edm::Transition::Event),
0343                                      consumer.esGetTokenIndices(edm::Transition::Event),
0344                                      parentC);
0345     edm::ESHandle<DummyData> pDummy = eventSetup.getHandle(consumer.m_token);
0346     CPPUNIT_ASSERT(0 != pDummy.product());
0347     CPPUNIT_ASSERT(iTime == pDummy->value_);
0348   }
0349 }
0350 
0351 void testEsproducer::getfromShareTestNull() {
0352   SynchronousEventSetupsController controller;
0353   edm::ParameterSet pset = createDummyPset();
0354   EventSetupProvider& provider = *controller.makeProvider(pset, &activityRegistry);
0355 
0356   std::shared_ptr<ESProductResolverProvider> pResolverProv = std::make_shared<ShareProducer>(false);
0357   provider.add(pResolverProv);
0358 
0359   auto pFinder = std::make_shared<DummyFinder>();
0360   provider.add(std::shared_ptr<EventSetupRecordIntervalFinder>(pFinder));
0361 
0362   edm::ESParentContext parentC;
0363   for (int iTime = 1; iTime != 6; ++iTime) {
0364     const edm::Timestamp time(iTime);
0365     pFinder->setInterval(edm::ValidityInterval(edm::IOVSyncValue(time), edm::IOVSyncValue(time)));
0366     controller.eventSetupForInstance(edm::IOVSyncValue(time));
0367     DummyDataConsumer<DummyRecord> consumer;
0368     consumer.updateLookup(provider.recordsToResolverIndices());
0369     consumer.prefetch(provider.eventSetupImpl());
0370     const edm::EventSetup eventSetup(provider.eventSetupImpl(),
0371                                      static_cast<unsigned int>(edm::Transition::Event),
0372                                      consumer.esGetTokenIndices(edm::Transition::Event),
0373                                      parentC);
0374     CPPUNIT_ASSERT_THROW(eventSetup.getHandle(consumer.m_token), cms::Exception);
0375     CPPUNIT_ASSERT_THROW(eventSetup.getData(consumer.m_token), cms::Exception);
0376   }
0377 }
0378 
0379 void testEsproducer::getfromUniqueTest() {
0380   SynchronousEventSetupsController controller;
0381   edm::ParameterSet pset = createDummyPset();
0382   EventSetupProvider& provider = *controller.makeProvider(pset, &activityRegistry);
0383 
0384   std::shared_ptr<ESProductResolverProvider> pResolverProv = std::make_shared<UniqueProducer>();
0385   provider.add(pResolverProv);
0386 
0387   auto pFinder = std::make_shared<DummyFinder>();
0388   provider.add(std::shared_ptr<EventSetupRecordIntervalFinder>(pFinder));
0389 
0390   edm::ESParentContext parentC;
0391   for (int iTime = 1; iTime != 6; ++iTime) {
0392     const edm::Timestamp time(iTime);
0393     pFinder->setInterval(edm::ValidityInterval(edm::IOVSyncValue(time), edm::IOVSyncValue(time)));
0394     controller.eventSetupForInstance(edm::IOVSyncValue(time));
0395     DummyDataConsumer<DummyRecord> consumer;
0396     consumer.updateLookup(provider.recordsToResolverIndices());
0397     consumer.prefetch(provider.eventSetupImpl());
0398     const edm::EventSetup eventSetup(provider.eventSetupImpl(),
0399                                      static_cast<unsigned int>(edm::Transition::Event),
0400                                      consumer.esGetTokenIndices(edm::Transition::Event),
0401                                      parentC);
0402     edm::ESHandle<DummyData> pDummy = eventSetup.getHandle(consumer.m_token);
0403     CPPUNIT_ASSERT(0 != pDummy.product());
0404     CPPUNIT_ASSERT(iTime == pDummy->value_);
0405   }
0406 }
0407 
0408 void testEsproducer::getfromUniqueTestNull() {
0409   SynchronousEventSetupsController controller;
0410   edm::ParameterSet pset = createDummyPset();
0411   EventSetupProvider& provider = *controller.makeProvider(pset, &activityRegistry);
0412 
0413   std::shared_ptr<ESProductResolverProvider> pResolverProv = std::make_shared<UniqueProducer>(false);
0414   provider.add(pResolverProv);
0415 
0416   auto pFinder = std::make_shared<DummyFinder>();
0417   provider.add(std::shared_ptr<EventSetupRecordIntervalFinder>(pFinder));
0418 
0419   edm::ESParentContext parentC;
0420   for (int iTime = 1; iTime != 6; ++iTime) {
0421     const edm::Timestamp time(iTime);
0422     pFinder->setInterval(edm::ValidityInterval(edm::IOVSyncValue(time), edm::IOVSyncValue(time)));
0423     controller.eventSetupForInstance(edm::IOVSyncValue(time));
0424     DummyDataConsumer<DummyRecord> consumer;
0425     consumer.updateLookup(provider.recordsToResolverIndices());
0426     consumer.prefetch(provider.eventSetupImpl());
0427     const edm::EventSetup eventSetup(provider.eventSetupImpl(),
0428                                      static_cast<unsigned int>(edm::Transition::Event),
0429                                      consumer.esGetTokenIndices(edm::Transition::Event),
0430                                      parentC);
0431     CPPUNIT_ASSERT_THROW(eventSetup.getHandle(consumer.m_token), cms::Exception);
0432     CPPUNIT_ASSERT_THROW(eventSetup.getData(consumer.m_token), cms::Exception);
0433   }
0434 }
0435 
0436 void testEsproducer::getfromOptionalTest() {
0437   SynchronousEventSetupsController controller;
0438   edm::ParameterSet pset = createDummyPset();
0439   EventSetupProvider& provider = *controller.makeProvider(pset, &activityRegistry);
0440 
0441   provider.add(std::make_shared<OptionalProducer>());
0442 
0443   auto pFinder = std::make_shared<DummyFinder>();
0444   provider.add(std::shared_ptr<EventSetupRecordIntervalFinder>(pFinder));
0445 
0446   edm::ESParentContext parentC;
0447   for (int iTime = 1; iTime != 6; ++iTime) {
0448     const edm::Timestamp time(iTime);
0449     pFinder->setInterval(edm::ValidityInterval(edm::IOVSyncValue(time), edm::IOVSyncValue(time)));
0450     controller.eventSetupForInstance(edm::IOVSyncValue(time));
0451     DummyDataConsumer<DummyRecord> consumer;
0452     consumer.updateLookup(provider.recordsToResolverIndices());
0453     consumer.prefetch(provider.eventSetupImpl());
0454     const edm::EventSetup eventSetup(provider.eventSetupImpl(),
0455                                      static_cast<unsigned int>(edm::Transition::Event),
0456                                      consumer.esGetTokenIndices(edm::Transition::Event),
0457                                      parentC);
0458     edm::ESHandle<DummyData> pDummy = eventSetup.getHandle(consumer.m_token);
0459     CPPUNIT_ASSERT(0 != pDummy.product());
0460     CPPUNIT_ASSERT(iTime == pDummy->value_);
0461   }
0462 }
0463 
0464 void testEsproducer::getfromOptionalTestNull() {
0465   SynchronousEventSetupsController controller;
0466   edm::ParameterSet pset = createDummyPset();
0467   EventSetupProvider& provider = *controller.makeProvider(pset, &activityRegistry);
0468 
0469   provider.add(std::make_shared<OptionalProducer>(false));
0470 
0471   auto pFinder = std::make_shared<DummyFinder>();
0472   provider.add(std::shared_ptr<EventSetupRecordIntervalFinder>(pFinder));
0473 
0474   edm::ESParentContext parentC;
0475   for (int iTime = 1; iTime != 6; ++iTime) {
0476     const edm::Timestamp time(iTime);
0477     pFinder->setInterval(edm::ValidityInterval(edm::IOVSyncValue(time), edm::IOVSyncValue(time)));
0478     controller.eventSetupForInstance(edm::IOVSyncValue(time));
0479     DummyDataConsumer<DummyRecord> consumer;
0480     consumer.updateLookup(provider.recordsToResolverIndices());
0481     consumer.prefetch(provider.eventSetupImpl());
0482     const edm::EventSetup eventSetup(provider.eventSetupImpl(),
0483                                      static_cast<unsigned int>(edm::Transition::Event),
0484                                      consumer.esGetTokenIndices(edm::Transition::Event),
0485                                      parentC);
0486     CPPUNIT_ASSERT_THROW(eventSetup.getHandle(consumer.m_token), cms::Exception);
0487     CPPUNIT_ASSERT_THROW(eventSetup.getData(consumer.m_token), cms::Exception);
0488   }
0489 }
0490 
0491 void testEsproducer::labelTest() {
0492   try {
0493     SynchronousEventSetupsController controller;
0494     edm::ParameterSet pset = createDummyPset();
0495     EventSetupProvider& provider = *controller.makeProvider(pset, &activityRegistry);
0496 
0497     std::shared_ptr<ESProductResolverProvider> pResolverProv = std::make_shared<LabelledProducer>();
0498     provider.add(pResolverProv);
0499 
0500     auto pFinder = std::make_shared<DummyFinder>();
0501     provider.add(std::shared_ptr<EventSetupRecordIntervalFinder>(pFinder));
0502 
0503     edm::ESParentContext parentC;
0504     for (int iTime = 1; iTime != 6; ++iTime) {
0505       const edm::Timestamp time(iTime);
0506       pFinder->setInterval(edm::ValidityInterval(edm::IOVSyncValue(time), edm::IOVSyncValue(time)));
0507       controller.eventSetupForInstance(edm::IOVSyncValue(time));
0508       DummyDataConsumer2 consumer(edm::ESInputTag("", "foo"), edm::ESInputTag("", "fi"), edm::ESInputTag("", "fum"));
0509       consumer.updateLookup(provider.recordsToResolverIndices());
0510       consumer.prefetch(provider.eventSetupImpl());
0511       const edm::EventSetup eventSetup(provider.eventSetupImpl(),
0512                                        static_cast<unsigned int>(edm::Transition::Event),
0513                                        consumer.esGetTokenIndices(edm::Transition::Event),
0514                                        parentC);
0515 
0516       edm::ESHandle<DummyData> pDummy = eventSetup.getHandle(consumer.m_token1);
0517       CPPUNIT_ASSERT(0 != pDummy.product());
0518       CPPUNIT_ASSERT(iTime == pDummy->value_);
0519 
0520       pDummy = eventSetup.getHandle(consumer.m_token2);
0521       CPPUNIT_ASSERT(0 != pDummy.product());
0522       CPPUNIT_ASSERT(iTime == pDummy->value_);
0523 
0524       pDummy = eventSetup.getHandle(consumer.m_token3);
0525       CPPUNIT_ASSERT(0 != pDummy.product());
0526       CPPUNIT_ASSERT(iTime == pDummy->value_);
0527     }
0528   } catch (const cms::Exception& iException) {
0529     std::cout << "caught exception " << iException.explainSelf() << std::endl;
0530     throw;
0531   }
0532 }
0533 
0534 struct TestDecorator {
0535   static int s_pre;
0536   static int s_post;
0537 
0538   void pre(const DummyRecord&) { ++s_pre; }
0539 
0540   void post(const DummyRecord&) { ++s_post; }
0541 };
0542 
0543 int TestDecorator::s_pre = 0;
0544 int TestDecorator::s_post = 0;
0545 
0546 class DecoratorProducer : public ESProducer {
0547 public:
0548   DecoratorProducer() { setWhatProduced(this, TestDecorator{}); }
0549   std::shared_ptr<DummyData> produce(const DummyRecord& /*iRecord*/) {
0550     ++ptr_->value_;
0551     return ptr_;
0552   }
0553 
0554 private:
0555   std::shared_ptr<DummyData> ptr_{std::make_shared<DummyData>(0)};
0556 };
0557 
0558 void testEsproducer::decoratorTest() {
0559   SynchronousEventSetupsController controller;
0560   edm::ParameterSet pset = createDummyPset();
0561   EventSetupProvider& provider = *controller.makeProvider(pset, &activityRegistry);
0562 
0563   provider.add(std::make_shared<DecoratorProducer>());
0564 
0565   auto pFinder = std::make_shared<DummyFinder>();
0566   provider.add(std::shared_ptr<EventSetupRecordIntervalFinder>(pFinder));
0567 
0568   edm::ESParentContext parentC;
0569   for (int iTime = 1; iTime != 6; ++iTime) {
0570     const edm::Timestamp time(iTime);
0571     pFinder->setInterval(edm::ValidityInterval(edm::IOVSyncValue(time), edm::IOVSyncValue(time)));
0572     controller.eventSetupForInstance(edm::IOVSyncValue(time));
0573     DummyDataConsumer<DummyRecord> consumer;
0574     consumer.updateLookup(provider.recordsToResolverIndices());
0575 
0576     CPPUNIT_ASSERT(iTime - 1 == TestDecorator::s_pre);
0577     CPPUNIT_ASSERT(iTime - 1 == TestDecorator::s_post);
0578     consumer.prefetch(provider.eventSetupImpl());
0579     const edm::EventSetup eventSetup(provider.eventSetupImpl(),
0580                                      static_cast<unsigned int>(edm::Transition::Event),
0581                                      consumer.esGetTokenIndices(edm::Transition::Event),
0582                                      parentC);
0583     edm::ESHandle<DummyData> pDummy = eventSetup.getHandle(consumer.m_token);
0584     CPPUNIT_ASSERT(0 != pDummy.product());
0585     CPPUNIT_ASSERT(iTime == TestDecorator::s_pre);
0586     CPPUNIT_ASSERT(iTime == TestDecorator::s_post);
0587     CPPUNIT_ASSERT(iTime == pDummy->value_);
0588   }
0589 }
0590 
0591 class DepProducer : public ESProducer {
0592 public:
0593   DepProducer() {
0594     setWhatProduced(this,
0595                     dependsOn(&DepProducer::callWhenDummyChanges,
0596                               &DepProducer::callWhenDummyChanges2,
0597                               &DepProducer::callWhenDummyChanges3));
0598   }
0599   std::shared_ptr<DummyData> produce(const DepRecord& /*iRecord*/) { return ptr_; }
0600   void callWhenDummyChanges(const DummyRecord&) { ++ptr_->value_; }
0601   void callWhenDummyChanges2(const DummyRecord&) { ++ptr_->value_; }
0602   void callWhenDummyChanges3(const DummyRecord&) { ++ptr_->value_; }
0603 
0604 private:
0605   std::shared_ptr<DummyData> ptr_{std::make_shared<DummyData>(0)};
0606 };
0607 
0608 void testEsproducer::dependsOnTest() {
0609   SynchronousEventSetupsController controller;
0610   edm::ParameterSet pset = createDummyPset();
0611   EventSetupProvider& provider = *controller.makeProvider(pset, &activityRegistry);
0612 
0613   provider.add(std::make_shared<DepProducer>());
0614 
0615   auto pFinder = std::make_shared<DummyFinder>();
0616   provider.add(std::shared_ptr<EventSetupRecordIntervalFinder>(pFinder));
0617 
0618   edm::ESParentContext parentC;
0619   for (int iTime = 1; iTime != 6; ++iTime) {
0620     const edm::Timestamp time(iTime);
0621     pFinder->setInterval(edm::ValidityInterval(edm::IOVSyncValue(time), edm::IOVSyncValue(time)));
0622     controller.eventSetupForInstance(edm::IOVSyncValue(time));
0623     DummyDataConsumer<DepRecord> consumer;
0624     consumer.updateLookup(provider.recordsToResolverIndices());
0625     consumer.prefetch(provider.eventSetupImpl());
0626     const edm::EventSetup eventSetup(provider.eventSetupImpl(),
0627                                      static_cast<unsigned int>(edm::Transition::Event),
0628                                      consumer.esGetTokenIndices(edm::Transition::Event),
0629                                      parentC);
0630     edm::ESHandle<DummyData> pDummy = eventSetup.getHandle(consumer.m_token);
0631     CPPUNIT_ASSERT(0 != pDummy.product());
0632     CPPUNIT_ASSERT(3 * iTime == pDummy->value_);
0633   }
0634 }
0635 
0636 void testEsproducer::failMultipleRegistration() { MultiRegisterProducer dummy; }
0637 
0638 void testEsproducer::forceCacheClearTest() {
0639   SynchronousEventSetupsController controller;
0640   edm::ParameterSet pset = createDummyPset();
0641   EventSetupProvider& provider = *controller.makeProvider(pset, &activityRegistry);
0642 
0643   provider.add(std::make_shared<Test1Producer>());
0644 
0645   auto pFinder = std::make_shared<DummyFinder>();
0646   provider.add(std::shared_ptr<EventSetupRecordIntervalFinder>(pFinder));
0647 
0648   const edm::Timestamp time(1);
0649   pFinder->setInterval(edm::ValidityInterval(edm::IOVSyncValue(time), edm::IOVSyncValue(time)));
0650   controller.eventSetupForInstance(edm::IOVSyncValue(time));
0651   {
0652     DummyDataConsumer<DummyRecord> consumer;
0653     consumer.updateLookup(provider.recordsToResolverIndices());
0654     consumer.prefetch(provider.eventSetupImpl());
0655     edm::ESParentContext parentC;
0656     const edm::EventSetup eventSetup(provider.eventSetupImpl(),
0657                                      static_cast<unsigned int>(edm::Transition::Event),
0658                                      consumer.esGetTokenIndices(edm::Transition::Event),
0659                                      parentC);
0660     edm::ESHandle<DummyData> pDummy = eventSetup.getHandle(consumer.m_token);
0661     CPPUNIT_ASSERT(0 != pDummy.product());
0662     CPPUNIT_ASSERT(1 == pDummy->value_);
0663   }
0664   provider.forceCacheClear();
0665   controller.eventSetupForInstance(edm::IOVSyncValue(time));
0666   {
0667     DummyDataConsumer<DummyRecord> consumer;
0668     consumer.updateLookup(provider.recordsToResolverIndices());
0669     consumer.prefetch(provider.eventSetupImpl());
0670     edm::ESParentContext parentC;
0671     const edm::EventSetup eventSetup2(provider.eventSetupImpl(),
0672                                       static_cast<unsigned int>(edm::Transition::Event),
0673                                       consumer.esGetTokenIndices(edm::Transition::Event),
0674                                       parentC);
0675     edm::ESHandle<DummyData> pDummy = eventSetup2.getHandle(consumer.m_token);
0676     CPPUNIT_ASSERT(0 != pDummy.product());
0677     CPPUNIT_ASSERT(2 == pDummy->value_);
0678   }
0679 }
0680 
0681 namespace {
0682   class TestESProductResolverProvider : public ESProductResolverProvider {
0683   public:
0684     TestESProductResolverProvider();
0685 
0686     class TestResolver : public ESProductResolver {
0687     public:
0688       void prefetchAsyncImpl(edm::WaitingTaskHolder,
0689                              EventSetupRecordImpl const&,
0690                              DataKey const&,
0691                              edm::EventSetupImpl const*,
0692                              edm::ServiceToken const&,
0693                              edm::ESParentContext const&) noexcept override {}
0694       void invalidateCache() override {}
0695       void const* getAfterPrefetchImpl() const override { return nullptr; }
0696     };
0697 
0698     DataKey dataKeyDummy_0_;
0699     DataKey dataKeyDummy2_0_;
0700     DataKey dataKeyDummy2_1_;
0701     DataKey dataKeyDummy2_2_;
0702     DataKey dataKeyDep_0_;
0703     DataKey dataKeyDep_1_;
0704     std::shared_ptr<TestResolver> resolverDummy_0_0_;
0705     std::shared_ptr<TestResolver> resolverDummy_0_1_;
0706     std::shared_ptr<TestResolver> resolverDummy_0_2_;
0707     std::shared_ptr<TestResolver> resolverDummy2_0_0_;
0708     std::shared_ptr<TestResolver> resolverDummy2_1_0_;
0709     std::shared_ptr<TestResolver> resolverDummy2_2_0_;
0710     std::shared_ptr<TestResolver> resolverDep_0_0_;
0711     std::shared_ptr<TestResolver> resolverDep_0_1_;
0712     std::shared_ptr<TestResolver> resolverDep_1_0_;
0713     std::shared_ptr<TestResolver> resolverDep_1_1_;
0714 
0715   private:
0716     KeyedResolversVector registerResolvers(const EventSetupRecordKey& recordKey, unsigned int iovIndex) override {
0717       KeyedResolversVector keyedResolversVector;
0718       if (recordKey == EventSetupRecordKey::makeKey<DummyRecord>()) {
0719         if (iovIndex == 0) {
0720           keyedResolversVector.emplace_back(dataKeyDummy_0_, resolverDummy_0_0_);
0721         } else if (iovIndex == 1) {
0722           keyedResolversVector.emplace_back(dataKeyDummy_0_, resolverDummy_0_1_);
0723         } else if (iovIndex == 2) {
0724           keyedResolversVector.emplace_back(dataKeyDummy_0_, resolverDummy_0_2_);
0725         }
0726       } else if (recordKey == EventSetupRecordKey::makeKey<Dummy2Record>()) {
0727         keyedResolversVector.emplace_back(dataKeyDummy2_0_, resolverDummy2_0_0_);
0728         keyedResolversVector.emplace_back(dataKeyDummy2_1_, resolverDummy2_1_0_);
0729         keyedResolversVector.emplace_back(dataKeyDummy2_2_, resolverDummy2_2_0_);
0730       } else if (recordKey == EventSetupRecordKey::makeKey<DepRecord>()) {
0731         if (iovIndex == 0) {
0732           keyedResolversVector.emplace_back(dataKeyDep_0_, resolverDep_0_0_);
0733           keyedResolversVector.emplace_back(dataKeyDep_1_, resolverDep_1_0_);
0734         } else if (iovIndex == 1) {
0735           keyedResolversVector.emplace_back(dataKeyDep_0_, resolverDep_0_1_);
0736           keyedResolversVector.emplace_back(dataKeyDep_1_, resolverDep_1_1_);
0737         }
0738       }
0739       return keyedResolversVector;
0740     }
0741   };
0742 
0743   TestESProductResolverProvider::TestESProductResolverProvider()
0744       : dataKeyDummy_0_(DataKey::makeTypeTag<DummyData>(), "Dummy_0"),
0745         dataKeyDummy2_0_(DataKey::makeTypeTag<DummyData>(), "Dummy2_0"),
0746         dataKeyDummy2_1_(DataKey::makeTypeTag<DummyData>(), "Dummy2_1"),
0747         dataKeyDummy2_2_(DataKey::makeTypeTag<DummyData>(), "Dummy2_2"),
0748         dataKeyDep_0_(DataKey::makeTypeTag<DummyData>(), "Dep_0"),
0749         dataKeyDep_1_(DataKey::makeTypeTag<DummyData>(), "Dep_1"),
0750         resolverDummy_0_0_(std::make_shared<TestResolver>()),
0751         resolverDummy_0_1_(std::make_shared<TestResolver>()),
0752         resolverDummy_0_2_(std::make_shared<TestResolver>()),
0753         resolverDummy2_0_0_(std::make_shared<TestResolver>()),
0754         resolverDummy2_1_0_(std::make_shared<TestResolver>()),
0755         resolverDummy2_2_0_(std::make_shared<TestResolver>()),
0756         resolverDep_0_0_(std::make_shared<TestResolver>()),
0757         resolverDep_0_1_(std::make_shared<TestResolver>()),
0758         resolverDep_1_0_(std::make_shared<TestResolver>()),
0759         resolverDep_1_1_(std::make_shared<TestResolver>()) {
0760     usingRecord<DummyRecord>();
0761     usingRecord<Dummy2Record>();
0762     usingRecord<DepRecord>();
0763     usingRecord<DepOn2Record>();
0764     usingRecord<DummyRecord>();
0765     usingRecord<Dummy2Record>();
0766     usingRecord<DepRecord>();
0767     usingRecord<DepOn2Record>();
0768   }
0769 }  // namespace
0770 
0771 void testEsproducer::productResolverProviderTest() {
0772   TestESProductResolverProvider productResolverProvider;
0773   EventSetupRecordKey dummyRecordKey = EventSetupRecordKey::makeKey<DummyRecord>();
0774   EventSetupRecordKey dummy2RecordKey = EventSetupRecordKey::makeKey<Dummy2Record>();
0775   EventSetupRecordKey depRecordKey = EventSetupRecordKey::makeKey<DepRecord>();
0776   EventSetupRecordKey depOn2RecordKey = EventSetupRecordKey::makeKey<DepOn2Record>();
0777   unsigned int nConcurrentIOVs = 3;
0778   productResolverProvider.createKeyedResolvers(dummyRecordKey, nConcurrentIOVs);
0779   CPPUNIT_ASSERT(productResolverProvider.isUsingRecord(dummyRecordKey));
0780   CPPUNIT_ASSERT(productResolverProvider.isUsingRecord(dummy2RecordKey));
0781   CPPUNIT_ASSERT(productResolverProvider.isUsingRecord(depRecordKey));
0782   CPPUNIT_ASSERT(productResolverProvider.isUsingRecord(depOn2RecordKey));
0783 
0784   std::set<EventSetupRecordKey> expectedKeys;
0785   expectedKeys.insert(dummyRecordKey);
0786   expectedKeys.insert(dummy2RecordKey);
0787   expectedKeys.insert(depRecordKey);
0788   expectedKeys.insert(depOn2RecordKey);
0789 
0790   auto keys = productResolverProvider.usingRecords();
0791   CPPUNIT_ASSERT(keys == expectedKeys);
0792 
0793   keys.clear();
0794   productResolverProvider.fillRecordsNotAllowingConcurrentIOVs(keys);
0795   expectedKeys.clear();
0796   expectedKeys.insert(dummy2RecordKey);
0797   CPPUNIT_ASSERT(keys == expectedKeys);
0798 
0799   nConcurrentIOVs = 1;
0800   productResolverProvider.createKeyedResolvers(dummy2RecordKey, nConcurrentIOVs);
0801   nConcurrentIOVs = 2;
0802   productResolverProvider.createKeyedResolvers(depRecordKey, nConcurrentIOVs);
0803   nConcurrentIOVs = 4;
0804   productResolverProvider.createKeyedResolvers(depOn2RecordKey, nConcurrentIOVs);
0805 
0806   ESProductResolverProvider::KeyedResolvers& keyedResolvers0 =
0807       productResolverProvider.keyedResolvers(dummyRecordKey, 0);
0808   CPPUNIT_ASSERT(keyedResolvers0.recordKey() == dummyRecordKey);
0809   CPPUNIT_ASSERT(keyedResolvers0.size() == 1);
0810   {
0811     auto it = keyedResolvers0.begin();
0812     auto itEnd = keyedResolvers0.end();
0813     CPPUNIT_ASSERT(it.dataKey() == productResolverProvider.dataKeyDummy_0_);
0814     CPPUNIT_ASSERT(it.productResolver() == productResolverProvider.resolverDummy_0_0_.get());
0815     CPPUNIT_ASSERT(it != itEnd);
0816     ++it;
0817     CPPUNIT_ASSERT(!(it != itEnd));
0818   }
0819   ESProductResolverProvider::KeyedResolvers& keyedResolvers1 =
0820       productResolverProvider.keyedResolvers(dummyRecordKey, 1);
0821   CPPUNIT_ASSERT(keyedResolvers1.recordKey() == dummyRecordKey);
0822   CPPUNIT_ASSERT(keyedResolvers1.size() == 1);
0823   {
0824     auto it = keyedResolvers1.begin();
0825     auto itEnd = keyedResolvers1.end();
0826     CPPUNIT_ASSERT(it.dataKey() == productResolverProvider.dataKeyDummy_0_);
0827     CPPUNIT_ASSERT(it.productResolver() == productResolverProvider.resolverDummy_0_1_.get());
0828     CPPUNIT_ASSERT(it != itEnd);
0829     ++it;
0830     CPPUNIT_ASSERT(!(it != itEnd));
0831   }
0832   ESProductResolverProvider::KeyedResolvers& keyedResolvers2 =
0833       productResolverProvider.keyedResolvers(dummyRecordKey, 2);
0834   CPPUNIT_ASSERT(keyedResolvers2.recordKey() == dummyRecordKey);
0835   CPPUNIT_ASSERT(keyedResolvers2.size() == 1);
0836   {
0837     auto it = keyedResolvers2.begin();
0838     auto itEnd = keyedResolvers2.end();
0839     CPPUNIT_ASSERT(it.dataKey() == productResolverProvider.dataKeyDummy_0_);
0840     CPPUNIT_ASSERT(it.productResolver() == productResolverProvider.resolverDummy_0_2_.get());
0841     CPPUNIT_ASSERT(it != itEnd);
0842     ++it;
0843     CPPUNIT_ASSERT(!(it != itEnd));
0844   }
0845   ESProductResolverProvider::KeyedResolvers& keyedResolvers3 =
0846       productResolverProvider.keyedResolvers(dummy2RecordKey, 0);
0847   CPPUNIT_ASSERT(keyedResolvers3.recordKey() == dummy2RecordKey);
0848   CPPUNIT_ASSERT(keyedResolvers3.size() == 3);
0849   {
0850     auto it = keyedResolvers3.begin();
0851     auto itEnd = keyedResolvers3.end();
0852     CPPUNIT_ASSERT(it.dataKey() == productResolverProvider.dataKeyDummy2_0_);
0853     CPPUNIT_ASSERT(it.productResolver() == productResolverProvider.resolverDummy2_0_0_.get());
0854     CPPUNIT_ASSERT(it != itEnd);
0855     ++it;
0856     CPPUNIT_ASSERT(it.dataKey() == productResolverProvider.dataKeyDummy2_1_);
0857     CPPUNIT_ASSERT(it.productResolver() == productResolverProvider.resolverDummy2_1_0_.get());
0858     CPPUNIT_ASSERT(it != itEnd);
0859     ++it;
0860     CPPUNIT_ASSERT(it.dataKey() == productResolverProvider.dataKeyDummy2_2_);
0861     CPPUNIT_ASSERT(it.productResolver() == productResolverProvider.resolverDummy2_2_0_.get());
0862     CPPUNIT_ASSERT(it != itEnd);
0863     ++it;
0864     CPPUNIT_ASSERT(!(it != itEnd));
0865   }
0866   ESProductResolverProvider::KeyedResolvers& keyedResolvers4 = productResolverProvider.keyedResolvers(depRecordKey, 0);
0867   CPPUNIT_ASSERT(keyedResolvers4.recordKey() == depRecordKey);
0868   CPPUNIT_ASSERT(keyedResolvers4.size() == 2);
0869   {
0870     auto it = keyedResolvers4.begin();
0871     auto itEnd = keyedResolvers4.end();
0872     CPPUNIT_ASSERT(it.dataKey() == productResolverProvider.dataKeyDep_0_);
0873     CPPUNIT_ASSERT(it.productResolver() == productResolverProvider.resolverDep_0_0_.get());
0874     CPPUNIT_ASSERT(it != itEnd);
0875     ++it;
0876     CPPUNIT_ASSERT(it.dataKey() == productResolverProvider.dataKeyDep_1_);
0877     CPPUNIT_ASSERT(it.productResolver() == productResolverProvider.resolverDep_1_0_.get());
0878     CPPUNIT_ASSERT(it != itEnd);
0879     ++it;
0880     CPPUNIT_ASSERT(!(it != itEnd));
0881   }
0882   ESProductResolverProvider::KeyedResolvers& keyedResolvers5 = productResolverProvider.keyedResolvers(depRecordKey, 1);
0883   CPPUNIT_ASSERT(keyedResolvers5.recordKey() == depRecordKey);
0884   CPPUNIT_ASSERT(keyedResolvers5.size() == 2);
0885   {
0886     auto it = keyedResolvers5.begin();
0887     auto itEnd = keyedResolvers5.end();
0888     CPPUNIT_ASSERT(it.dataKey() == productResolverProvider.dataKeyDep_0_);
0889     CPPUNIT_ASSERT(it.productResolver() == productResolverProvider.resolverDep_0_1_.get());
0890     CPPUNIT_ASSERT(it != itEnd);
0891     ++it;
0892     CPPUNIT_ASSERT(it.dataKey() == productResolverProvider.dataKeyDep_1_);
0893     CPPUNIT_ASSERT(it.productResolver() == productResolverProvider.resolverDep_1_1_.get());
0894     CPPUNIT_ASSERT(it != itEnd);
0895     ++it;
0896     CPPUNIT_ASSERT(!(it != itEnd));
0897   }
0898   ESProductResolverProvider::KeyedResolvers& keyedResolvers6 =
0899       productResolverProvider.keyedResolvers(depOn2RecordKey, 0);
0900   CPPUNIT_ASSERT(keyedResolvers6.recordKey() == depOn2RecordKey);
0901   CPPUNIT_ASSERT(keyedResolvers6.size() == 0);
0902   {
0903     auto it = keyedResolvers6.begin();
0904     auto itEnd = keyedResolvers6.end();
0905     CPPUNIT_ASSERT(!(it != itEnd));
0906   }
0907   ESProductResolverProvider::KeyedResolvers& keyedResolvers7 =
0908       productResolverProvider.keyedResolvers(depOn2RecordKey, 1);
0909   CPPUNIT_ASSERT(keyedResolvers7.recordKey() == depOn2RecordKey);
0910   CPPUNIT_ASSERT(keyedResolvers7.size() == 0);
0911   {
0912     auto it = keyedResolvers7.begin();
0913     auto itEnd = keyedResolvers7.end();
0914     CPPUNIT_ASSERT(!(it != itEnd));
0915   }
0916   ESProductResolverProvider::KeyedResolvers& keyedResolvers8 =
0917       productResolverProvider.keyedResolvers(depOn2RecordKey, 2);
0918   CPPUNIT_ASSERT(keyedResolvers8.recordKey() == depOn2RecordKey);
0919   CPPUNIT_ASSERT(keyedResolvers8.size() == 0);
0920   {
0921     auto it = keyedResolvers8.begin();
0922     auto itEnd = keyedResolvers8.end();
0923     CPPUNIT_ASSERT(!(it != itEnd));
0924   }
0925   ESProductResolverProvider::KeyedResolvers& keyedResolvers9 =
0926       productResolverProvider.keyedResolvers(depOn2RecordKey, 3);
0927   CPPUNIT_ASSERT(keyedResolvers9.recordKey() == depOn2RecordKey);
0928   CPPUNIT_ASSERT(keyedResolvers9.size() == 0);
0929   {
0930     auto it = keyedResolvers9.begin();
0931     auto itEnd = keyedResolvers9.end();
0932     CPPUNIT_ASSERT(!(it != itEnd));
0933   }
0934 
0935   CPPUNIT_ASSERT(keyedResolvers4.contains(productResolverProvider.dataKeyDep_0_));
0936   CPPUNIT_ASSERT(keyedResolvers4.contains(productResolverProvider.dataKeyDep_1_));
0937   CPPUNIT_ASSERT(!keyedResolvers4.contains(productResolverProvider.dataKeyDummy_0_));
0938 
0939   ESProductResolverProvider::KeyedResolvers keyedResolvers10(nullptr, 0);
0940   CPPUNIT_ASSERT(keyedResolvers10.unInitialized());
0941   CPPUNIT_ASSERT(!keyedResolvers0.unInitialized());
0942 }