Back to home page

Project CMSSW displayed by LXR

 
 

    


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   // Does the same thing as the previous function in a different
0035   // way. The previous function goes through the links in the
0036   // ProductsResolver. Both should give the same answer.
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 }  // namespace
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 }  // namespace edmtest
0156 
0157 using edmtest::TestParentage;
0158 DEFINE_FWK_MODULE(TestParentage);