Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-01-11 16:27:25

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/TestDataProxy.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<TestDataProxy<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<TestDataProxy<T>*>(esHelper_->getProxy(iPut.first.index()).get())->setData(std::move(iPut.second));
0272       }
0273 
0274       void put(unsigned int, std::unique_ptr<WrapperBase>);
0275 
0276       edm::test::Event testImpl();
0277 
0278       template <typename T, typename... U>
0279       edm::test::LuminosityBlock testBeginLuminosityBlockImpl(
0280           edm::LuminosityBlockNumber_t iNum,
0281           std::pair<edm::test::ESPutTokenT<T>, std::unique_ptr<T>>&& iPut,
0282           U&&... iArgs) {
0283         put(std::move(iPut));
0284         return testBeginLuminosityBlockImpl(iNum, std::forward<U>(iArgs)...);
0285       }
0286       edm::test::LuminosityBlock testBeginLuminosityBlockImpl(edm::LuminosityBlockNumber_t);
0287 
0288       template <typename T, typename... U>
0289       edm::test::LuminosityBlock testEndLuminosityBlockImpl(
0290           std::pair<edm::test::ESPutTokenT<T>, std::unique_ptr<T>>&& iPut, U&&... iArgs) {
0291         put(std::move(iPut));
0292         return testEndLuminosityBlockImpl(std::forward<U>(iArgs)...);
0293       }
0294       edm::test::LuminosityBlock testEndLuminosityBlockImpl();
0295 
0296       template <typename T, typename... U>
0297       edm::test::Run testBeginRunImpl(edm::RunNumber_t iNum,
0298                                       std::pair<edm::test::ESPutTokenT<T>, std::unique_ptr<T>>&& iPut,
0299                                       U&&... iArgs) {
0300         put(std::move(iPut));
0301         return testBeginRunImpl(iNum, std::forward<U>(iArgs)...);
0302       }
0303       edm::test::Run testBeginRunImpl(edm::RunNumber_t);
0304       template <typename T, typename... U>
0305       edm::test::LuminosityBlock testEndRunImpl(std::pair<edm::test::ESPutTokenT<T>, std::unique_ptr<T>>&& iPut,
0306                                                 U&&... iArgs) {
0307         put(std::move(iPut));
0308         return testEndRunImpl(std::forward<U>(iArgs)...);
0309       }
0310       edm::test::Run testEndRunImpl();
0311 
0312       edm::test::ProcessBlock testBeginProcessBlockImpl();
0313       edm::test::ProcessBlock testEndProcessBlockImpl();
0314 
0315       void setupProcessing();
0316       void teardownProcessing();
0317 
0318       void beginJob();
0319       void beginProcessBlock();
0320       void beginRun();
0321       void beginLuminosityBlock();
0322       void event();
0323       std::shared_ptr<LuminosityBlockPrincipal> endLuminosityBlock();
0324       std::shared_ptr<RunPrincipal> endRun();
0325       ProcessBlockPrincipal const* endProcessBlock();
0326       void endJob();
0327 
0328       // ---------- member data --------------------------------
0329       oneapi::tbb::global_control globalControl_;
0330       oneapi::tbb::task_group taskGroup_;
0331       oneapi::tbb::task_arena arena_;
0332       std::string labelOfTestModule_;
0333       std::shared_ptr<ActivityRegistry> actReg_;  // We do not use propagate_const because the registry itself is mutable.
0334       std::shared_ptr<ProductRegistry> preg_;
0335       std::shared_ptr<BranchIDListHelper> branchIDListHelper_;
0336       std::shared_ptr<ProcessBlockHelper> processBlockHelper_;
0337       std::shared_ptr<ThinnedAssociationsHelper> thinnedAssociationsHelper_;
0338       ServiceToken serviceToken_;
0339       std::unique_ptr<ModuleTypeResolverMaker const> moduleTypeResolverMaker_;
0340       std::unique_ptr<eventsetup::EventSetupsController> espController_;
0341       std::shared_ptr<eventsetup::EventSetupProvider> esp_;
0342       std::shared_ptr<EventSetupTestHelper> esHelper_;
0343 
0344       std::unique_ptr<ExceptionToActionTable const> act_table_;
0345       std::shared_ptr<ProcessConfiguration const> processConfiguration_;
0346       ProcessContext processContext_;
0347 
0348       ProcessHistoryRegistry processHistoryRegistry_;
0349       std::unique_ptr<HistoryAppender> historyAppender_;
0350 
0351       PrincipalCache principalCache_;
0352       PreallocationConfiguration preallocations_;
0353 
0354       std::shared_ptr<ModuleRegistry> moduleRegistry_;
0355       std::unique_ptr<Schedule> schedule_;
0356       std::shared_ptr<RunPrincipal> runPrincipal_;
0357       std::shared_ptr<LuminosityBlockPrincipal> lumiPrincipal_;
0358 
0359       std::vector<std::pair<edm::BranchDescription, std::unique_ptr<WrapperBase>>> dataProducts_;
0360 
0361       RunNumber_t runNumber_ = 1;
0362       LuminosityBlockNumber_t lumiNumber_ = 1;
0363       EventNumber_t eventNumber_ = 1;
0364       bool beginJobCalled_ = false;
0365       bool beginProcessBlockCalled_ = false;
0366       bool beginRunCalled_ = false;
0367       bool beginLumiCalled_ = false;
0368     };
0369   }  // namespace test
0370 }  // namespace edm
0371 
0372 #endif