File indexing completed on 2025-07-24 02:01:38
0001 #include "catch.hpp"
0002
0003 #include "FWCore/Framework/src/ScheduleBuilder.h"
0004 #include "FWCore/Framework/interface/global/EDProducer.h"
0005 #include "FWCore/Framework/interface/ModuleRegistry.h"
0006 #include "FWCore/Framework/interface/PreallocationConfiguration.h"
0007 #include "FWCore/Framework/interface/SignallingProductRegistryFiller.h"
0008 #include "FWCore/ServiceRegistry/interface/ActivityRegistry.h"
0009 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0010 #include "DataFormats/Provenance/interface/ProcessConfiguration.h"
0011
0012 #include <vector>
0013 #include <string_view>
0014 namespace edm::test::sb {
0015 class SBIntProducer : public edm::global::EDProducer<> {
0016 public:
0017 explicit SBIntProducer(std::vector<edm::InputTag> const& iConsumes) {
0018 for (auto const& tag : iConsumes) {
0019 consumes<int>(tag);
0020 }
0021 produces<int>();
0022 }
0023 void produce(StreamID, edm::Event&, edm::EventSetup const&) const final {}
0024 };
0025 }
0026
0027 namespace {
0028 struct ModuleInfo {
0029 std::string label_;
0030 std::string type_;
0031 std::string edmType_;
0032 };
0033 enum class EdmType { kProducer, kFilter, kAnalyzer, kSwitchProducer, kOutputModule };
0034
0035 struct ConfigBuilder {
0036 void addModule(std::string const& iLabel, std::string const& iType, EdmType iEdmType) {
0037 ModuleInfo info = {.label_ = iLabel, .type_ = iType, .edmType_ = enumToName(iEdmType)};
0038 modules_.emplace_back(std::move(info));
0039 }
0040 std::string enumToName(EdmType iType) {
0041 switch (iType) {
0042 case EdmType::kProducer:
0043 return "EDProducer";
0044 case EdmType::kFilter:
0045 return "EDFilter";
0046 case EdmType::kAnalyzer:
0047 return "EDAnalyzer";
0048 case EdmType::kOutputModule:
0049 return "OutputModule";
0050 case EdmType::kSwitchProducer:
0051 return "SwitchProducer";
0052 }
0053 return "";
0054 }
0055 void addPath(std::string iName, std::vector<std::string> iModuleLabels) {
0056 paths_.emplace_back(std::move(iName), std::move(iModuleLabels));
0057 }
0058 void addEndPath(std::string iName, std::vector<std::string> iModuleLabels) {
0059 endpaths_.emplace_back(std::move(iName), std::move(iModuleLabels));
0060 }
0061 void addAllowedFilterOnEndPath(std::string iLabel) { allowedFiltersOnEndPaths_.emplace_back(std::move(iLabel)); }
0062
0063 edm::ParameterSet buildConfig() {
0064 edm::ParameterSet config;
0065 config.addParameter<std::vector<std::string>>("@all_aliases", std::vector<std::string>());
0066 std::vector<std::string> pathNames;
0067 for (auto const& pathInfo : paths_) {
0068 pathNames.emplace_back(pathInfo.first);
0069 config.addParameter<std::vector<std::string>>(pathInfo.first, pathInfo.second);
0070 }
0071 for (auto const& pathInfo : endpaths_) {
0072 config.addParameter<std::vector<std::string>>(pathInfo.first, pathInfo.second);
0073 }
0074 edm::ParameterSet trigPaths;
0075 trigPaths.addParameter<std::vector<std::string>>("@trigger_paths", pathNames);
0076 config.addParameter<edm::ParameterSet>("@trigger_paths", trigPaths);
0077 std::vector<std::string> moduleLabels;
0078 moduleLabels.reserve(modules_.size());
0079 for (auto const& moduleInfo : modules_) {
0080 moduleLabels.emplace_back(moduleInfo.label_);
0081 edm::ParameterSet moduleConfig;
0082 moduleConfig.addParameter<std::string>("@module_type", moduleInfo.type_);
0083 moduleConfig.addParameter<std::string>("@module_edm_type", moduleInfo.edmType_);
0084 config.addParameter<edm::ParameterSet>(moduleInfo.label_, moduleConfig);
0085 }
0086 config.addParameter<std::vector<std::string>>("@all_modules", moduleLabels);
0087 config.addUntrackedParameter<std::vector<std::string>>("@filters_on_endpaths", allowedFiltersOnEndPaths_);
0088
0089 return config;
0090 }
0091
0092 std::vector<std::string> paths() {
0093 std::vector<std::string> ret;
0094 for (auto const& p : paths_) {
0095 ret.push_back(p.first);
0096 }
0097 return ret;
0098 }
0099
0100 std::vector<std::string> endpaths() {
0101 std::vector<std::string> ret;
0102 for (auto const& p : endpaths_) {
0103 ret.push_back(p.first);
0104 }
0105 return ret;
0106 }
0107
0108 private:
0109 std::vector<ModuleInfo> modules_;
0110 std::vector<std::pair<std::string, std::vector<std::string>>> paths_;
0111 std::vector<std::pair<std::string, std::vector<std::string>>> endpaths_;
0112 std::vector<std::string> allowedFiltersOnEndPaths_;
0113 };
0114 }
0115
0116 TEST_CASE("test edm::ScheduleBuilder", "[ScheduleBuilder]") {
0117 edm::HardwareResourcesDescription hardware;
0118 auto const processConfig = std::make_shared<edm::ProcessConfiguration const>("TEST", "CMSSW_X_Y_Z", hardware);
0119 edm::PreallocationConfiguration prealloc;
0120 SECTION("empty schedule") {
0121 edm::ModuleRegistry moduleRegistry;
0122 edm::SignallingProductRegistryFiller productRegistry;
0123 edm::ActivityRegistry activityRegistry;
0124
0125 ConfigBuilder confBuilder;
0126 auto config = confBuilder.buildConfig();
0127 edm::ScheduleBuilder builder(moduleRegistry,
0128 config,
0129 confBuilder.paths(),
0130 confBuilder.endpaths(),
0131 prealloc,
0132 productRegistry,
0133 activityRegistry,
0134 processConfig);
0135
0136 REQUIRE(builder.endpathNameAndModules_.empty());
0137 REQUIRE(builder.pathNameAndModules_.empty());
0138 REQUIRE(builder.allNeededModules_.empty());
0139 REQUIRE(builder.unscheduledModules_.empty());
0140 REQUIRE(builder.pathStatusInserters_.empty());
0141 REQUIRE(not builder.resultsInserter_);
0142 }
0143 SECTION("one module on path") {
0144 edm::SignallingProductRegistryFiller productRegistry;
0145 edm::ActivityRegistry activityRegistry;
0146
0147 edm::ModuleRegistry moduleRegistry;
0148 edm::ParameterSet pset;
0149 pset.addParameter<std::string>("@module_type", "edm::test::sb::SBIntProducer");
0150 pset.addParameter<std::string>("@module_edm_type", "EDProducer");
0151 pset.registerIt();
0152
0153 edm::ModuleDescription desc(
0154 pset.id(), "edm::test::sb::SBIntProducer", "prod1", processConfig.get(), edm::ModuleDescription::getUniqueID());
0155 moduleRegistry.makeExplicitModule<edm::test::sb::SBIntProducer>(desc,
0156 prealloc,
0157 &productRegistry,
0158 activityRegistry.preModuleConstructionSignal_,
0159 activityRegistry.postModuleConstructionSignal_,
0160 std::vector<edm::InputTag>());
0161
0162 ConfigBuilder confBuilder;
0163 confBuilder.addModule("prod1", "edm::test::sb::SBIntProducer", EdmType::kProducer);
0164 confBuilder.addPath("p1", {{"prod1"}});
0165 auto config = confBuilder.buildConfig();
0166 edm::ScheduleBuilder builder(moduleRegistry,
0167 config,
0168 confBuilder.paths(),
0169 confBuilder.endpaths(),
0170 prealloc,
0171 productRegistry,
0172 activityRegistry,
0173 processConfig);
0174
0175 REQUIRE(builder.endpathNameAndModules_.empty());
0176 REQUIRE(builder.pathNameAndModules_.size() == 1);
0177 REQUIRE(builder.pathNameAndModules_.front().first == "p1");
0178 REQUIRE(builder.pathNameAndModules_.front().second.size() == 1);
0179 auto moduleInfo = builder.pathNameAndModules_.front().second.front();
0180 REQUIRE(moduleInfo.description_->moduleLabel() == "prod1");
0181 REQUIRE(moduleInfo.description_->moduleName() == "edm::test::sb::SBIntProducer");
0182 REQUIRE(moduleInfo.action_ == edm::WorkerInPath::Normal);
0183 REQUIRE(moduleInfo.placeInPath_ == 0);
0184 REQUIRE(moduleInfo.runConcurrently_ == true);
0185 REQUIRE(builder.allNeededModules_.size() == 3);
0186 REQUIRE(std::find_if(builder.allNeededModules_.begin(), builder.allNeededModules_.end(), [&desc](auto const* el) {
0187 return *el == desc;
0188 }) != builder.allNeededModules_.end());
0189 REQUIRE(builder.unscheduledModules_.empty());
0190 REQUIRE(builder.pathStatusInserters_.size() == 1);
0191 REQUIRE(builder.endPathStatusInserters_.empty());
0192 REQUIRE(builder.resultsInserter_);
0193 }
0194
0195 SECTION("one module on endpath") {
0196
0197 edm::SignallingProductRegistryFiller productRegistry;
0198 edm::ActivityRegistry activityRegistry;
0199
0200 edm::ModuleRegistry moduleRegistry;
0201 edm::ParameterSet pset;
0202 pset.addParameter<std::string>("@module_type", "edm::test::sb::SBIntProducer");
0203 pset.addParameter<std::string>("@module_edm_type", "EDProducer");
0204 pset.registerIt();
0205
0206 edm::ModuleDescription desc(
0207 pset.id(), "edm::test::sb::SBIntProducer", "prod1", processConfig.get(), edm::ModuleDescription::getUniqueID());
0208 moduleRegistry.makeExplicitModule<edm::test::sb::SBIntProducer>(desc,
0209 prealloc,
0210 &productRegistry,
0211 activityRegistry.preModuleConstructionSignal_,
0212 activityRegistry.postModuleConstructionSignal_,
0213 std::vector<edm::InputTag>());
0214
0215 ConfigBuilder confBuilder;
0216 confBuilder.addModule("prod1", "edm::test::sb::SBIntProducer", EdmType::kProducer);
0217 confBuilder.addEndPath("e", {{"prod1"}});
0218 auto config = confBuilder.buildConfig();
0219 edm::ScheduleBuilder builder(moduleRegistry,
0220 config,
0221 confBuilder.paths(),
0222 confBuilder.endpaths(),
0223 prealloc,
0224 productRegistry,
0225 activityRegistry,
0226 processConfig);
0227
0228 REQUIRE(builder.endpathNameAndModules_.size() == 1);
0229 REQUIRE(builder.endpathNameAndModules_.front().first == "e");
0230 REQUIRE(builder.endpathNameAndModules_.front().second.size() == 1);
0231 auto moduleInfo = builder.endpathNameAndModules_.front().second.front();
0232 REQUIRE(moduleInfo.description_->moduleLabel() == "prod1");
0233 REQUIRE(moduleInfo.description_->moduleName() == "edm::test::sb::SBIntProducer");
0234 REQUIRE(moduleInfo.action_ == edm::WorkerInPath::Normal);
0235 REQUIRE(moduleInfo.placeInPath_ == 0);
0236 REQUIRE(moduleInfo.runConcurrently_ == true);
0237 REQUIRE(builder.pathNameAndModules_.empty());
0238 REQUIRE(builder.allNeededModules_.size() == 1);
0239 REQUIRE(std::find_if(builder.allNeededModules_.begin(), builder.allNeededModules_.end(), [&desc](auto const* el) {
0240 return *el == desc;
0241 }) != builder.allNeededModules_.end());
0242 REQUIRE(builder.unscheduledModules_.empty());
0243 REQUIRE(builder.pathStatusInserters_.empty());
0244 REQUIRE(builder.endPathStatusInserters_.empty());
0245 REQUIRE(not builder.resultsInserter_);
0246 }
0247 }