Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-12-24 02:18:57

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