Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement framework modules for EventID-related tests #46790

Merged
merged 2 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions FWCore/Modules/src/EmptySourceFromEventIDs.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "FWCore/Framework/interface/Event.h"
#include "FWCore/Framework/interface/InputSource.h"
#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
#include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
#include "FWCore/Sources/interface/IDGeneratorSourceBase.h"

/*
* IDGeneratorSourceBase implements the logic to generate run, lumi, and event numbers, and event timestamps.
* These will actually be overwritten by this source, but it's easier to do that than to write a new source base
* type from scratch.
*/

class EmptySourceFromEventIDs : public edm::IDGeneratorSourceBase<edm::InputSource> {
public:
explicit EmptySourceFromEventIDs(edm::ParameterSet const&, edm::InputSourceDescription const&);
~EmptySourceFromEventIDs() override = default;

static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);

private:
bool setRunAndEventInfo(edm::EventID& id, edm::TimeValue_t& time, edm::EventAuxiliary::ExperimentType& type) override;
void readEvent_(edm::EventPrincipal& e) override;

std::vector<edm::EventID> events_;
};

// Note that almost all configuration parameters passed to IDGeneratorSourceBase will effectively be ignored, because
// the EmptySourceFromEventIDs will explicitly set the run, lumi, and event numbers, the timestamp, and the event type.
EmptySourceFromEventIDs::EmptySourceFromEventIDs(edm::ParameterSet const& config,
edm::InputSourceDescription const& desc)
: IDGeneratorSourceBase<InputSource>(config, desc, false),
events_{config.getUntrackedParameter<std::vector<edm::EventID>>("events")} // List of event ids to create
{
// Invert the order of the events so they can efficiently be popped off the back of the vector
std::reverse(events_.begin(), events_.end());
}

bool EmptySourceFromEventIDs::setRunAndEventInfo(edm::EventID& event,
edm::TimeValue_t& time,
edm::EventAuxiliary::ExperimentType& type) {
if (events_.empty()) {
return false;
}

event = std::move(events_.back());
events_.pop_back();
return true;
}

void EmptySourceFromEventIDs::readEvent_(edm::EventPrincipal& e) {
doReadEvent(e, [](auto const&) {});
}

void EmptySourceFromEventIDs::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
edm::ParameterSetDescription desc;
desc.setComment("Creates runs, lumis and events (containing no products) based on the provided list of event ids.");
edm::IDGeneratorSourceBase<edm::InputSource>::fillDescription(desc);

desc.addUntracked<std::vector<edm::EventID>>("events", {});
descriptions.add("source", desc);
}

#include "FWCore/Framework/interface/InputSourceMacros.h"
DEFINE_FWK_INPUT_SOURCE(EmptySourceFromEventIDs);
2 changes: 2 additions & 0 deletions FWCore/Modules/test/BuildFile.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

<test name="TestFWCoreModulesEmptySourceRunsAndLumis" command="cmsRun ${LOCALTOP}/src/FWCore/Modules/test/emptysource_RunsAndLumis_cfg.py"/>

<test name="TestFWCoreModulesEmptySourceFromEventIDs" command="cmsRun ${LOCALTOP}/src/FWCore/Modules/test/testEmptySourceFromEventIDs_cfg.py"/>

<test name="testGenericConsumer" command="${LOCALTOP}/src/FWCore/Modules/test/testGenericConsumer.sh"/>

<bin file="test_catch2_*.cc" name="TestFWCoreModulesTP">
Expand Down
49 changes: 49 additions & 0 deletions FWCore/Modules/test/testEmptySourceFromEventIDs_cfg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#! /usr/bin/env cmsRun

import FWCore.ParameterSet.Config as cms

events = cms.VEventID(
# Run 100
cms.EventID(100, 1, 1),
cms.EventID(100, 1, 2),
cms.EventID(100, 2, 3),
cms.EventID(100, 2, 4),
cms.EventID(100, 3, 5),
# Run 101
cms.EventID(101, 1, 1),
cms.EventID(101, 1, 2),
cms.EventID(101, 2, 3),
cms.EventID(101, 2, 4),
cms.EventID(101, 3, 5),
# Run 102
cms.EventID(102, 1, 1),
cms.EventID(102, 1, 2),
cms.EventID(102, 2, 3),
cms.EventID(102, 2, 4),
cms.EventID(102, 3, 5),
# Run 103
cms.EventID(103, 1, 1),
cms.EventID(103, 1, 2),
cms.EventID(103, 2, 3),
cms.EventID(103, 2, 4),
cms.EventID(103, 3, 5),
)

process = cms.Process("TEST")

process.source = cms.Source("EmptySourceFromEventIDs",
events = cms.untracked(events)
)

process.maxEvents = cms.untracked.PSet(
input = cms.untracked.int32(42)
)

# EventIDChecker requires synchronizing on LuminosityBlock boundaries
process.options.numberOfThreads = 4
process.options.numberOfStreams = 4
process.options.numberOfConcurrentLuminosityBlocks = 1

process.check = cms.EDAnalyzer("EventIDChecker", eventSequence = cms.untracked(events))

process.endp = cms.EndPath(process.check)
17 changes: 17 additions & 0 deletions FWCore/TestModules/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,23 @@ This package contains modules that are used in framework tests, but
are generic-enough to be usable outside of the framework as well.
Their interfaces are intended to be relatively stable.


## `edmtest::StreamIDFilter`

This module can be used to reject all events in specific streams.


## `edmtest::EventIDProducer`

This module reads the `EventID` from the current event and copies it as a data
product into the `Event`.


## `edmtest::EventIDValidator`

This module reads the `EventID` from the current event and compares it to a data
product read from the `Event`.

Together `edmtest::EventIDProducer` and `edmtest::EventIDValidator` can be used
to validate that an object produced in a given event is being read back in the
same event.
3 changes: 3 additions & 0 deletions FWCore/TestModules/plugins/BuildFile.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<use name="DataFormats/Provenance"/>
<use name="FWCore/Framework"/>
<use name="FWCore/ParameterSet"/>
<use name="FWCore/PluginManager"/>
<use name="FWCore/Utilities"/>
<library file="*.cc" name="FWCoreTestModulesPlugins">
<flags EDM_PLUGIN="1"/>
</library>
31 changes: 31 additions & 0 deletions FWCore/TestModules/plugins/EventIDProducer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// CMSSW include files
#include "DataFormats/Provenance/interface/EventID.h"
#include "FWCore/Framework/interface/Event.h"
#include "FWCore/Framework/interface/global/EDProducer.h"
#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
#include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
#include "FWCore/Utilities/interface/EDPutToken.h"

namespace edmtest {

class EventIDProducer : public edm::global::EDProducer<> {
public:
EventIDProducer(edm::ParameterSet const& config) : token_(produces()) {}

void produce(edm::StreamID, edm::Event& event, edm::EventSetup const&) const final {
event.emplace(token_, event.id());
}

static void fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
edm::ParameterSetDescription desc;
descriptions.addWithDefaultLabel(desc);
}

private:
edm::EDPutTokenT<edm::EventID> token_;
};

} // namespace edmtest

#include "FWCore/Framework/interface/MakerMacros.h"
DEFINE_FWK_MODULE(edmtest::EventIDProducer);
40 changes: 40 additions & 0 deletions FWCore/TestModules/plugins/EventIDValidator.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// CMSSW include files
#include "DataFormats/Provenance/interface/EventID.h"
#include "FWCore/Framework/interface/Event.h"
#include "FWCore/Framework/interface/global/EDAnalyzer.h"
#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
#include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
#include "FWCore/Utilities/interface/EDGetToken.h"
#include "FWCore/Utilities/interface/Exception.h"

namespace edmtest {

class EventIDValidator : public edm::global::EDAnalyzer<> {
public:
EventIDValidator(edm::ParameterSet const& config)
: token_(consumes(config.getUntrackedParameter<edm::InputTag>("source"))) {}

void analyze(edm::StreamID, edm::Event const& event, edm::EventSetup const&) const final {
auto const& id = event.get(token_);
if (id != event.id()) {
throw cms::Exception("InvalidValue") << "EventIDValidator: found invalid input value\n"
<< id << "\nwhile expecting\n"
<< event.id();
}
}

static void fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
edm::ParameterSetDescription desc;
desc.addUntracked("source", edm::InputTag{"eventIDProducer", ""})
->setComment("EventID product to read from the event");
descriptions.addWithDefaultLabel(desc);
}

private:
edm::EDGetTokenT<edm::EventID> token_;
};

} // namespace edmtest

#include "FWCore/Framework/interface/MakerMacros.h"
DEFINE_FWK_MODULE(edmtest::EventIDValidator);
1 change: 1 addition & 0 deletions FWCore/TestModules/test/BuildFile.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<test name="TestFWCoreModulesEventIDValidator" command="cmsRun ${LOCALTOP}/src/FWCore/TestModules/test/testEventIDValidator_cfg.py"/>
17 changes: 17 additions & 0 deletions FWCore/TestModules/test/testEventIDValidator_cfg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import FWCore.ParameterSet.Config as cms

process = cms.Process("TEST")

process.options.numberOfThreads = 4
process.options.numberOfStreams = 4

process.source = cms.Source("EmptySource")
process.maxEvents.input = 10

process.eventIds = cms.EDProducer("edmtest::EventIDProducer")

process.eventValidator = cms.EDAnalyzer("edmtest::EventIDValidator",
source = cms.untracked.InputTag('eventIds')
)

process.path = cms.Path(process.eventIds + process.eventValidator)