diff --git a/FWCore/Framework/src/ScheduleItems.cc b/FWCore/Framework/src/ScheduleItems.cc index e2c23426e8f5f..008cb4a1041c0 100644 --- a/FWCore/Framework/src/ScheduleItems.cc +++ b/FWCore/Framework/src/ScheduleItems.cc @@ -134,8 +134,15 @@ namespace edm { act_table_ = std::make_unique(parameterSet); std::string processName = parameterSet.getParameter("@process_name"); - processConfiguration_ = std::make_shared( - processName, getReleaseVersion(), getPassID()); // propagate_const has no reset() function + std::string releaseVersion; + if (parameterSet.existsAs("@special_override_release_version_only_for_testing", false)) { + releaseVersion = + parameterSet.getUntrackedParameter("@special_override_release_version_only_for_testing"); + } else { + releaseVersion = getReleaseVersion(); + } + // propagate_const has no reset() function + processConfiguration_ = std::make_shared(processName, releaseVersion, getPassID()); auto common = std::make_shared( parameterSet.getUntrackedParameterSet("maxEvents").getUntrackedParameter("input"), parameterSet.getUntrackedParameterSet("maxLuminosityBlocks").getUntrackedParameter("input"), diff --git a/FWCore/Framework/test/stubs/RunLumiEventAnalyzer.cc b/FWCore/Framework/test/stubs/RunLumiEventAnalyzer.cc index b49e923365adb..f55bafea176a5 100644 --- a/FWCore/Framework/test/stubs/RunLumiEventAnalyzer.cc +++ b/FWCore/Framework/test/stubs/RunLumiEventAnalyzer.cc @@ -1,51 +1,87 @@ - -#include "FWCore/Framework/test/stubs/RunLumiEventAnalyzer.h" - #include "DataFormats/Common/interface/Handle.h" #include "DataFormats/Common/interface/TriggerResults.h" #include "FWCore/Framework/interface/Event.h" #include "FWCore/Framework/interface/LuminosityBlock.h" #include "FWCore/Framework/interface/MakerMacros.h" #include "FWCore/Framework/interface/Run.h" +#include "FWCore/Framework/interface/one/EDAnalyzer.h" #include "FWCore/MessageLogger/interface/MessageLogger.h" #include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/EDGetToken.h" #include "FWCore/Utilities/interface/Exception.h" +#include "FWCore/Utilities/interface/propagate_const.h" #include -#include +#include namespace edmtest { + class RunLumiEventAnalyzer : public edm::one::EDAnalyzer { + public: + explicit RunLumiEventAnalyzer(edm::ParameterSet const& pset); + + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + + void analyze(edm::Event const& event, edm::EventSetup const& es) final; + void beginRun(edm::Run const& run, edm::EventSetup const& es) final; + void endRun(edm::Run const& run, edm::EventSetup const& es) final; + void beginLuminosityBlock(edm::LuminosityBlock const& lumi, edm::EventSetup const& es) final; + void endLuminosityBlock(edm::LuminosityBlock const& lumi, edm::EventSetup const& es) final; + void endJob(); + + private: + std::vector expectedRunLumisEvents0_; + std::vector expectedRunLumisEvents1_; + edm::propagate_const*> const expectedRunLumisEvents_; + bool const verbose_; + bool const dumpTriggerResults_; + int const expectedEndingIndex0_; + int const expectedEndingIndex1_; + int const expectedEndingIndex_; + edm::EDGetTokenT triggerResultsToken_; + int index_ = 0; + }; RunLumiEventAnalyzer::RunLumiEventAnalyzer(edm::ParameterSet const& pset) : expectedRunLumisEvents0_(), expectedRunLumisEvents1_(), expectedRunLumisEvents_(&expectedRunLumisEvents0_), - index_(0), - verbose_(pset.getUntrackedParameter("verbose", false)), - dumpTriggerResults_(pset.getUntrackedParameter("dumpTriggerResults", false)), - expectedEndingIndex0_(pset.getUntrackedParameter("expectedEndingIndex", -1)), - expectedEndingIndex1_(pset.getUntrackedParameter("expectedEndingIndex1", -1)), + verbose_(pset.getUntrackedParameter("verbose")), + dumpTriggerResults_(pset.getUntrackedParameter("dumpTriggerResults")), + expectedEndingIndex0_(pset.getUntrackedParameter("expectedEndingIndex")), + expectedEndingIndex1_(pset.getUntrackedParameter("expectedEndingIndex1")), expectedEndingIndex_(expectedEndingIndex0_) { - if (pset.existsAs >("expectedRunLumiEvents", false)) { - std::vector temp = pset.getUntrackedParameter >("expectedRunLumiEvents"); + if (pset.existsAs>("expectedRunLumiEvents", false)) { + std::vector temp = pset.getUntrackedParameter>("expectedRunLumiEvents"); expectedRunLumisEvents0_.assign(temp.begin(), temp.end()); } else { - expectedRunLumisEvents0_ = pset.getUntrackedParameter >( - "expectedRunLumiEvents", std::vector()); + expectedRunLumisEvents0_ = pset.getUntrackedParameter>("expectedRunLumiEvents"); } - if (pset.existsAs >("expectedRunLumiEvents1", false)) { - std::vector temp = pset.getUntrackedParameter >("expectedRunLumiEvents1"); + if (pset.existsAs>("expectedRunLumiEvents1", false)) { + std::vector temp = pset.getUntrackedParameter>("expectedRunLumiEvents1"); expectedRunLumisEvents1_.assign(temp.begin(), temp.end()); } else { - expectedRunLumisEvents1_ = pset.getUntrackedParameter >( - "expectedRunLumiEvents1", std::vector()); + expectedRunLumisEvents1_ = pset.getUntrackedParameter>("expectedRunLumiEvents1"); } if (dumpTriggerResults_) { triggerResultsToken_ = consumes(edm::InputTag("TriggerResults")); } } + void RunLumiEventAnalyzer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + desc.addUntracked("verbose", false); + desc.addUntracked("dumpTriggerResults", false); + desc.addUntracked("expectedEndingIndex", -1); + desc.addUntracked("expectedEndingIndex1", -1); + desc.addNode(edm::ParameterDescription>("expectedRunLumiEvents", {}, false) xor + edm::ParameterDescription>("expectedRunLumiEvents", {}, false)); + desc.addNode(edm::ParameterDescription>("expectedRunLumiEvents1", {}, false) xor + edm::ParameterDescription>("expectedRunLumiEvents1", {}, false)); + + descriptions.addDefault(desc); + } + void RunLumiEventAnalyzer::analyze(edm::Event const& event, edm::EventSetup const&) { if (verbose_) { edm::LogAbsolute("RunLumiEvent") << "RUN_LUMI_EVENT " << event.run() << ", " << event.luminosityBlock() << ", " diff --git a/FWCore/Framework/test/stubs/RunLumiEventAnalyzer.h b/FWCore/Framework/test/stubs/RunLumiEventAnalyzer.h deleted file mode 100644 index ab02420502755..0000000000000 --- a/FWCore/Framework/test/stubs/RunLumiEventAnalyzer.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef Integration_RunLumiEventAnalyzer_h -#define Integration_RunLumiEventAnalyzer_h - -#include "FWCore/Framework/interface/Frameworkfwd.h" -#include "FWCore/Framework/interface/one/EDAnalyzer.h" -#include "FWCore/Utilities/interface/EDGetToken.h" -#include "FWCore/Utilities/interface/propagate_const.h" - -#include - -namespace edm { - class TriggerResults; -} - -namespace edmtest { - - class RunLumiEventAnalyzer : public edm::one::EDAnalyzer { - public: - explicit RunLumiEventAnalyzer(edm::ParameterSet const& pset); - - virtual ~RunLumiEventAnalyzer() {} - - virtual void analyze(edm::Event const& event, edm::EventSetup const& es); - virtual void beginRun(edm::Run const& run, edm::EventSetup const& es); - virtual void endRun(edm::Run const& run, edm::EventSetup const& es); - virtual void beginLuminosityBlock(edm::LuminosityBlock const& lumi, edm::EventSetup const& es); - virtual void endLuminosityBlock(edm::LuminosityBlock const& lumi, edm::EventSetup const& es); - virtual void endJob(); - - private: - std::vector expectedRunLumisEvents0_; - std::vector expectedRunLumisEvents1_; - edm::propagate_const*> expectedRunLumisEvents_; - int index_; - bool verbose_; - bool dumpTriggerResults_; - int expectedEndingIndex0_; - int expectedEndingIndex1_; - int expectedEndingIndex_; - edm::EDGetTokenT triggerResultsToken_; - }; -} // namespace edmtest - -#endif diff --git a/FWCore/Framework/test/stubs/TestMergeResults.cc b/FWCore/Framework/test/stubs/TestMergeResults.cc index ab75ad830bb2f..e0d5184097124 100644 --- a/FWCore/Framework/test/stubs/TestMergeResults.cc +++ b/FWCore/Framework/test/stubs/TestMergeResults.cc @@ -45,6 +45,8 @@ namespace edmtest { public: explicit TestMergeResults(edm::ParameterSet const&); + static void fillDescriptions(edm::ConfigurationDescriptions&); + void analyze(edm::Event const& e, edm::EventSetup const& c) override; void beginRun(edm::Run const&, edm::EventSetup const&) override; void endRun(edm::Run const&, edm::EventSetup const&) override; @@ -74,84 +76,70 @@ namespace edmtest { int actualValue, bool unexpectedImproperlyMergedValue = false) const; - std::vector default_; - std::vector defaultvstring_; - - std::vector expectedBeginRunProd_; - std::vector expectedEndRunProd_; - std::vector expectedBeginLumiProd_; - std::vector expectedEndLumiProd_; + std::vector const expectedBeginRunProd_; + std::vector const expectedEndRunProd_; + std::vector const expectedBeginLumiProd_; + std::vector const expectedEndLumiProd_; - std::vector expectedBeginRunNew_; - std::vector expectedEndRunNew_; - std::vector expectedBeginLumiNew_; - std::vector expectedEndLumiNew_; + std::vector const expectedBeginRunNew_; + std::vector const expectedEndRunNew_; + std::vector const expectedBeginLumiNew_; + std::vector const expectedEndLumiNew_; - std::vector expectedEndRunProdImproperlyMerged_; - std::vector expectedEndLumiProdImproperlyMerged_; + std::vector const expectedEndRunProdImproperlyMerged_; + std::vector const expectedEndLumiProdImproperlyMerged_; - std::vector expectedParents_; + std::vector const expectedParents_; - std::vector expectedProcessHistoryInRuns_; + std::vector const expectedProcessHistoryInRuns_; - std::vector expectedDroppedEvent_; - std::vector expectedDroppedEvent1_; - std::vector expectedDroppedEvent1NEvents_; + std::vector const expectedDroppedEvent_; + std::vector const expectedDroppedEvent1_; + std::vector const expectedDroppedEvent1NEvents_; - bool verbose_; + bool const verbose_; + bool const testAlias_; - unsigned int indexRun_; - unsigned int indexLumi_; - unsigned int parentIndex_; - unsigned int droppedIndex1_; - int droppedIndex1EventCount_; - unsigned int processHistoryIndex_; + unsigned int indexRun_ = 0; + unsigned int indexLumi_ = 0; + unsigned int parentIndex_ = 0; + unsigned int droppedIndex1_ = 0; + int droppedIndex1EventCount_ = 0; + unsigned int processHistoryIndex_ = 0; edm::Handle h_thing; edm::Handle h_thingWithMerge; edm::Handle h_thingWithIsEqual; - - bool testAlias_; }; // ----------------------------------------------------------------- TestMergeResults::TestMergeResults(edm::ParameterSet const& ps) - : default_(), - defaultvstring_(), - expectedBeginRunProd_(ps.getUntrackedParameter >("expectedBeginRunProd", default_)), - expectedEndRunProd_(ps.getUntrackedParameter >("expectedEndRunProd", default_)), - expectedBeginLumiProd_(ps.getUntrackedParameter >("expectedBeginLumiProd", default_)), - expectedEndLumiProd_(ps.getUntrackedParameter >("expectedEndLumiProd", default_)), - - expectedBeginRunNew_(ps.getUntrackedParameter >("expectedBeginRunNew", default_)), - expectedEndRunNew_(ps.getUntrackedParameter >("expectedEndRunNew", default_)), - expectedBeginLumiNew_(ps.getUntrackedParameter >("expectedBeginLumiNew", default_)), - expectedEndLumiNew_(ps.getUntrackedParameter >("expectedEndLumiNew", default_)), + : expectedBeginRunProd_(ps.getUntrackedParameter>("expectedBeginRunProd")), + expectedEndRunProd_(ps.getUntrackedParameter>("expectedEndRunProd")), + expectedBeginLumiProd_(ps.getUntrackedParameter>("expectedBeginLumiProd")), + expectedEndLumiProd_(ps.getUntrackedParameter>("expectedEndLumiProd")), + + expectedBeginRunNew_(ps.getUntrackedParameter>("expectedBeginRunNew")), + expectedEndRunNew_(ps.getUntrackedParameter>("expectedEndRunNew")), + expectedBeginLumiNew_(ps.getUntrackedParameter>("expectedBeginLumiNew")), + expectedEndLumiNew_(ps.getUntrackedParameter>("expectedEndLumiNew")), expectedEndRunProdImproperlyMerged_( - ps.getUntrackedParameter >("expectedEndRunProdImproperlyMerged", default_)), + ps.getUntrackedParameter>("expectedEndRunProdImproperlyMerged")), expectedEndLumiProdImproperlyMerged_( - ps.getUntrackedParameter >("expectedEndLumiProdImproperlyMerged", default_)), + ps.getUntrackedParameter>("expectedEndLumiProdImproperlyMerged")), - expectedParents_(ps.getUntrackedParameter >("expectedParents", defaultvstring_)), + expectedParents_(ps.getUntrackedParameter>("expectedParents")), expectedProcessHistoryInRuns_( - ps.getUntrackedParameter >("expectedProcessHistoryInRuns", defaultvstring_)), - - expectedDroppedEvent_(ps.getUntrackedParameter >("expectedDroppedEvent", default_)), - expectedDroppedEvent1_(ps.getUntrackedParameter >("expectedDroppedEvent1", default_)), - expectedDroppedEvent1NEvents_( - ps.getUntrackedParameter >("expectedDroppedEvent1NEvents", default_)), - - verbose_(ps.getUntrackedParameter("verbose", false)), - - indexRun_(0), - indexLumi_(0), - parentIndex_(0), - droppedIndex1_(0), - droppedIndex1EventCount_(0), - processHistoryIndex_(0), - testAlias_(ps.getUntrackedParameter("testAlias", false)) { + ps.getUntrackedParameter>("expectedProcessHistoryInRuns")), + + expectedDroppedEvent_(ps.getUntrackedParameter>("expectedDroppedEvent")), + expectedDroppedEvent1_(ps.getUntrackedParameter>("expectedDroppedEvent1")), + expectedDroppedEvent1NEvents_(ps.getUntrackedParameter>("expectedDroppedEvent1NEvents")), + + verbose_(ps.getUntrackedParameter("verbose")), + testAlias_(ps.getUntrackedParameter("testAlias")) { auto ap_thing = std::make_unique(); edm::Wrapper w_thing(std::move(ap_thing)); assert(!w_thing.isMergeable()); @@ -277,6 +265,61 @@ namespace edmtest { // ----------------------------------------------------------------- + void TestMergeResults::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + desc.addUntracked>("expectedBeginRunProd", {}) + ->setComment( + "Check the expected values of Thing, ThingWithMerge, ThingWithIsEqual from process PROD at beginRun."); + desc.addUntracked>("expectedEndRunProd", {}) + ->setComment( + "Check the expected values of Thing, ThingWithMerge, ThingWithIsEqual from process PROD at nendRun."); + desc.addUntracked>("expectedBeginLumiProd", {}) + ->setComment( + "Check the expected values of Thing, ThingWithMerge, ThingWithIsEqual from process PROD at " + "beginLuminosityBlock."); + desc.addUntracked>("expectedEndLumiProd", {}) + ->setComment( + "Check the expected values of Thing, ThingWithMerge, ThingWithIsEqual from process PROD at " + "endLuminosityBlock."); + + desc.addUntracked>("expectedBeginRunNew", {}) + ->setComment( + "Check the expected values of Thing, ThingWithMerge, ThingWithIsEqual from the latest process at " + "beginRun."); + desc.addUntracked>("expectedEndRunNew", {}) + ->setComment( + "Check the expected values of Thing, ThingWithMerge, ThingWithIsEqual from the latest process at endRun."); + desc.addUntracked>("expectedBeginLumiNew", {}) + ->setComment( + "Check the expected values of Thing, ThingWithMerge, ThingWithIsEqual from the latest process at " + "beginLuminosityBlock."); + desc.addUntracked>("expectedEndLumiNew", {}) + ->setComment( + "Check the expected values of Thing, ThingWithMerge, ThingWithIsEqual from the latest process at " + "endLuminosityBlock."); + + desc.addUntracked>("expectedEndRunProdImproperlyMerged", {}); + desc.addUntracked>("expectedEndLumiProdImproperlyMerged", {}); + desc.addUntracked>("expectedParents", {}); + desc.addUntracked>("expectedProcessHistoryInRuns", {}); + desc.addUntracked>("expectedDroppedEvent", {}); + desc.addUntracked>("expectedDroppedEvent1", {}); + desc.addUntracked>("expectedDroppedEvent1NEvents", {}); + + desc.addUntracked("testAlias", false); + desc.addUntracked("verbose", false); + + desc.setComment( + "The expected{Begin,End}(Run,Lumi}{Prod,New} parameters follow the same pattern. The expected values come in " + "sets of three: value expected in Thing, ThingWithMerge, and ThingWithIsEqual. Each set of 3 is tested at the " + "specific transition, and then the next set of 3 is tested at the next transition, and so on. When the " + "sequence of parameter values is exhausted, the checking is stopped. The values if 0 are just placedholders, " + "i.e. if the value is a 0, the check is not made."); + + descriptions.addDefault(desc); + } + + // ----------------------------------------------------------------- void TestMergeResults::analyze(edm::Event const& e, edm::EventSetup const&) { assert(e.processHistory().id() == e.processHistoryID()); diff --git a/FWCore/ParameterSet/python/Config.py b/FWCore/ParameterSet/python/Config.py index 031cf11befd0e..c729bd14f56c9 100644 --- a/FWCore/ParameterSet/python/Config.py +++ b/FWCore/ParameterSet/python/Config.py @@ -149,6 +149,7 @@ def __init__(self,name: str, *Mods): self.__isStrict = False self.__dict__['_Process__modifiers'] = Mods self.__dict__['_Process__accelerators'] = {} + self.__dict__['_Process__specialOverrideReleaseVersionOnlyForTesting'] = None self.__injectValidValue('options', Process.defaultOptions_()) self.__injectValidValue('maxEvents', Process.defaultMaxEvents_()) self.maxLuminosityBlocks = Process.defaultMaxLuminosityBlocks_() @@ -813,6 +814,10 @@ def extend(self,other,items=()): self.__dict__['_Process__InExtendCall'] = False + def _specialOverrideReleaseVersionOnlyForTesting(self, version): + "This function is intended only for specific framework tests. Do not use for anything else." + self.__specialOverrideReleaseVersionOnlyForTesting = version + def _dumpConfigNamedList(self,items,typeName:str,options:PrintOptions) -> str: returnValue = '' for name,item in items: @@ -1458,6 +1463,8 @@ def __extractPSet(self,pset): self.validate() processPSet.addString(True, "@process_name", self.name_()) + if self.__specialOverrideReleaseVersionOnlyForTesting is not None: + processPSet.addString(False, "@special_override_release_version_only_for_testing", self.__specialOverrideReleaseVersionOnlyForTesting) self.handleProcessAccelerators(processPSet) all_modules = self.producers_().copy() all_modules.update(self.filters_()) @@ -4944,4 +4951,16 @@ def testProcessAccelerator(self): self.assertEqual((False, "sp@test1"), p.values["sp"][1].values["@chosen_case"]) self.assertEqual(["cpu", "test1"], p.values["@available_accelerators"][1]) + def testProcessSpecialOverrideReleaseVersion(self): + proc = Process("TEST") + p = TestMakePSet() + proc.fillProcessDesc(p) + self.assertFalse("@special_override_release_version_only_for_testing" in p.values) + + proc = Process("TEST") + proc._specialOverrideReleaseVersionOnlyForTesting("CMSSW_15_0_0") + p = TestMakePSet() + proc.fillProcessDesc(p) + self.assertEqual((False, "CMSSW_15_0_0"), p.values["@special_override_release_version_only_for_testing"]) + unittest.main() diff --git a/IOPool/Input/test/BuildFile.xml b/IOPool/Input/test/BuildFile.xml index 16f8aea45fcab..7aeda0519ec7c 100644 --- a/IOPool/Input/test/BuildFile.xml +++ b/IOPool/Input/test/BuildFile.xml @@ -1,6 +1,4 @@ - - @@ -21,10 +19,25 @@ + + + + + + + + + + + + - + + + + diff --git a/IOPool/Input/test/TestPoolInput.sh b/IOPool/Input/test/TestPoolInput.sh index 46a9316061f56..6aae9800d8c32 100755 --- a/IOPool/Input/test/TestPoolInput.sh +++ b/IOPool/Input/test/TestPoolInput.sh @@ -58,90 +58,3 @@ cmsRun ${LOCAL_TEST_DIR}/PoolAliasSubProcessTestStep1_cfg.py || die 'Failure usi cmsRun ${LOCAL_TEST_DIR}/PoolAliasSubProcessTestStep2_cfg.py || die 'Failure using PoolAliasSubProcessTestStep2_cfg.py' $? -cmsRun ${LOCAL_TEST_DIR}/PrePoolInputTest_cfg.py RunPerLumiTest.root 50 1 25 1 5 || die 'Failure using PrePoolInputTest_cfg.py' $? - -cmsRun ${LOCAL_TEST_DIR}/RunPerLumiTest_cfg.py 25 >& RunPerLumiTest.txt || die 'Failure using RunPerLumiTest_cfg.py' $? -grep 'record' RunPerLumiTest.txt | cut -d ' ' -f 4-11 > RunPerLumiTest.filtered.txt -diff ${LOCAL_TEST_DIR}/unit_test_outputs/RunPerLumiTest.filtered.txt RunPerLumiTest.filtered.txt || die 'incorrect output using RunPerLumiTest_cfg.py' $? - -cmsRun ${LOCAL_TEST_DIR}/RunPerLumiTest_cfg.py 50 >& tooManyLumis.txt && die 'RunPerLumiTest_cfg.py should have failed but did not' 1 -grep "MismatchedInputFiles" tooManyLumis.txt || die 'RunPerLumiTest_cfg.py should have failed but did not' $? - -cmsRun ${LOCAL_TEST_DIR}/firstLuminosityBlockForEachRunTest_cfg.py 'file:RunPerLumiTest.root' 25 1 25 1 5 || die 'Failure using firstLuminosityBlockForEachRunTest_cfg.py' $? -cmsRun ${LOCAL_TEST_DIR}/PrePoolInputTest_cfg.py firstLumiTest1.root 25 1 100 1 5 || die 'Failure using PrePoolInputTest_cfg.py' $? -cmsRun ${LOCAL_TEST_DIR}/PrePoolInputTest_cfg.py firstLumiTest2.root 25 1 100 6 5 || die 'Failure using PrePoolInputTest_cfg.py' $? -cmsRun ${LOCAL_TEST_DIR}/firstLuminosityBlockForEachRunTest_cfg.py 'file:firstLumiTest1.root,file:firstLumiTest2.root' 50 1 25 1 5 || die 'Failure using firstLuminosityBlockForEachRunTest_cfg.py with 2 files' $? -cmsRun ${LOCAL_TEST_DIR}/firstLuminosityBlockForEachRunTest_cfg.py 'file:firstLumiTest1.root,file:firstLumiTest2.root' 50 1 25 1 5 shareRun || die 'Failure using firstLuminosityBlockForEachRunTest_cfg.py with 2 files which share a run' $? -cmsRun ${LOCAL_TEST_DIR}/firstLuminosityBlockForEachRun_skipLumis_Test_cfg.py 'file:firstLumiTest1.root' 2 || die 'Failure using firstLuminosityBlockForEachRun_skipLumis_Test_cfg.py with first lumi 2' $? -cmsRun ${LOCAL_TEST_DIR}/firstLuminosityBlockForEachRun_skipLumis_Test_cfg.py 'file:firstLumiTest1.root' 4 || die 'Failure using firstLuminosityBlockForEachRun_skipLumis_Test_cfg.py with first lumi 4' $? -cmsRun ${LOCAL_TEST_DIR}/firstLuminosityBlockForEachRun_skipLumis_Test_cfg.py 'file:firstLumiTest1.root' 3 || die 'Failure using firstLuminosityBlockForEachRun_skipLumis_Test_cfg.py with first lumi 3' $? - -cmsRun ${LOCAL_TEST_DIR}/firstLuminosityBlockForEachRun_skipLumis2_Test_cfg.py 'file:firstLumiTest1.root' 2 || die 'Failure using firstLuminosityBlockForEachRun_skipLumis2_Test_cfg.py with first lumi 2' $? -cmsRun ${LOCAL_TEST_DIR}/firstLuminosityBlockForEachRun_skipLumis2_Test_cfg.py 'file:firstLumiTest1.root' 4 || die 'Failure using firstLuminosityBlockForEachRun_skipLumis2_Test_cfg.py with first lumi 4' $? -cmsRun ${LOCAL_TEST_DIR}/firstLuminosityBlockForEachRun_skipLumis2_Test_cfg.py 'file:firstLumiTest1.root' 3 || die 'Failure using firstLuminosityBlockForEachRun_skipLumis2_Test_cfg.py with first lumi 3' $? - - -#test merging of heterogeneous files with extra provenenace in subsequent files - -cmsRun ${LOCAL_TEST_DIR}/preMerge_cfg.py || die 'Failure using preMerge_cfg.py' $? - -cmsRun ${LOCAL_TEST_DIR}/preMerge2_cfg.py || die 'Failure using preMerge2_cfg.py' $? - -cmsRun ${LOCAL_TEST_DIR}/HeteroMerge_cfg.py || die 'Failure using HeteroMerge_cfg.py' $? - -#test reading of the old format files -IOPoolInputData=$CMSSW_BASE/src -for dir in $(echo $CMSSW_SEARCH_PATH | tr : '\n') ; do - if [ -d ${dir}/IOPool/Input/data ] ; then - IOPoolInputData=${dir} - break - fi -done - -for file in ${IOPoolInputData}/IOPool/Input/data/raw*.root -do - cmsRun ${LOCAL_TEST_DIR}/test_old_raw_data_step1_cfg.py "$file" || die "Failed to read old raw data file $file" $? - cmsRun ${LOCAL_TEST_DIR}/test_old_raw_data_step2_cfg.py || die "Failed to read raw data file converted from $file" $? - rm -fr converted.root -done - -for file in ${IOPoolInputData}/IOPool/Input/data/old*.root -do - cmsRun ${LOCAL_TEST_DIR}/test_old_formats_cfg.py "$file" || die "Failed to read old file $file" $? -done - -for file in ${IOPoolInputData}/IOPool/Input/data/empty*.root -do - cmsRun ${LOCAL_TEST_DIR}/test_empty_old_formats_cfg.py "$file" || die "Failed to read old empty file $file" $? -done - -# Note that the expected sequence of runs, lumis, and events changed slightly at 3_8_0 so -# a different test config is required to run the following test for earlier releases. -for file in ${IOPoolInputData}/IOPool/Input/data/complex*.root -do - case $file in - "${IOPoolInputData}/IOPool/Input/data/complex_old_format_CMSSW_2_2_13.root" | "${IOPoolInputData}/IOPool/Input/data/complex_old_format_CMSSW_3_5_0.root" | "${IOPoolInputData}/IOPool/Input/data/complex_old_format_CMSSW_3_7_0.root") - script=test_complex_before_3_8_0_cfg.py - ;; - *) - script=test_complex_old_formats_cfg.py - ;; - esac - cmsRun ${LOCAL_TEST_DIR}/$script "$file" || die "Failed to read old complex file $file" $? -done - -cmsRun ${LOCAL_TEST_DIR}/test_merge_two_files.py ${IOPoolInputData}/IOPool/Input/data/complex_old_format_CMSSW_4_2_7.root ${IOPoolInputData}/IOPool/Input/data/complex_old_format_CMSSW_4_2_8.root || die 'Failure using test_merge_two_files.py' $? - -cmsRun ${LOCAL_TEST_DIR}/test_reduced_ProcessHistory_cfg.py merged_files.root || die 'Failure using test_reduced_ProcessHistory_cfg.py' $? - -cmsRun ${LOCAL_TEST_DIR}/test_reduced_ProcessHistory_dup_cfg.py merged_files.root || die 'Failure using test_reduced_ProcessHistory_dup_cfg.py' $? - -cmsRun ${LOCAL_TEST_DIR}/test_reduced_ProcessHistory_end_cfg.py merged_files.root || die 'Failure using test_reduced_ProcessHistory_end_cfg.py' $? - -cmsRun ${LOCAL_TEST_DIR}/test_make_multi_lumi_cfg.py || die 'Failure using test_make_multi_lumi_cfg.py' $? -cmsRun ${LOCAL_TEST_DIR}/test_read_multi_lumi_as_one_cfg.py || die 'Failure using test_read_multi_lumi_as_one_cfg.py' $? - -cmsRun ${LOCAL_TEST_DIR}/test_make_overlapping_lumis_cfg.py || die 'Failure using test_make_overlapping_lumis_cfg.py' $? -cmsRun ${LOCAL_TEST_DIR}/test_read_overlapping_lumis_cfg.py || die 'Failure using test_read_overlapping_lumis_cfg.py' $? - -exit 0 diff --git a/IOPool/Input/test/TestPoolInputOldFormat.sh b/IOPool/Input/test/TestPoolInputOldFormat.sh new file mode 100755 index 0000000000000..fefa96b26654f --- /dev/null +++ b/IOPool/Input/test/TestPoolInputOldFormat.sh @@ -0,0 +1,54 @@ +#!/bin/sh -ex +# Pass in name and status +function die { echo $1: status $2 ; exit $2; } + +LOCAL_TEST_DIR=${SCRAM_TEST_PATH} + +#test reading of the old format files +IOPoolInputData=$CMSSW_BASE/src +for dir in $(echo $CMSSW_SEARCH_PATH | tr : '\n') ; do + if [ -d ${dir}/IOPool/Input/data ] ; then + IOPoolInputData=${dir} + break + fi +done + +for file in ${IOPoolInputData}/IOPool/Input/data/raw*.root +do + cmsRun ${LOCAL_TEST_DIR}/test_old_raw_data_step1_cfg.py "$file" || die "Failed to read old raw data file $file" $? + cmsRun ${LOCAL_TEST_DIR}/test_old_raw_data_step2_cfg.py || die "Failed to read raw data file converted from $file" $? + rm -fr converted.root +done + +for file in ${IOPoolInputData}/IOPool/Input/data/old*.root +do + cmsRun ${LOCAL_TEST_DIR}/test_old_formats_cfg.py "$file" || die "Failed to read old file $file" $? +done + +for file in ${IOPoolInputData}/IOPool/Input/data/empty*.root +do + cmsRun ${LOCAL_TEST_DIR}/test_empty_old_formats_cfg.py "$file" || die "Failed to read old empty file $file" $? +done + +# Note that the expected sequence of runs, lumis, and events changed slightly at 3_8_0 so +# a different test config is required to run the following test for earlier releases. +for file in ${IOPoolInputData}/IOPool/Input/data/complex*.root +do + case $file in + "${IOPoolInputData}/IOPool/Input/data/complex_old_format_CMSSW_2_2_13.root" | "${IOPoolInputData}/IOPool/Input/data/complex_old_format_CMSSW_3_5_0.root" | "${IOPoolInputData}/IOPool/Input/data/complex_old_format_CMSSW_3_7_0.root") + script=test_complex_before_3_8_0_cfg.py + ;; + *) + script=test_complex_old_formats_cfg.py + ;; + esac + cmsRun ${LOCAL_TEST_DIR}/$script "$file" || die "Failed to read old complex file $file" $? +done + +cmsRun ${LOCAL_TEST_DIR}/test_merge_two_files.py ${IOPoolInputData}/IOPool/Input/data/complex_old_format_CMSSW_4_2_7.root ${IOPoolInputData}/IOPool/Input/data/complex_old_format_CMSSW_4_2_8.root || die 'Failure using test_merge_two_files.py' $? + +cmsRun ${LOCAL_TEST_DIR}/test_reduced_ProcessHistory_cfg.py merged_files.root || die 'Failure using test_reduced_ProcessHistory_cfg.py' $? + +cmsRun ${LOCAL_TEST_DIR}/test_reduced_ProcessHistory_dup_cfg.py merged_files.root || die 'Failure using test_reduced_ProcessHistory_dup_cfg.py' $? + +cmsRun ${LOCAL_TEST_DIR}/test_reduced_ProcessHistory_end_cfg.py merged_files.root || die 'Failure using test_reduced_ProcessHistory_end_cfg.py' $? diff --git a/IOPool/Input/test/TestPoolInputRunPerLumi.sh b/IOPool/Input/test/TestPoolInputRunPerLumi.sh new file mode 100755 index 0000000000000..66ac121e471f1 --- /dev/null +++ b/IOPool/Input/test/TestPoolInputRunPerLumi.sh @@ -0,0 +1,27 @@ +#!/bin/sh -ex +# Pass in name and status +function die { echo $1: status $2 ; exit $2; } + +LOCAL_TEST_DIR=${SCRAM_TEST_PATH} + +cmsRun ${LOCAL_TEST_DIR}/PrePoolInputTest_cfg.py RunPerLumiTest.root 50 1 25 1 5 || die 'Failure using PrePoolInputTest_cfg.py' $? + +cmsRun ${LOCAL_TEST_DIR}/RunPerLumiTest_cfg.py 25 >& RunPerLumiTest.txt || die 'Failure using RunPerLumiTest_cfg.py' $? +grep 'record' RunPerLumiTest.txt | cut -d ' ' -f 4-11 > RunPerLumiTest.filtered.txt +diff ${LOCAL_TEST_DIR}/unit_test_outputs/RunPerLumiTest.filtered.txt RunPerLumiTest.filtered.txt || die 'incorrect output using RunPerLumiTest_cfg.py' $? + +cmsRun ${LOCAL_TEST_DIR}/RunPerLumiTest_cfg.py 50 >& tooManyLumis.txt && die 'RunPerLumiTest_cfg.py should have failed but did not' 1 +grep "MismatchedInputFiles" tooManyLumis.txt || die 'RunPerLumiTest_cfg.py should have failed but did not' $? + +cmsRun ${LOCAL_TEST_DIR}/firstLuminosityBlockForEachRunTest_cfg.py 'file:RunPerLumiTest.root' 25 1 25 1 5 || die 'Failure using firstLuminosityBlockForEachRunTest_cfg.py' $? +cmsRun ${LOCAL_TEST_DIR}/PrePoolInputTest_cfg.py firstLumiTest1.root 25 1 100 1 5 || die 'Failure using PrePoolInputTest_cfg.py' $? +cmsRun ${LOCAL_TEST_DIR}/PrePoolInputTest_cfg.py firstLumiTest2.root 25 1 100 6 5 || die 'Failure using PrePoolInputTest_cfg.py' $? +cmsRun ${LOCAL_TEST_DIR}/firstLuminosityBlockForEachRunTest_cfg.py 'file:firstLumiTest1.root,file:firstLumiTest2.root' 50 1 25 1 5 || die 'Failure using firstLuminosityBlockForEachRunTest_cfg.py with 2 files' $? +cmsRun ${LOCAL_TEST_DIR}/firstLuminosityBlockForEachRunTest_cfg.py 'file:firstLumiTest1.root,file:firstLumiTest2.root' 50 1 25 1 5 shareRun || die 'Failure using firstLuminosityBlockForEachRunTest_cfg.py with 2 files which share a run' $? +cmsRun ${LOCAL_TEST_DIR}/firstLuminosityBlockForEachRun_skipLumis_Test_cfg.py 'file:firstLumiTest1.root' 2 || die 'Failure using firstLuminosityBlockForEachRun_skipLumis_Test_cfg.py with first lumi 2' $? +cmsRun ${LOCAL_TEST_DIR}/firstLuminosityBlockForEachRun_skipLumis_Test_cfg.py 'file:firstLumiTest1.root' 4 || die 'Failure using firstLuminosityBlockForEachRun_skipLumis_Test_cfg.py with first lumi 4' $? +cmsRun ${LOCAL_TEST_DIR}/firstLuminosityBlockForEachRun_skipLumis_Test_cfg.py 'file:firstLumiTest1.root' 3 || die 'Failure using firstLuminosityBlockForEachRun_skipLumis_Test_cfg.py with first lumi 3' $? + +cmsRun ${LOCAL_TEST_DIR}/firstLuminosityBlockForEachRun_skipLumis2_Test_cfg.py 'file:firstLumiTest1.root' 2 || die 'Failure using firstLuminosityBlockForEachRun_skipLumis2_Test_cfg.py with first lumi 2' $? +cmsRun ${LOCAL_TEST_DIR}/firstLuminosityBlockForEachRun_skipLumis2_Test_cfg.py 'file:firstLumiTest1.root' 4 || die 'Failure using firstLuminosityBlockForEachRun_skipLumis2_Test_cfg.py with first lumi 4' $? +cmsRun ${LOCAL_TEST_DIR}/firstLuminosityBlockForEachRun_skipLumis2_Test_cfg.py 'file:firstLumiTest1.root' 3 || die 'Failure using firstLuminosityBlockForEachRun_skipLumis2_Test_cfg.py with first lumi 3' $? diff --git a/IOPool/Input/test/testReducedProcessHistory.sh b/IOPool/Input/test/testReducedProcessHistory.sh new file mode 100755 index 0000000000000..6000c5de65653 --- /dev/null +++ b/IOPool/Input/test/testReducedProcessHistory.sh @@ -0,0 +1,55 @@ +#!/bin/bash + +function die { echo $1: status $2 ; exit $2; } +function runSuccess { + echo "cmsRun $@" + cmsRun $@ || die "cmsRun $*" $? + echo +} +function runFailure { + echo "cmsRun $@ (expected to fail)" + cmsRun $@ && die "cmsRun $*" 1 + echo +} + +VERSION_ARR=(${CMSSW_VERSION//_/ }) +VERSION1="${VERSION_ARR[0]}_${VERSION_ARR[1]}_${VERSION_ARR[2]}_0" +VERSION2="${VERSION_ARR[0]}_${VERSION_ARR[1]}_${VERSION_ARR[2]}_1" +VERSION3="${VERSION_ARR[0]}_${VERSION_ARR[1]}_$((${VERSION_ARR[2]}+1))_0" + +# Check that changing the patch version does not lead to new lumi or run +runSuccess ${SCRAM_TEST_PATH}/testReducedProcessHistoryCreate_cfg.py --version ${VERSION1} --firstEvent 1 --output version1.root +runSuccess ${SCRAM_TEST_PATH}/testReducedProcessHistoryCreate_cfg.py --version ${VERSION2} --firstEvent 101 --output version2.root + +edmProvDump version1.root | grep -q "PROD.*'${VERSION1}'" || die "Did not find ${VERSION1} from version.root provenance" $? +edmProvDump version2.root | grep -q "PROD.*'${VERSION2}'" || die "Did not find ${VERSION2} from version.root provenance" $? + +runSuccess ${SCRAM_TEST_PATH}/test_merge_two_files.py version1.root version2.root + +runSuccess ${SCRAM_TEST_PATH}/testReducedProcessHistory_cfg.py --input merged_files.root + + +# Check that changing the minor version leads to new lumi +runSuccess ${SCRAM_TEST_PATH}/testReducedProcessHistoryCreate_cfg.py --version ${VERSION3} --firstEvent 201 --output version3_lumi.root + +edmProvDump version3_lumi.root | grep -q "PROD.*'${VERSION3}'" || die "Did not find ${VERSION3} from version3_lumi.root provenance" $? + +runSuccess ${SCRAM_TEST_PATH}/test_merge_two_files.py version1.root version3_lumi.root --output merged_files3_lumi.root --bypassVersionCheck + +runFailure ${SCRAM_TEST_PATH}/testReducedProcessHistory_cfg.py --input merged_files3_lumi.root --bypassVersionCheck + +runSuccess ${SCRAM_TEST_PATH}/testReducedProcessHistory_cfg.py --input merged_files3_lumi.root --bypassVersionCheck --expectNewLumi + + +# Check that changing the minor version leads to new run +runSuccess ${SCRAM_TEST_PATH}/testReducedProcessHistoryCreate_cfg.py --version ${VERSION3} --firstEvent 201 --lumi 2 --output version3_run.root + +edmProvDump version3_run.root | grep -q "PROD.*'${VERSION3}'" || die "Did not find ${VERSION3} from version3_lumi.root provenance" $? + +runSuccess ${SCRAM_TEST_PATH}/test_merge_two_files.py version1.root version3_run.root --output merged_files3_run.root --bypassVersionCheck + +runFailure ${SCRAM_TEST_PATH}/testReducedProcessHistory_cfg.py --input merged_files3_run.root --bypassVersionCheck + +runSuccess ${SCRAM_TEST_PATH}/testReducedProcessHistory_cfg.py --input merged_files3_run.root --bypassVersionCheck --expectNewRun + +exit 0 diff --git a/IOPool/Input/test/testReducedProcessHistoryCreate_cfg.py b/IOPool/Input/test/testReducedProcessHistoryCreate_cfg.py new file mode 100644 index 0000000000000..ca896235e7fc0 --- /dev/null +++ b/IOPool/Input/test/testReducedProcessHistoryCreate_cfg.py @@ -0,0 +1,39 @@ +import FWCore.ParameterSet.Config as cms +import argparse + +parser = argparse.ArgumentParser(description='Create files for reduced ProcessHistory test') +parser.add_argument("--version", type=str, help="CMSSW version to be used in the ProcessHistory") +parser.add_argument("--firstEvent", default=1, type=int, help="Number of first event") +parser.add_argument("--lumi", default=1, type=int, help="LuminosityBlock number") +parser.add_argument("--output", type=str, help="Output file name") + +args = parser.parse_args() + +process = cms.Process("PROD") +process._specialOverrideReleaseVersionOnlyForTesting(args.version) + +process.maxEvents.input = 10 + +from FWCore.Modules.modules import EmptySource +process.source = EmptySource( + firstEvent = args.firstEvent, + firstLuminosityBlock = args.lumi, +) + +from IOPool.Output.modules import PoolOutputModule +process.out = PoolOutputModule( + fileName = args.output +) + +from FWCore.Framework.modules import IntProducer +process.intProducer = IntProducer(ivalue = 42) + +from FWCore.Integration.modules import ThingWithMergeProducer +process.thingWithMergeProducer = ThingWithMergeProducer() + +process.t = cms.Task( + process.intProducer, + process.thingWithMergeProducer, +) +process.p = cms.Path(process.t) +process.ep = cms.EndPath(process.out) diff --git a/IOPool/Input/test/testReducedProcessHistory_cfg.py b/IOPool/Input/test/testReducedProcessHistory_cfg.py new file mode 100644 index 0000000000000..4d4ff297670f5 --- /dev/null +++ b/IOPool/Input/test/testReducedProcessHistory_cfg.py @@ -0,0 +1,117 @@ +import FWCore.ParameterSet.Config as cms +import argparse + +parser = argparse.ArgumentParser(description='Test reduced ProcessHistory') +parser.add_argument("--input", type=str, help="Input file") +parser.add_argument("--bypassVersionCheck", action="store_true", help="Bypass version check") +parser.add_argument("--expectNewLumi", action="store_true", help="Set this if a new lumi is expected between the original files") +parser.add_argument("--expectNewRun", action="store_true", help="Set this if a new run is expected between the original files") + +args = parser.parse_args() + +process = cms.Process("READ") + +from IOPool.Input.modules import PoolSource +process.source = PoolSource( + fileNames = [f"file:{args.input}"], + bypassVersionCheck = args.bypassVersionCheck, +) + +from FWCore.Framework.modules import TestMergeResults, RunLumiEventAnalyzer +process.testmerge = TestMergeResults( + expectedBeginRunProd = [10001, 20004, 10003], + expectedEndRunProd = [100001, 200004, 100003], + expectedBeginLumiProd = [101, 204, 103], + expectedEndLumiProd = [1001, 2004, 1003], + + expectedBeginRunNew = [10001, 10002, 10003], + expectedEndRunNew = [100001, 100002, 100003], + expectedBeginLumiNew = [101, 102, 103], + expectedEndLumiNew = [1001, 1002, 1003], + expectedProcessHistoryInRuns = [ + 'PROD', + 'MERGETWOFILES', + 'READ' + ] +) +def setWithMergeAndCopyEntry(p, value): + p[1] = value + p[3:5] = p[0:2] +if args.expectNewLumi or args.expectNewRun: + setWithMergeAndCopyEntry(process.testmerge.expectedBeginRunProd, 10002) + setWithMergeAndCopyEntry(process.testmerge.expectedEndRunProd, 100002) + setWithMergeAndCopyEntry(process.testmerge.expectedBeginLumiProd, 102) + setWithMergeAndCopyEntry(process.testmerge.expectedEndLumiProd, 1002) + +process.test = RunLumiEventAnalyzer( + expectedRunLumiEvents = [ + 1, 0, 0, # beginRun + 1, 1, 0, # beginLumi + 1, 1, 1, + 1, 1, 2, + 1, 1, 3, + 1, 1, 4, + 1, 1, 5, + 1, 1, 6, + 1, 1, 7, + 1, 1, 8, + 1, 1, 9, + 1, 1, 10, + 1, 1, 101, + 1, 1, 102, + 1, 1, 103, + 1, 1, 104, + 1, 1, 105, + 1, 1, 106, + 1, 1, 107, + 1, 1, 108, + 1, 1, 109, + 1, 1, 110, + 1, 1, 0, # endLumi + 1, 0, 0, # endRun + ] +) +endFirstFileIndex = 3*(10+2) +if args.expectNewLumi: + process.test.expectedRunLumiEvents = process.test.expectedRunLumiEvents[:endFirstFileIndex] + [ + 1, 1, 0, # endLumi + 1, 0, 0, # endRun + 1, 0, 0, # beginRun + 1, 1, 0, # beginLumi + 1, 1, 201, + 1, 1, 202, + 1, 1, 203, + 1, 1, 204, + 1, 1, 205, + 1, 1, 206, + 1, 1, 207, + 1, 1, 208, + 1, 1, 209, + 1, 1, 210, + 1, 1, 0, # endLumi + 1, 0, 0, # endRun + ] +elif args.expectNewRun: + process.test.expectedRunLumiEvents = process.test.expectedRunLumiEvents[:endFirstFileIndex] + [ + 1, 1, 0, # endLumi + 1, 0, 0, # endRun + 1, 0, 0, # beginRun + 1, 2, 0, # beginLumi + 1, 2, 201, + 1, 2, 202, + 1, 2, 203, + 1, 2, 204, + 1, 2, 205, + 1, 2, 206, + 1, 2, 207, + 1, 2, 208, + 1, 2, 209, + 1, 2, 210, + 1, 2, 0, # endLumi + 1, 0, 0, # endRun + ] + +process.p = cms.Path( + process.testmerge + + process.test +) diff --git a/IOPool/Input/test/test_merge_two_files.py b/IOPool/Input/test/test_merge_two_files.py index e12272830dd50..043287436b650 100644 --- a/IOPool/Input/test/test_merge_two_files.py +++ b/IOPool/Input/test/test_merge_two_files.py @@ -1,18 +1,28 @@ import FWCore.ParameterSet.Config as cms -import sys +import argparse + +parser = argparse.ArgumentParser(description='Create files for reduced ProcessHistory test') +parser.add_argument("file1", type=str, help="First file to merge") +parser.add_argument("file2", type=str, help="Second file to merge") +parser.add_argument("--output", default="merged_files.root", help="Output file name") +parser.add_argument("--bypassVersionCheck", action="store_true", help="Bypass version check") + +args = parser.parse_args() process = cms.Process("MERGETWOFILES") -process.source = cms.Source("PoolSource", - fileNames = cms.untracked.vstring("file:"+sys.argv[1], - "file:"+sys.argv[2]), - duplicateCheckMode = cms.untracked.string("noDuplicateCheck") +from IOPool.Input.modules import PoolSource +process.source = PoolSource( + fileNames = ["file:"+args.file1,"file:"+args.file2], + duplicateCheckMode = "noDuplicateCheck", + bypassVersionCheck = args.bypassVersionCheck, ) -process.thingWithMergeProducer = cms.EDProducer("ThingWithMergeProducer") +from FWCore.Integration.modules import ThingWithMergeProducer +process.thingWithMergeProducer = ThingWithMergeProducer() -process.out = cms.OutputModule("PoolOutputModule", - fileName = cms.untracked.string("merged_files.root")) +from IOPool.Output.modules import PoolOutputModule +process.out = PoolOutputModule(fileName = args.output) process.p = cms.Path(process.thingWithMergeProducer)