File indexing completed on 2025-04-22 06:27:22
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 void getAncestorsFromRetriever(edm::ProductProvenanceLookup const* retriever,
0038 edm::BranchID const& branchID,
0039 std::set<edm::BranchID>& ancestors) {
0040 edm::ProductProvenance const* productProvenance = retriever->branchIDToProvenance(branchID);
0041 if (productProvenance) {
0042 for (auto const& parent : productProvenance->parentage().parents()) {
0043 ancestors.insert(parent);
0044 getAncestorsFromRetriever(retriever, parent, ancestors);
0045 }
0046 }
0047 }
0048 }
0049
0050 namespace edmtest {
0051
0052 class TestParentage : public edm::global::EDAnalyzer<> {
0053 public:
0054 explicit TestParentage(edm::ParameterSet const& pset);
0055 ~TestParentage() override = default;
0056
0057 void analyze(edm::StreamID, edm::Event const& e, edm::EventSetup const& es) const override;
0058
0059 static void fillDescriptions(edm::ConfigurationDescriptions& iDesc);
0060
0061 private:
0062 edm::EDGetTokenT<IntProduct> token_;
0063 std::vector<std::string> expectedAncestors_;
0064 bool callGetProvenance_;
0065 };
0066
0067 TestParentage::TestParentage(edm::ParameterSet const& pset)
0068 : token_(consumes(pset.getParameter<edm::InputTag>("inputTag"))),
0069 expectedAncestors_(pset.getParameter<std::vector<std::string> >("expectedAncestors")),
0070 callGetProvenance_(pset.getUntrackedParameter<bool>("callGetProvenance", true)) {}
0071
0072 void TestParentage::fillDescriptions(edm::ConfigurationDescriptions& iDesc) {
0073 edm::ParameterSetDescription ps;
0074 ps.add<edm::InputTag>("inputTag");
0075 ps.add<std::vector<std::string> >("expectedAncestors")
0076 ->setComment(
0077 "Module labels for data products directly/indirectly obtained to make data product retrieved using "
0078 "'inputTag'.");
0079 ps.addUntracked<bool>("callGetProvenance", true)
0080 ->setComment("Use Event::getProvenance to get ancestor provenance.");
0081
0082 iDesc.addDefault(ps);
0083 }
0084
0085 void TestParentage::analyze(edm::StreamID, edm::Event const& e, edm::EventSetup const&) const {
0086 edm::Handle<IntProduct> h = e.getHandle(token_);
0087 *h;
0088 edm::Provenance const* prov = h.provenance();
0089
0090 if (not prov) {
0091 throw cms::Exception("MissingProvenance") << "Failed to get provenance for 'inputTag'";
0092 }
0093 if (prov->originalBranchID() != prov->productDescription().originalBranchID()) {
0094 throw cms::Exception("InconsistentBranchID")
0095 << " test of Provenance::originalBranchID function failed. Expected "
0096 << prov->productDescription().originalBranchID() << " but see " << prov->originalBranchID();
0097 }
0098
0099 std::set<std::string> expectedAncestors(expectedAncestors_.begin(), expectedAncestors_.end());
0100
0101 auto toException = [](auto& ex, auto const& ancestors) {
0102 for (auto const& a : ancestors) {
0103 ex << a << ", ";
0104 }
0105 };
0106
0107 if (callGetProvenance_) {
0108 std::set<edm::BranchID> ancestors;
0109 getAncestors(e, prov->branchID(), ancestors);
0110
0111 std::set<std::string> ancestorLabels;
0112 for (edm::BranchID const& ancestor : ancestors) {
0113 try {
0114 ancestorLabels.insert(e.getStableProvenance(ancestor).moduleLabel());
0115 } catch (cms::Exception& iEx) {
0116 edm::LogSystem("MissingProvenance") << "the provenance for BranchID " << ancestor << " is missing\n"
0117 << iEx.what();
0118 ancestorLabels.insert("");
0119 }
0120 }
0121 if (ancestorLabels != expectedAncestors) {
0122 cms::Exception ex("WrongAncestors");
0123 ex << "ancestors from Event::getProvenance\n";
0124 toException(ex, ancestorLabels);
0125 ex << "\n do not match expected ancestors\n";
0126 toException(ex, expectedAncestors);
0127 throw ex;
0128 }
0129 }
0130
0131 auto const* retriever = prov->store();
0132 std::set<edm::BranchID> ancestorsFromRetriever;
0133 getAncestorsFromRetriever(retriever, prov->originalBranchID(), ancestorsFromRetriever);
0134
0135 std::set<std::string> ancestorLabels2;
0136 for (edm::BranchID const& ancestor : ancestorsFromRetriever) {
0137 try {
0138 ancestorLabels2.insert(e.getStableProvenance(ancestor).moduleLabel());
0139 } catch (cms::Exception& iEx) {
0140 edm::LogSystem("MissingProvenance")
0141 << "the provenance from Retriever for BranchID " << ancestor << " is missing\n"
0142 << iEx.what();
0143 ancestorLabels2.insert("");
0144 }
0145 }
0146 if (ancestorLabels2 != expectedAncestors) {
0147 cms::Exception ex("WrongAncestors");
0148 ex << "ancestors from ParentageRetriever\n";
0149 toException(ex, ancestorLabels2);
0150 ex << "\n do not match expected ancestors\n";
0151 toException(ex, expectedAncestors);
0152 throw ex;
0153 }
0154 }
0155 }
0156
0157 using edmtest::TestParentage;
0158 DEFINE_FWK_MODULE(TestParentage);