Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:13:10

0001 #ifndef FWCore_TestProcessor_TestProcessor_h
0002 #define FWCore_TestProcessor_TestProcessor_h
0003 // -*- C++ -*-
0004 //
0005 // Package:     FWCore/TestProcessor
0006 // Class  :     TestProcessor
0007 //
0008 /**\class TestProcessor TestProcessor.h "TestProcessor.h"
0009 
0010  Description: [one line class summary]
0011 
0012  Usage:
0013     <usage>
0014 
0015 */
0016 //
0017 // Original Author:  Chris Jones
0018 //         Created:  Mon, 30 Apr 2018 18:51:00 GMT
0019 //
0020 
0021 // system include files
0022 #include <string>
0023 #include <utility>
0024 #include <memory>
0025 #include "oneapi/tbb/global_control.h"
0026 #include "oneapi/tbb/task_arena.h"
0027 #include "oneapi/tbb/task_group.h"
0028 
0029 // user include files
0030 #include "FWCore/Common/interface/FWCoreCommonFwd.h"
0031 #include "FWCore/Framework/interface/SharedResourcesAcquirer.h"
0032 #include "FWCore/Framework/interface/PrincipalCache.h"
0033 #include "FWCore/Framework/interface/SignallingProductRegistry.h"
0034 #include "FWCore/Framework/interface/PreallocationConfiguration.h"
0035 #include "FWCore/Framework/interface/ModuleRegistry.h"
0036 #include "FWCore/Framework/interface/Schedule.h"
0037 #include "FWCore/Framework/interface/EventSetupRecordKey.h"
0038 #include "FWCore/Framework/interface/DataKey.h"
0039 #include "FWCore/ServiceRegistry/interface/ActivityRegistry.h"
0040 #include "FWCore/ServiceRegistry/interface/ProcessContext.h"
0041 #include "FWCore/ServiceRegistry/interface/ServiceLegacy.h"
0042 #include "FWCore/ServiceRegistry/interface/ServiceToken.h"
0043 
0044 #include "DataFormats/Provenance/interface/RunLumiEventNumber.h"
0045 #include "DataFormats/Provenance/interface/ProcessHistoryRegistry.h"
0046 #include "DataFormats/Common/interface/Wrapper.h"
0047 
0048 #include "FWCore/TestProcessor/interface/Event.h"
0049 #include "FWCore/TestProcessor/interface/LuminosityBlock.h"
0050 #include "FWCore/TestProcessor/interface/ProcessBlock.h"
0051 #include "FWCore/TestProcessor/interface/Run.h"
0052 #include "FWCore/TestProcessor/interface/TestESProductResolver.h"
0053 #include "FWCore/TestProcessor/interface/ESPutTokenT.h"
0054 #include "FWCore/TestProcessor/interface/ESProduceEntry.h"
0055 #include "FWCore/TestProcessor/interface/EventSetupTestHelper.h"
0056 
0057 #include "FWCore/Utilities/interface/EDPutToken.h"
0058 
0059 // forward declarations
0060 
0061 namespace edm {
0062   class ThinnedAssociationsHelper;
0063   class ExceptionToActionTable;
0064   class HistoryAppender;
0065   class ModuleTypeResolverMaker;
0066 
0067   namespace eventsetup {
0068     class EventSetupProvider;
0069     class EventSetupsController;
0070   }  // namespace eventsetup
0071 
0072   namespace test {
0073     class TestProcessorConfig;
0074     class EventSetupTestHelper;
0075 
0076     class ProcessToken {
0077       friend TestProcessorConfig;
0078 
0079     public:
0080       ProcessToken() : index_{undefinedIndex()} {}
0081 
0082       int index() const { return index_; }
0083 
0084       static int undefinedIndex() { return -1; }
0085 
0086     private:
0087       explicit ProcessToken(int index) : index_{index} {}
0088 
0089       int index_;
0090     };
0091 
0092     class TestProcessorConfig {
0093     public:
0094       TestProcessorConfig(std::string const& iPythonConfiguration) : config_(iPythonConfiguration) {}
0095       std::string const& pythonConfiguration() const { return config_; }
0096       void setPythonConfiguration(std::string iConfig) { config_ = std::move(iConfig); }
0097 
0098       /** add a Process name to the Process history. If multiple calls are made to addProcess,
0099      then the call order will be the order of the Processes in the history.*/
0100       ProcessToken addExtraProcess(std::string const& iProcessName) {
0101         extraProcesses_.emplace_back(iProcessName);
0102         return ProcessToken(extraProcesses_.size() - 1);
0103       }
0104 
0105       std::vector<std::string> const& extraProcesses() const { return extraProcesses_; }
0106 
0107       /** A blank iProcessName means it produces in the primary process.
0108      The use of any other name requires that it is first added via `addExtraProcess`.
0109      */
0110       template <typename T>
0111       edm::EDPutTokenT<T> produces(std::string iModuleLabel,
0112                                    std::string iProductInstanceLabel = std::string(),
0113                                    ProcessToken iToken = ProcessToken()) {
0114         produceEntries_.emplace_back(
0115             edm::TypeID(typeid(T)), std::move(iModuleLabel), std::move(iProductInstanceLabel), processName(iToken));
0116         return edm::EDPutTokenT<T>(produceEntries_.size() - 1);
0117       }
0118 
0119       template <typename REC, typename T>
0120       edm::test::ESPutTokenT<T> esProduces(std::string iLabel = std::string()) {
0121         auto rk = eventsetup::EventSetupRecordKey::makeKey<REC>();
0122         eventsetup::DataKey dk(eventsetup::DataKey::makeTypeTag<T>(), iLabel.c_str());
0123         esProduceEntries_.emplace_back(rk, dk, std::make_shared<TestESProductResolver<T>>());
0124         return edm::test::ESPutTokenT<T>(esProduceEntries_.size() - 1);
0125       }
0126 
0127       struct ProduceEntry {
0128         ProduceEntry(edm::TypeID const& iType,
0129                      std::string moduleLabel,
0130                      std::string instanceLabel,
0131                      std::string processName)
0132             : type_{iType},
0133               moduleLabel_{std::move(moduleLabel)},
0134               instanceLabel_{std::move(instanceLabel)},
0135               processName_{std::move(processName)} {}
0136         edm::TypeID type_;
0137         std::string moduleLabel_;
0138         std::string instanceLabel_;
0139         std::string processName_;
0140       };
0141 
0142       std::vector<ProduceEntry> const& produceEntries() const { return produceEntries_; }
0143 
0144       std::vector<ESProduceEntry> const& esProduceEntries() const { return esProduceEntries_; }
0145 
0146     private:
0147       std::string config_;
0148       std::vector<std::string> extraProcesses_;
0149       std::vector<ProduceEntry> produceEntries_;
0150       std::vector<ESProduceEntry> esProduceEntries_;
0151 
0152       std::string processName(ProcessToken iToken) {
0153         if (iToken.index() == ProcessToken::undefinedIndex()) {
0154           return std::string();
0155         }
0156         return extraProcesses_[iToken.index()];
0157       }
0158     };
0159 
0160     class TestProcessor {
0161     public:
0162       using Config = TestProcessorConfig;
0163 
0164       TestProcessor(Config const& iConfig, ServiceToken iToken = ServiceToken());
0165       TestProcessor(const TestProcessor&) = delete;
0166       const TestProcessor& operator=(const TestProcessor&) = delete;
0167       ~TestProcessor() noexcept(false);
0168 
0169       /** Run the test. The function arguments are the data products to be added to the
0170      Event for this particular test.
0171      */
0172       template <typename... T>
0173       edm::test::Event test(T&&... iArgs) {
0174         return testImpl(std::forward<T>(iArgs)...);
0175       }
0176 
0177       template <typename... T>
0178       edm::test::LuminosityBlock testBeginLuminosityBlock(edm::LuminosityBlockNumber_t iNum, T&&... iArgs) {
0179         return testBeginLuminosityBlockImpl(iNum, std::forward<T>(iArgs)...);
0180       }
0181       template <typename... T>
0182       edm::test::LuminosityBlock testEndLuminosityBlock(T&&... iArgs) {
0183         return testEndLuminosityBlockImpl(std::forward<T>(iArgs)...);
0184       }
0185 
0186       template <typename... T>
0187       edm::test::Run testBeginRun(edm::RunNumber_t iNum, T&&... iArgs) {
0188         return testBeginRunImpl(iNum, std::forward<T>(iArgs)...);
0189       }
0190       template <typename... T>
0191       edm::test::Run testEndRun(T&&... iArgs) {
0192         return testEndRunImpl(std::forward<T>(iArgs)...);
0193       }
0194 
0195       // It makes no sense to pass EventSetup products and at least
0196       // for now Runs, Lumis, and ProcessBlocks don't allow passing
0197       // in other products. So for now these don't need to be templates
0198       // for ProcessBlock.
0199       edm::test::ProcessBlock testBeginProcessBlock() { return testBeginProcessBlockImpl(); }
0200 
0201       edm::test::ProcessBlock testEndProcessBlock() { return testEndProcessBlockImpl(); }
0202 
0203       /** Run only beginJob and endJob. Once this is used, you should not attempt to run any further tests.
0204 This simulates a problem happening early in the job which causes processing not to proceed.
0205    */
0206       void testBeginAndEndJobOnly() {
0207         arena_.execute([this]() {
0208           beginJob();
0209           endJob();
0210         });
0211       }
0212 
0213       void testWithNoRuns() {
0214         arena_.execute([this]() {
0215           beginJob();
0216           beginProcessBlock();
0217           endProcessBlock();
0218           endJob();
0219         });
0220       }
0221 
0222       void testRunWithNoLuminosityBlocks() {
0223         arena_.execute([this]() {
0224           beginJob();
0225           beginProcessBlock();
0226           beginRun();
0227           endRun();
0228           endProcessBlock();
0229           endJob();
0230         });
0231       }
0232 
0233       void testLuminosityBlockWithNoEvents() {
0234         arena_.execute([this]() {
0235           beginJob();
0236           beginProcessBlock();
0237           beginRun();
0238           beginLuminosityBlock();
0239           endLuminosityBlock();
0240           endRun();
0241           endProcessBlock();
0242           endJob();
0243         });
0244       }
0245       void setRunNumber(edm::RunNumber_t);
0246       void setLuminosityBlockNumber(edm::LuminosityBlockNumber_t);
0247       void setEventNumber(edm::EventNumber_t);
0248 
0249       std::string const& labelOfTestModule() const { return labelOfTestModule_; }
0250 
0251     private:
0252       template <typename T, typename... U>
0253       edm::test::Event testImpl(std::pair<edm::EDPutTokenT<T>, std::unique_ptr<T>>&& iPut, U&&... iArgs) {
0254         put(std::move(iPut));
0255         return testImpl(std::forward<U>(iArgs)...);
0256       }
0257 
0258       template <typename T, typename... U>
0259       edm::test::Event testImpl(std::pair<edm::test::ESPutTokenT<T>, std::unique_ptr<T>>&& iPut, U&&... iArgs) {
0260         put(std::move(iPut));
0261         return testImpl(std::forward<U>(iArgs)...);
0262       }
0263 
0264       template <typename T>
0265       void put(std::pair<edm::EDPutTokenT<T>, std::unique_ptr<T>>&& iPut) {
0266         put(iPut.first.index(), std::make_unique<edm::Wrapper<T>>(std::move(iPut.second)));
0267       }
0268 
0269       template <typename T>
0270       void put(std::pair<edm::test::ESPutTokenT<T>, std::unique_ptr<T>>&& iPut) {
0271         dynamic_cast<TestESProductResolver<T>*>(esHelper_->getResolver(iPut.first.index()).get())
0272             ->setData(std::move(iPut.second));
0273       }
0274 
0275       void put(unsigned int, std::unique_ptr<WrapperBase>);
0276 
0277       edm::test::Event testImpl();
0278 
0279       template <typename T, typename... U>
0280       edm::test::LuminosityBlock testBeginLuminosityBlockImpl(
0281           edm::LuminosityBlockNumber_t iNum,
0282           std::pair<edm::test::ESPutTokenT<T>, std::unique_ptr<T>>&& iPut,
0283           U&&... iArgs) {
0284         put(std::move(iPut));
0285         return testBeginLuminosityBlockImpl(iNum, std::forward<U>(iArgs)...);
0286       }
0287       edm::test::LuminosityBlock testBeginLuminosityBlockImpl(edm::LuminosityBlockNumber_t);
0288 
0289       template <typename T, typename... U>
0290       edm::test::LuminosityBlock testEndLuminosityBlockImpl(
0291           std::pair<edm::test::ESPutTokenT<T>, std::unique_ptr<T>>&& iPut, U&&... iArgs) {
0292         put(std::move(iPut));
0293         return testEndLuminosityBlockImpl(std::forward<U>(iArgs)...);
0294       }
0295       edm::test::LuminosityBlock testEndLuminosityBlockImpl();
0296 
0297       template <typename T, typename... U>
0298       edm::test::Run testBeginRunImpl(edm::RunNumber_t iNum,
0299                                       std::pair<edm::test::ESPutTokenT<T>, std::unique_ptr<T>>&& iPut,
0300                                       U&&... iArgs) {
0301         put(std::move(iPut));
0302         return testBeginRunImpl(iNum, std::forward<U>(iArgs)...);
0303       }
0304       edm::test::Run testBeginRunImpl(edm::RunNumber_t);
0305       template <typename T, typename... U>
0306       edm::test::LuminosityBlock testEndRunImpl(std::pair<edm::test::ESPutTokenT<T>, std::unique_ptr<T>>&& iPut,
0307                                                 U&&... iArgs) {
0308         put(std::move(iPut));
0309         return testEndRunImpl(std::forward<U>(iArgs)...);
0310       }
0311       edm::test::Run testEndRunImpl();
0312 
0313       edm::test::ProcessBlock testBeginProcessBlockImpl();
0314       edm::test::ProcessBlock testEndProcessBlockImpl();
0315 
0316       void setupProcessing();
0317       void teardownProcessing();
0318 
0319       void beginJob();
0320       void beginProcessBlock();
0321       void beginRun();
0322       void beginLuminosityBlock();
0323       void event();
0324       std::shared_ptr<LuminosityBlockPrincipal> endLuminosityBlock();
0325       std::shared_ptr<RunPrincipal> endRun();
0326       ProcessBlockPrincipal const* endProcessBlock();
0327       void endJob();
0328 
0329       // ---------- member data --------------------------------
0330       oneapi::tbb::global_control globalControl_;
0331       oneapi::tbb::task_group taskGroup_;
0332       oneapi::tbb::task_arena arena_;
0333       std::string labelOfTestModule_;
0334       std::shared_ptr<ActivityRegistry> actReg_;  // We do not use propagate_const because the registry itself is mutable.
0335       std::shared_ptr<ProductRegistry> preg_;
0336       std::shared_ptr<BranchIDListHelper> branchIDListHelper_;
0337       std::shared_ptr<ProcessBlockHelper> processBlockHelper_;
0338       std::shared_ptr<ThinnedAssociationsHelper> thinnedAssociationsHelper_;
0339       ServiceToken serviceToken_;
0340       std::unique_ptr<ModuleTypeResolverMaker const> moduleTypeResolverMaker_;
0341       std::unique_ptr<eventsetup::EventSetupsController> espController_;
0342       std::shared_ptr<eventsetup::EventSetupProvider> esp_;
0343       std::shared_ptr<EventSetupTestHelper> esHelper_;
0344 
0345       std::unique_ptr<ExceptionToActionTable const> act_table_;
0346       std::shared_ptr<ProcessConfiguration const> processConfiguration_;
0347       ProcessContext processContext_;
0348 
0349       ProcessHistoryRegistry processHistoryRegistry_;
0350       std::unique_ptr<HistoryAppender> historyAppender_;
0351 
0352       PrincipalCache principalCache_;
0353       PreallocationConfiguration preallocations_;
0354 
0355       std::shared_ptr<ModuleRegistry> moduleRegistry_;
0356       std::unique_ptr<Schedule> schedule_;
0357       std::shared_ptr<RunPrincipal> runPrincipal_;
0358       std::shared_ptr<LuminosityBlockPrincipal> lumiPrincipal_;
0359 
0360       std::vector<std::pair<edm::BranchDescription, std::unique_ptr<WrapperBase>>> dataProducts_;
0361 
0362       RunNumber_t runNumber_ = 1;
0363       LuminosityBlockNumber_t lumiNumber_ = 1;
0364       EventNumber_t eventNumber_ = 1;
0365       bool beginJobCalled_ = false;
0366       bool beginProcessBlockCalled_ = false;
0367       bool beginRunCalled_ = false;
0368       bool beginLumiCalled_ = false;
0369     };
0370   }  // namespace test
0371 }  // namespace edm
0372 
0373 #endif