diff --git a/DataFormats/FEDRawData/README.md b/DataFormats/FEDRawData/README.md new file mode 100644 index 0000000000000..0cc3c76428f37 --- /dev/null +++ b/DataFormats/FEDRawData/README.md @@ -0,0 +1,10 @@ +# DataFormats/FEDRawData + +## `FEDRawDataCollection` + +The class `FEDRawDataCollection` 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 `TestFEDRawDataCollectionFormat` unit test, which makes use of the `TestReadFEDRawDataCollection` analyzer and the `TestWriteFEDRawDataCollection` producer. The unit test checks that the object can be read properly from + +* a file written by the same release +* files written by (some) earlier releases + +If the persistent format of class `FEDRawDataCollection` gets changed in the future, please adjust the `TestReadFEDRawDataCollection` and `TestWriteFEDRawDataCollection` modules accordingly. It is important that every member container has some content in this test. Please also add a new file to the [https://github.com/cms-data/DataFormats-FEDRawData/](https://github.com/cms-data/DataFormats-FEDRawData/) repository, and update the `TestFEDRawDataCollectionFormat` unit test to read the newly created file. The file name should contain the release or pre-release with which it was written. diff --git a/DataFormats/FEDRawData/test/BuildFile.xml b/DataFormats/FEDRawData/test/BuildFile.xml index c69c5fdc725d3..28fbaa29c7152 100644 --- a/DataFormats/FEDRawData/test/BuildFile.xml +++ b/DataFormats/FEDRawData/test/BuildFile.xml @@ -1,4 +1,14 @@ + + + + + + + + + + diff --git a/DataFormats/FEDRawData/test/TestFEDRawDataCollectionFormat.sh b/DataFormats/FEDRawData/test/TestFEDRawDataCollectionFormat.sh new file mode 100755 index 0000000000000..ba15b3bb6619a --- /dev/null +++ b/DataFormats/FEDRawData/test/TestFEDRawDataCollectionFormat.sh @@ -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_FEDRawDataCollection_test_file_cfg.py || die 'Failure using create_FEDRawDataCollection_test_file_cfg.py' $? + +file=testFEDRawDataCollection.root + +cmsRun ${LOCAL_TEST_DIR}/test_readFEDRawDataCollection_cfg.py "$file" || die "Failure using test_readFEDRawDataCollection_cfg.py $file" $? + +oldFiles="testFEDRawDataCollection_CMSSW_13_0_0.root testFEDRawDataCollection_CMSSW_13_1_0_pre3.root" +for file in $oldFiles; do + inputfile=$(edmFileInPath DataFormats/FEDRawData/data/$file) || die "Failure edmFileInPath DataFormats/FEDRawData/data/$file" $? + cmsRun ${LOCAL_TEST_DIR}/test_readFEDRawDataCollection_cfg.py "$inputfile" || die "Failed to read old file $file" $? +done + +exit 0 diff --git a/DataFormats/FEDRawData/test/TestReadFEDRawDataCollection.cc b/DataFormats/FEDRawData/test/TestReadFEDRawDataCollection.cc new file mode 100644 index 0000000000000..788a5153dd51a --- /dev/null +++ b/DataFormats/FEDRawData/test/TestReadFEDRawDataCollection.cc @@ -0,0 +1,95 @@ +// -*- C++ -*- +// +// Package: DataFormats/FEDRawData +// Class: TestReadFEDRawDataCollection +// +/**\class edmtest::TestReadFEDRawDataCollection + Description: Used as part of tests that ensure the FEDRawDataCollection + data format can be persistently written and in a subsequent process + read. First, this is done using the current release version for writing + and reading. In addition, the output file of the write process should + be saved permanently each time the FEDRawDataCollection persistent data + format changes. In unit tests, we read each of those saved files to verify + that the current releases can read older versions of the data format. +*/ +// Original Author: W. David Dagenhart +// Created: 1 May 2023 + +#include "DataFormats/FEDRawData/interface/FEDRawData.h" +#include "DataFormats/FEDRawData/interface/FEDRawDataCollection.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/global/EDAnalyzer.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 "FWCore/Utilities/interface/StreamID.h" + +#include + +namespace edmtest { + + class TestReadFEDRawDataCollection : public edm::global::EDAnalyzer<> { + public: + TestReadFEDRawDataCollection(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: + // Two FEDRawData elements should be enough to verify we can read + // and write the whole collection. I arbitrarily chose elements + // 0 and 3 of the Collection. Values are meaningless, we just + // verify what we read matches what we wrote. For purposes of + // this test that is enough. + std::vector expectedFEDData0_; + std::vector expectedFEDData3_; + edm::EDGetTokenT fedRawDataCollectionToken_; + }; + + TestReadFEDRawDataCollection::TestReadFEDRawDataCollection(edm::ParameterSet const& iPSet) + : expectedFEDData0_(iPSet.getParameter>("expectedFEDData0")), + expectedFEDData3_(iPSet.getParameter>("expectedFEDData3")), + fedRawDataCollectionToken_(consumes(iPSet.getParameter("fedRawDataCollectionTag"))) {} + + void TestReadFEDRawDataCollection::analyze(edm::StreamID, edm::Event const& iEvent, edm::EventSetup const&) const { + auto const& fedRawDataCollection = iEvent.get(fedRawDataCollectionToken_); + auto const& fedData0 = fedRawDataCollection.FEDData(0); + if (fedData0.size() != expectedFEDData0_.size()) { + throwWithMessage("fedData0 does not have expected size"); + } + for (unsigned int i = 0; i < fedData0.size(); ++i) { + if (fedData0.data()[i] != expectedFEDData0_[i]) { + throwWithMessage("fedData0 does not have expected contents"); + } + } + auto const& fedData3 = fedRawDataCollection.FEDData(3); + if (fedData3.size() != expectedFEDData3_.size()) { + throwWithMessage("fedData3 does not have expected size"); + } + for (unsigned int i = 0; i < fedData3.size(); ++i) { + if (fedData3.data()[i] != expectedFEDData3_[i]) { + throwWithMessage("fedData3 does not have expected contents"); + } + } + } + + void TestReadFEDRawDataCollection::throwWithMessage(const char* msg) const { + throw cms::Exception("TestFailure") << "TestReadFEDRawDataCollection::analyze, " << msg; + } + + void TestReadFEDRawDataCollection::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + desc.add>("expectedFEDData0"); + desc.add>("expectedFEDData3"); + desc.add("fedRawDataCollectionTag"); + descriptions.addDefault(desc); + } +} // namespace edmtest + +using edmtest::TestReadFEDRawDataCollection; +DEFINE_FWK_MODULE(TestReadFEDRawDataCollection); diff --git a/DataFormats/FEDRawData/test/TestWriteFEDRawDataCollection.cc b/DataFormats/FEDRawData/test/TestWriteFEDRawDataCollection.cc new file mode 100644 index 0000000000000..ff846686598f9 --- /dev/null +++ b/DataFormats/FEDRawData/test/TestWriteFEDRawDataCollection.cc @@ -0,0 +1,80 @@ +// -*- C++ -*- +// +// Package: DataFormats/FEDRawData +// Class: TestWriteFEDRawDataCollection +// +/**\class edmtest::TestWriteFEDRawDataCollection + Description: Used as part of tests that ensure the FEDRawDataCollection + data format can be persistently written and in a subsequent process + read. First, this is done using the current release version for writing + and reading. In addition, the output file of the write process should + be saved permanently each time the FEDRawDataCollection persistent data + format changes. In unit tests, we read each of those saved files to verify + that the current releases can read older versions of the data format. +*/ +// Original Author: W. David Dagenhart +// Created: 1 May 2023 + +#include "DataFormats/FEDRawData/interface/FEDRawData.h" +#include "DataFormats/FEDRawData/interface/FEDRawDataCollection.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/global/EDProducer.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 "FWCore/Utilities/interface/StreamID.h" + +#include +#include +#include + +namespace edmtest { + + class TestWriteFEDRawDataCollection : public edm::global::EDProducer<> { + public: + TestWriteFEDRawDataCollection(edm::ParameterSet const&); + void produce(edm::StreamID, edm::Event&, edm::EventSetup const&) const override; + static void fillDescriptions(edm::ConfigurationDescriptions&); + + private: + std::vector fedData0_; + std::vector fedData3_; + edm::EDPutTokenT fedRawDataCollectionPutToken_; + }; + + TestWriteFEDRawDataCollection::TestWriteFEDRawDataCollection(edm::ParameterSet const& iPSet) + : fedData0_(iPSet.getParameter>("FEDData0")), + fedData3_(iPSet.getParameter>("FEDData3")), + fedRawDataCollectionPutToken_(produces()) {} + + void TestWriteFEDRawDataCollection::produce(edm::StreamID, edm::Event& iEvent, edm::EventSetup const&) const { + auto fedRawDataCollection = std::make_unique(); + FEDRawData& fedData0 = fedRawDataCollection->FEDData(0); + FEDRawData& fedData3 = fedRawDataCollection->FEDData(3); + + fedData0.resize(fedData0_.size()); + unsigned char* dataPtr0 = fedData0.data(); + for (unsigned int i = 0; i < fedData0_.size(); ++i) { + dataPtr0[i] = fedData0_[i]; + } + fedData3.resize(fedData3_.size()); + unsigned char* dataPtr3 = fedData3.data(); + for (unsigned int i = 0; i < fedData3_.size(); ++i) { + dataPtr3[i] = fedData3_[i]; + } + iEvent.put(fedRawDataCollectionPutToken_, std::move(fedRawDataCollection)); + } + + void TestWriteFEDRawDataCollection::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + desc.add>("FEDData0"); + desc.add>("FEDData3"); + descriptions.addDefault(desc); + } +} // namespace edmtest + +using edmtest::TestWriteFEDRawDataCollection; +DEFINE_FWK_MODULE(TestWriteFEDRawDataCollection); diff --git a/DataFormats/FEDRawData/test/create_FEDRawDataCollection_test_file_cfg.py b/DataFormats/FEDRawData/test/create_FEDRawDataCollection_test_file_cfg.py new file mode 100644 index 0000000000000..02d2d7bfd3638 --- /dev/null +++ b/DataFormats/FEDRawData/test/create_FEDRawDataCollection_test_file_cfg.py @@ -0,0 +1,22 @@ +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.fedRawDataCollectionProducer = cms.EDProducer("TestWriteFEDRawDataCollection", + # Test values below are meaningless. We just make sure when we read + # we get the same values. + FEDData0 = cms.vuint32(0, 1, 2, 3, 4, 5, 6, 7), + FEDData3 = cms.vuint32(100, 101, 102, 103, 104, 105, 106, 107) +) + +process.out = cms.OutputModule("PoolOutputModule", + fileName = cms.untracked.string('testFEDRawDataCollection.root') +) + +process.path = cms.Path(process.fedRawDataCollectionProducer) +process.endPath = cms.EndPath(process.out) diff --git a/DataFormats/FEDRawData/test/test_readFEDRawDataCollection_cfg.py b/DataFormats/FEDRawData/test/test_readFEDRawDataCollection_cfg.py new file mode 100644 index 0000000000000..67389987c3424 --- /dev/null +++ b/DataFormats/FEDRawData/test/test_readFEDRawDataCollection_cfg.py @@ -0,0 +1,21 @@ +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.testReadFEDRawDataCollection = cms.EDAnalyzer("TestReadFEDRawDataCollection", + fedRawDataCollectionTag = cms.InputTag("fedRawDataCollectionProducer", "", "PROD"), + expectedFEDData0 = cms.vuint32(0, 1, 2, 3, 4, 5, 6, 7), + expectedFEDData3 = cms.vuint32(100, 101, 102, 103, 104, 105, 106, 107) +) + +process.out = cms.OutputModule("PoolOutputModule", + fileName = cms.untracked.string('testFEDRawDataCollection2.root') +) + +process.path = cms.Path(process.testReadFEDRawDataCollection) + +process.endPath = cms.EndPath(process.out)