File indexing completed on 2025-01-31 02:19:32
0001
0002 #include "DataFormats/Common/interface/Handle.h"
0003 #include "DataFormats/Provenance/interface/BranchID.h"
0004 #include "DataFormats/Provenance/interface/Parentage.h"
0005 #include "DataFormats/Provenance/interface/ProductProvenance.h"
0006 #include "DataFormats/Provenance/interface/ProductProvenanceLookup.h"
0007 #include "DataFormats/Provenance/interface/Provenance.h"
0008 #include "DataFormats/TestObjects/interface/ToyProducts.h"
0009 #include "FWCore/Framework/interface/global/EDAnalyzer.h"
0010 #include "FWCore/Framework/interface/Event.h"
0011 #include "FWCore/Framework/interface/MakerMacros.h"
0012 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0013 #include "FWCore/ServiceRegistry/interface/Service.h"
0014 #include "FWCore/Utilities/interface/InputTag.h"
0015 #include "FWCore/Utilities/interface/EDGetToken.h"
0016
0017 #include <iostream>
0018 #include <map>
0019 #include <set>
0020 #include <string>
0021 #include <vector>
0022
0023 namespace {
0024 void getAncestors(edm::Event const& e, edm::BranchID const& branchID, std::set<edm::BranchID>& ancestors) {
0025 const edm::Provenance& prov = e.getProvenance(branchID);
0026 if (prov.productProvenance()) {
0027 for (auto const& parent : prov.productProvenance()->parentage().parents()) {
0028 ancestors.insert(parent);
0029 getAncestors(e, parent, ancestors);
0030 }
0031 }
0032 }
0033
0034
0035
0036
0037
0038
0039 void getAncestorsFromRetriever(edm::ProductProvenanceLookup const* retriever,
0040 edm::BranchID const& branchID,
0041 std::set<edm::BranchID>& ancestors) {
0042 edm::ProductProvenance const* productProvenance = retriever->branchIDToProvenance(branchID);
0043 if (productProvenance) {
0044 for (auto const& parent : productProvenance->parentage().parents()) {
0045 ancestors.insert(parent);
0046 getAncestorsFromRetriever(retriever, parent, ancestors);
0047 }
0048 }
0049 }
0050 }
0051
0052 namespace edmtest {
0053
0054 class TestParentage : public edm::global::EDAnalyzer<> {
0055 public:
0056 explicit TestParentage(edm::ParameterSet const& pset);
0057 ~TestParentage() override = default;
0058
0059 void analyze(edm::StreamID, edm::Event const& e, edm::EventSetup const& es) const override;
0060
0061 static void fillDescriptions(edm::ConfigurationDescriptions& iDesc);
0062
0063 private:
0064 edm::EDGetTokenT<IntProduct> token_;
0065 std::vector<std::string> expectedAncestors_;
0066 bool callGetProvenance_;
0067 };
0068
0069 TestParentage::TestParentage(edm::ParameterSet const& pset)
0070 : token_(consumes(pset.getParameter<edm::InputTag>("inputTag"))),
0071 expectedAncestors_(pset.getParameter<std::vector<std::string> >("expectedAncestors")),
0072 callGetProvenance_(pset.getUntrackedParameter<bool>("callGetProvenance", true)) {}
0073
0074 void TestParentage::fillDescriptions(edm::ConfigurationDescriptions& iDesc) {
0075 edm::ParameterSetDescription ps;
0076 ps.add<edm::InputTag>("inputTag");
0077 ps.add<std::vector<std::string> >("expectedAncestors")
0078 ->setComment(
0079 "Module labels for data products directly/indirectly obtained to make data product retrieved using "
0080 "'inputTag'.");
0081 ps.addUntracked<bool>("callGetProvenance", true)
0082 ->setComment("Use Event::getProvenance to get ancestor provenance.");
0083
0084 iDesc.addDefault(ps);
0085 }
0086
0087 void TestParentage::analyze(edm::StreamID, edm::Event const& e, edm::EventSetup const&) const {
0088 edm::Handle<IntProduct> h = e.getHandle(token_);
0089 *h;
0090 edm::Provenance const* prov = h.provenance();
0091
0092 if (not prov) {
0093 throw cms::Exception("MissingProvenance") << "Failed to get provenance for 'inputTag'";
0094 }
0095 if (prov->originalBranchID() != prov->productDescription().originalBranchID()) {
0096 throw cms::Exception("InconsistentBranchID")
0097 << " test of Provenance::originalBranchID function failed. Expected "
0098 << prov->productDescription().originalBranchID() << " but see " << prov->originalBranchID();
0099 }
0100
0101 std::set<std::string> expectedAncestors(expectedAncestors_.begin(), expectedAncestors_.end());
0102
0103
0104
0105
0106 auto toException = [](auto& ex, auto const& ancestors) {
0107 for (auto const& a : ancestors) {
0108 ex << a << ", ";
0109 }
0110 };
0111
0112 if (callGetProvenance_) {
0113 std::set<edm::BranchID> ancestors;
0114 getAncestors(e, prov->branchID(), ancestors);
0115
0116 std::set<std::string> ancestorLabels;
0117 for (edm::BranchID const& ancestor : ancestors) {
0118 try {
0119 ancestorLabels.insert(e.getStableProvenance(ancestor).moduleLabel());
0120 } catch (cms::Exception& iEx) {
0121 edm::LogSystem("MissingProvenance") << "the provenance for BranchID " << ancestor << " is missing\n"
0122 << iEx.what();
0123 ancestorLabels.insert("");
0124 }
0125 }
0126 if (ancestorLabels != expectedAncestors) {
0127 cms::Exception ex("WrongAncestors");
0128 ex << "ancestors from Event::getProvenance\n";
0129 toException(ex, ancestorLabels);
0130 ex << "\n do not match expected ancestors\n";
0131 toException(ex, expectedAncestors);
0132 throw ex;
0133 }
0134 }
0135
0136 auto const* retriever = prov->store();
0137 std::set<edm::BranchID> ancestorsFromRetriever;
0138 getAncestorsFromRetriever(retriever, prov->originalBranchID(), ancestorsFromRetriever);
0139
0140 std::set<std::string> ancestorLabels2;
0141 for (edm::BranchID const& ancestor : ancestorsFromRetriever) {
0142 try {
0143 ancestorLabels2.insert(e.getStableProvenance(ancestor).moduleLabel());
0144 } catch (cms::Exception& iEx) {
0145 edm::LogSystem("MissingProvenance")
0146 << "the provenance from Retriever for BranchID " << ancestor << " is missing\n"
0147 << iEx.what();
0148 ancestorLabels2.insert("");
0149 }
0150 }
0151 if (ancestorLabels2 != expectedAncestors) {
0152 cms::Exception ex("WrongAncestors");
0153 ex << "ancestors from ParentageRetriever\n";
0154 toException(ex, ancestorLabels2);
0155 ex << "\n do not match expected ancestors\n";
0156 toException(ex, expectedAncestors);
0157 throw ex;
0158 }
0159 }
0160 }
0161
0162 using edmtest::TestParentage;
0163 DEFINE_FWK_MODULE(TestParentage);