-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #41395 from wddgit/testTriggerResults
Add unit test for TriggerResults format
- Loading branch information
Showing
7 changed files
with
276 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# DataFormats/Common | ||
|
||
## `edm::TriggerResults` | ||
|
||
The class `edm::TriggerResults` is part of the RAW data, and any changes must be backwards compatible. In order to ensure it can be read by all future CMSSW releases, there is a `TestTriggerResultsFormat` unit test, which makes use of the `TestReadTriggerResults` analyzer and the `TestWriteTriggerResults` producer. The unit test checks that the object can be read properly from | ||
|
||
* a file in the same release as it was written | ||
* files written by (some) earlier releases can be read | ||
|
||
If the persistent format of class `edm::TriggerResults` gets changed in the future, please adjust the `TestReadTriggerResults` and `TestWriteTriggerResults` modules accordingly. It is important that every member container has some content in this test. Please also add a new file to [https://github.com/cms-data/DataFormats-Common/](https://github.com/cms-data/DataFormats-Common/) repository, and update the `TestTriggerResultsFormat` unit test to read the newly created file. The file name should contain the release or pre-release with which it was written.` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
// -*- C++ -*- | ||
// | ||
// Package: DataFormats/Common | ||
// Class: TestReadTriggerResults | ||
// | ||
/**\class edmtest::TestReadTriggerResults | ||
Description: Used as part of tests that ensure the TriggerResults | ||
data format can be persistently written and in a subsequent process | ||
read. First, this is done using the current release version. In | ||
addition, the output file of the write process should be saved | ||
permanently each time its format changes. In unit tests, we read | ||
each of those saved files to verify that all future releases can | ||
read RAW data formats and Scouting data formats. | ||
*/ | ||
// Original Author: W. David Dagenhart | ||
// Created: 18 April 2023 | ||
|
||
#include "DataFormats/Common/interface/TriggerResults.h" | ||
#include "FWCore/Framework/interface/global/EDAnalyzer.h" | ||
#include "FWCore/Framework/interface/Event.h" | ||
#include "FWCore/Framework/interface/Frameworkfwd.h" | ||
#include "FWCore/Framework/interface/MakerMacros.h" | ||
#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" | ||
#include "FWCore/ParameterSet/interface/ParameterSet.h" | ||
#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" | ||
#include "FWCore/Utilities/interface/EDGetToken.h" | ||
#include "FWCore/Utilities/interface/Exception.h" | ||
#include "FWCore/Utilities/interface/InputTag.h" | ||
|
||
#include <string> | ||
#include <vector> | ||
|
||
namespace edmtest { | ||
|
||
class TestReadTriggerResults : public edm::global::EDAnalyzer<> { | ||
public: | ||
TestReadTriggerResults(edm::ParameterSet const&); | ||
void analyze(edm::StreamID, edm::Event const&, edm::EventSetup const&) const override; | ||
void throwWithMessage(const char*) const; | ||
static void fillDescriptions(edm::ConfigurationDescriptions&); | ||
|
||
private: | ||
std::string expectedParameterSetID_; | ||
std::vector<std::string> expectedNames_; | ||
std::vector<unsigned int> expectedHLTStates_; | ||
std::vector<unsigned int> expectedModuleIndexes_; | ||
edm::EDGetTokenT<edm::TriggerResults> triggerResultsToken_; | ||
}; | ||
|
||
TestReadTriggerResults::TestReadTriggerResults(edm::ParameterSet const& iPSet) | ||
: expectedParameterSetID_(iPSet.getParameter<std::string>("expectedParameterSetID")), | ||
expectedNames_(iPSet.getParameter<std::vector<std::string>>("expectedNames")), | ||
expectedHLTStates_(iPSet.getParameter<std::vector<unsigned int>>("expectedHLTStates")), | ||
expectedModuleIndexes_(iPSet.getParameter<std::vector<unsigned int>>("expectedModuleIndexes")), | ||
triggerResultsToken_(consumes(iPSet.getParameter<edm::InputTag>("triggerResultsTag"))) {} | ||
|
||
void TestReadTriggerResults::analyze(edm::StreamID, edm::Event const& iEvent, edm::EventSetup const&) const { | ||
auto const& triggerResults = iEvent.get(triggerResultsToken_); | ||
std::string parameterSetID; | ||
triggerResults.parameterSetID().toString(parameterSetID); | ||
if (parameterSetID != expectedParameterSetID_) { | ||
throwWithMessage("parameterSetID does not match expected value"); | ||
} | ||
if (triggerResults.getTriggerNames() != expectedNames_) { | ||
throwWithMessage("names vector does not include expected values"); | ||
} | ||
if (expectedHLTStates_.size() != expectedModuleIndexes_.size()) { | ||
throwWithMessage( | ||
"test configuration error, expectedHLTStates and expectedModuleIndexes should have the same size"); | ||
} | ||
if (triggerResults.size() != expectedHLTStates_.size()) { | ||
throwWithMessage("paths has unexpected size"); | ||
} | ||
for (unsigned int i = 0; i < expectedHLTStates_.size(); ++i) { | ||
if (static_cast<unsigned int>(triggerResults.state(i)) != expectedHLTStates_[i]) { | ||
throwWithMessage("state has unexpected value"); | ||
} | ||
if (triggerResults.index(i) != expectedModuleIndexes_[i]) { | ||
throwWithMessage("module index has unexpected value"); | ||
} | ||
} | ||
} | ||
|
||
void TestReadTriggerResults::throwWithMessage(const char* msg) const { | ||
throw cms::Exception("TestFailure") << "TestReadTriggerResults::analyze, " << msg; | ||
} | ||
|
||
void TestReadTriggerResults::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { | ||
edm::ParameterSetDescription desc; | ||
desc.add<std::string>("expectedParameterSetID"); | ||
desc.add<std::vector<std::string>>("expectedNames"); | ||
desc.add<std::vector<unsigned int>>("expectedHLTStates"); | ||
desc.add<std::vector<unsigned int>>("expectedModuleIndexes"); | ||
desc.add<edm::InputTag>("triggerResultsTag"); | ||
descriptions.addDefault(desc); | ||
} | ||
} // namespace edmtest | ||
|
||
using edmtest::TestReadTriggerResults; | ||
DEFINE_FWK_MODULE(TestReadTriggerResults); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#!/bin/sh -ex | ||
|
||
function die { echo $1: status $2 ; exit $2; } | ||
|
||
LOCAL_TEST_DIR=${SCRAM_TEST_PATH} | ||
|
||
cmsRun ${LOCAL_TEST_DIR}/create_triggerresults_test_file_cfg.py || die 'Failure using create_triggerresults_test_file_cfg.py' $? | ||
|
||
file=testTriggerResults.root | ||
|
||
cmsRun ${LOCAL_TEST_DIR}/test_readTriggerResults_cfg.py "$file" || die "Failure using test_readTriggerResults_cfg.py $file" $? | ||
|
||
oldFiles="testTriggerResults_CMSSW_13_0_0.root testTriggerResults_CMSSW_13_1_0_pre3.root" | ||
for file in $oldFiles; do | ||
inputfile=$(edmFileInPath DataFormats/Common/data/$file) || die "Failure edmFileInPath DataFormats/Common/data/$file" $? | ||
cmsRun ${LOCAL_TEST_DIR}/test_readTriggerResults_cfg.py "$inputfile" || die "Failed to read old file $file" $? | ||
done | ||
|
||
exit 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
// -*- C++ -*- | ||
// | ||
// Package: DataFormats/Common | ||
// Class: TestWriteTriggerResults | ||
// | ||
/**\class edmtest::TestWriteTriggerResults | ||
Description: Used as part of tests that ensure the TriggerResults | ||
data format can be persistently written and in a subsequent process | ||
read. First, this is done using the current release version. In | ||
addition, the output file of the write process should be saved | ||
permanently each time its format changes. In unit tests, we read | ||
each of those saved files to verify that all future releases can | ||
read all versions of RAW data formats and Scouting data formats. | ||
*/ | ||
// Original Author: W. David Dagenhart | ||
// Created: 20 April 2023 | ||
|
||
#include "DataFormats/Common/interface/HLTGlobalStatus.h" | ||
#include "DataFormats/Common/interface/TriggerResults.h" | ||
#include "DataFormats/Provenance/interface/ParameterSetID.h" | ||
#include "FWCore/Framework/interface/global/EDProducer.h" | ||
#include "FWCore/Framework/interface/Event.h" | ||
#include "FWCore/Framework/interface/Frameworkfwd.h" | ||
#include "FWCore/Framework/interface/MakerMacros.h" | ||
#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" | ||
#include "FWCore/ParameterSet/interface/ParameterSet.h" | ||
#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" | ||
#include "FWCore/Utilities/interface/EDPutToken.h" | ||
|
||
#include <cassert> | ||
#include <memory> | ||
#include <string> | ||
#include <vector> | ||
|
||
namespace edmtest { | ||
|
||
class TestWriteTriggerResults : public edm::global::EDProducer<> { | ||
public: | ||
TestWriteTriggerResults(edm::ParameterSet const&); | ||
void produce(edm::StreamID, edm::Event&, edm::EventSetup const&) const override; | ||
static void fillDescriptions(edm::ConfigurationDescriptions&); | ||
|
||
private: | ||
std::string parameterSetID_; | ||
std::vector<std::string> names_; | ||
std::vector<unsigned int> hltStates_; | ||
std::vector<unsigned int> moduleIndexes_; | ||
edm::EDPutTokenT<edm::TriggerResults> triggerResultsPutToken_; | ||
}; | ||
|
||
TestWriteTriggerResults::TestWriteTriggerResults(edm::ParameterSet const& iPSet) | ||
: parameterSetID_(iPSet.getParameter<std::string>("parameterSetID")), | ||
names_(iPSet.getParameter<std::vector<std::string>>("names")), | ||
hltStates_(iPSet.getParameter<std::vector<unsigned int>>("hltStates")), | ||
moduleIndexes_(iPSet.getParameter<std::vector<unsigned int>>("moduleIndexes")), | ||
triggerResultsPutToken_(produces()) {} | ||
|
||
void TestWriteTriggerResults::produce(edm::StreamID, edm::Event& iEvent, edm::EventSetup const&) const { | ||
edm::HLTGlobalStatus hltGlobalStatus(hltStates_.size()); | ||
for (unsigned int i = 0; i < hltStates_.size(); ++i) { | ||
assert(i < moduleIndexes_.size()); | ||
hltGlobalStatus[i] = edm::HLTPathStatus(static_cast<edm::hlt::HLTState>(hltStates_[i]), moduleIndexes_[i]); | ||
} | ||
edm::ParameterSetID parameterSetID(parameterSetID_); | ||
std::unique_ptr<edm::TriggerResults> result; | ||
if (names_.empty()) { | ||
// names_ will always be empty except in extremely old data or monte carlo files | ||
result = std::make_unique<edm::TriggerResults>(hltGlobalStatus, parameterSetID); | ||
} else { | ||
// If names is not empty, the ParameterSetID is not set and default constructed | ||
result = std::make_unique<edm::TriggerResults>(hltGlobalStatus, names_); | ||
} | ||
iEvent.put(triggerResultsPutToken_, std::move(result)); | ||
} | ||
|
||
void TestWriteTriggerResults::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { | ||
edm::ParameterSetDescription desc; | ||
desc.add<std::string>("parameterSetID"); | ||
desc.add<std::vector<std::string>>("names"); | ||
desc.add<std::vector<unsigned int>>("hltStates"); | ||
desc.add<std::vector<unsigned int>>("moduleIndexes"); | ||
descriptions.addDefault(desc); | ||
} | ||
} // namespace edmtest | ||
|
||
using edmtest::TestWriteTriggerResults; | ||
DEFINE_FWK_MODULE(TestWriteTriggerResults); |
27 changes: 27 additions & 0 deletions
27
DataFormats/Common/test/create_triggerresults_test_file_cfg.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import FWCore.ParameterSet.Config as cms | ||
|
||
process = cms.Process("PROD") | ||
|
||
process.load("FWCore.MessageService.MessageLogger_cfi") | ||
|
||
process.source = cms.Source("EmptySource") | ||
process.maxEvents.input = 1 | ||
|
||
process.triggerResultsProducer = cms.EDProducer("TestWriteTriggerResults", | ||
# Test values below are meaningless. We just make sure when we read | ||
# we get the same values. | ||
parameterSetID = cms.string('8b99d66b6c3865c75e460791f721202d'), | ||
# names should normally be empty. Only extremely old data or | ||
# has names filled and not empty. If it is not empty, the | ||
# ParameterSetID is ignored and left default constructed. | ||
names = cms.vstring(), | ||
hltStates = cms.vuint32(0, 1, 2, 3), | ||
moduleIndexes = cms.vuint32(11, 21, 31, 41) | ||
) | ||
|
||
process.out = cms.OutputModule("PoolOutputModule", | ||
fileName = cms.untracked.string('testTriggerResults.root') | ||
) | ||
|
||
process.path = cms.Path(process.triggerResultsProducer) | ||
process.endPath = cms.EndPath(process.out) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import FWCore.ParameterSet.Config as cms | ||
import sys | ||
|
||
process = cms.Process("READ") | ||
|
||
process.source = cms.Source("PoolSource", fileNames = cms.untracked.vstring("file:"+sys.argv[2])) | ||
process.maxEvents.input = 1 | ||
|
||
process.testReadTriggerResults = cms.EDAnalyzer("TestReadTriggerResults", | ||
triggerResultsTag = cms.InputTag("triggerResultsProducer", "", "PROD"), | ||
expectedParameterSetID = cms.string('8b99d66b6c3865c75e460791f721202d'), | ||
expectedNames = cms.vstring(), | ||
expectedHLTStates = cms.vuint32(0, 1, 2, 3), | ||
expectedModuleIndexes = cms.vuint32(11, 21, 31, 41) | ||
) | ||
|
||
process.out = cms.OutputModule("PoolOutputModule", | ||
fileName = cms.untracked.string('testTriggerResults2.root') | ||
) | ||
|
||
process.path = cms.Path(process.testReadTriggerResults) | ||
|
||
process.endPath = cms.EndPath(process.out) |