Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-04-30 22:24:11

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