Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-06-07 08:42:09

0001 
0002 #include "JANA/Components/JDatabundle.h"
0003 #include "JANA/JApplicationFwd.h"
0004 #include "PodioDatamodel/ExampleHit.h"
0005 #include <catch.hpp>
0006 
0007 #include <memory>
0008 #include <type_traits>
0009 #include <JANA/JEvent.h>
0010 #include <JANA/JFactoryGenerator.h>
0011 #include <JANA/JMultifactory.h>
0012 #include <JANA/Components/JOmniFactory.h>
0013 #include <JANA/Components/JOmniFactoryGeneratorT.h>
0014 #include <PodioDatamodel/ExampleHitCollection.h>
0015 #include <PodioDatamodel/ExampleClusterCollection.h>
0016 #include <podio/podioVersion.h>
0017 
0018 #if podio_VERSION >= PODIO_VERSION(1,2,0)
0019 #include <podio/LinkCollection.h>
0020 #endif
0021 
0022 namespace podiotests {
0023 
0024 
0025 TEST_CASE("PodioTestsInsertAndRetrieve") {
0026     ExampleClusterCollection clusters_to_insert;
0027     clusters_to_insert.push_back(MutableExampleCluster(16.0));
0028     clusters_to_insert.push_back(MutableExampleCluster(128.0));
0029 
0030     auto event = std::make_shared<JEvent>();
0031     event->InsertCollection<ExampleCluster>(std::move(clusters_to_insert), "clusters");
0032 
0033     SECTION("Retrieve using JEvent::GetCollection()") {
0034         auto* collection_retrieved = event->GetCollection<ExampleCluster>("clusters");
0035         REQUIRE(collection_retrieved->size() == 2);
0036         REQUIRE((*collection_retrieved)[0].energy() == 16.0);
0037     }
0038 
0039     SECTION("Retrieve using JEvent::GetCollectionBase()") {
0040         auto* collection_retrieved_untyped = event->GetCollectionBase("clusters");
0041         REQUIRE(collection_retrieved_untyped->size() == 2);
0042         auto* collection_retrieved = dynamic_cast<const ExampleClusterCollection*>(collection_retrieved_untyped);
0043         REQUIRE(collection_retrieved != nullptr);
0044         REQUIRE((*collection_retrieved)[0].energy() == 16.0);
0045     }
0046 
0047     SECTION("Retrieve directly from podio::Frame") {
0048         auto frame = event->GetSingle<podio::Frame>();
0049         auto* collection_retrieved = dynamic_cast<const ExampleClusterCollection*>(frame->get("clusters"));
0050         REQUIRE(collection_retrieved->size() == 2);
0051         REQUIRE((*collection_retrieved)[0].energy() == 16.0);
0052     }
0053 
0054 }
0055 
0056 template <typename, typename=void>
0057 struct is_podio : std::false_type {};
0058 
0059 template <typename T>
0060 struct is_podio<T, std::void_t<typename T::collection_type>> : std::true_type {};
0061 
0062 template <typename T>
0063 static constexpr bool is_podio_v = is_podio<T>::value;
0064 
0065 struct FakeMultifactory {
0066 
0067     template <typename T, typename std::enable_if_t<is_podio_v<T>>* = nullptr>
0068     bool DeclareOutput(std::string /*tag*/) {
0069         return true;
0070     }
0071 
0072     template <typename T, typename std::enable_if_t<!is_podio_v<T>>* = nullptr>
0073     bool DeclareOutput(std::string /*tag*/) {
0074         return false;
0075     }
0076 };
0077 
0078 TEST_CASE("SFINAE for JMultifactory::SetData") {
0079     FakeMultifactory sut;
0080     REQUIRE(sut.DeclareOutput<int>("asdf") == false);
0081     REQUIRE(sut.DeclareOutput<ExampleCluster>("asdf") == true);
0082 }
0083 
0084 
0085 TEST_CASE("PODIO 'subset' collections handled correctly (not involving factories yet") {
0086     auto event = std::make_shared<JEvent>();
0087 
0088     auto a1 = MutableExampleCluster(22.2);
0089     auto a2 = MutableExampleCluster(4.0);
0090     ExampleClusterCollection clusters_to_insert;
0091     clusters_to_insert.push_back(a1);
0092     clusters_to_insert.push_back(a2);
0093     event->InsertCollection<ExampleCluster>(std::move(clusters_to_insert), "original_clusters");
0094 
0095     auto* retrieved_clusters = event->GetCollection<ExampleCluster>("original_clusters");
0096     auto b = (*retrieved_clusters)[1];
0097     REQUIRE(b.energy() == 4.0);
0098 
0099     ExampleClusterCollection subset_clusters;
0100     subset_clusters.setSubsetCollection(true);
0101     subset_clusters.push_back(b);
0102     event->InsertCollection<ExampleCluster>(std::move(subset_clusters), "subset_clusters");
0103 
0104 
0105     // Retrieve via event->GetCollection
0106     const ExampleClusterCollection* retrieved_subset_clusters = event->GetCollection<ExampleCluster>("subset_clusters");
0107     const ExampleCluster& c = (*retrieved_subset_clusters)[0];
0108     REQUIRE(c.energy() == 4.0);
0109     REQUIRE(c.id() == b.id());
0110 
0111 }
0112 } // namespace podiotests
0113 
0114 
0115 #if podio_VERSION >= PODIO_VERSION(1,2,0)
0116 
0117 using ClusterClusterLink = podio::LinkCollection<ExampleCluster, ExampleCluster>::value_type;
0118 struct MyOmniFac: jana::components::JOmniFactory<MyOmniFac> {
0119 
0120     PodioInput<ExampleCluster> m_clusters_in {this};
0121     PodioInput<ClusterClusterLink> m_links_in {this};  // Just to test that the Input machinery is OK
0122     PodioOutput<ClusterClusterLink> m_links_out {this};
0123 
0124     void Configure() {};
0125 
0126     void ChangeRun(int32_t) {}
0127 
0128     void Execute(int32_t, int32_t) {
0129         auto link = m_links_out()->create();
0130         link.setFrom(m_clusters_in()->at(1));
0131         link.setTo(m_clusters_in()->at(0));
0132     }
0133 };
0134 
0135 TEST_CASE("PodioLink_Test") {
0136     JApplication app;
0137     app.Add(new JOmniFactoryGeneratorT<MyOmniFac>("blah", {"clusters", "simple"}, {"complex"}));
0138     auto event = std::make_shared<JEvent>(&app);
0139     ExampleClusterCollection clusters;
0140     auto c1 = clusters.create();
0141     c1.energy(22);
0142     auto c2 = clusters.create();
0143     c2.energy(33);
0144 
0145     event->InsertCollection<ExampleCluster>(std::move(clusters), "clusters");
0146     event->InsertCollection<ClusterClusterLink>(ClusterClusterLink::collection_type(), "simple");
0147 
0148     auto coll = event->GetCollection<ClusterClusterLink>("complex");
0149     REQUIRE(coll->size() == 1);
0150     REQUIRE(coll->at(0).getFrom().energy() == 33);
0151     REQUIRE(coll->at(0).getTo().energy() == 22);
0152 }
0153 #endif
0154 
0155 
0156 namespace jana2::tests::podio_cleardata {
0157 
0158 struct MyFac: jana::components::JOmniFactory<MyFac> {
0159 
0160     PodioInput<ExampleHit> m_hits_in {this};
0161     PodioOutput<ExampleCluster> m_clusters_out {this};
0162 
0163     MyFac() { SetTypeName("MyFac");}
0164     void Configure() {};
0165     void ChangeRun(int32_t) {}
0166     void Execute(int32_t, int32_t) {
0167         auto cluster = m_clusters_out()->create();
0168         for (auto hit : *m_hits_in()) {
0169             cluster.addHits(hit);
0170         }
0171     }
0172 };
0173 
0174 TEST_CASE("PodioClearData_Test") {
0175     JApplication app;
0176     app.Add(new JOmniFactoryGeneratorT<MyFac>("blah", {"hits"}, {"clusters"}));
0177     auto event = std::make_shared<JEvent>(&app);
0178 
0179     SECTION("InsertCollection") {
0180         ExampleHitCollection hits;
0181         auto h1 = hits.create();
0182         h1.cellID(22);
0183 
0184         event->InsertCollection<ExampleHit>(std::move(hits), "hits");
0185         auto clusters = event->GetCollection<ExampleCluster>("clusters");
0186         REQUIRE(clusters->size() == 1);
0187         REQUIRE(clusters->at(0).Hits_size() == 1);
0188         REQUIRE(clusters->at(0).Hits().at(0).cellID() == 22);
0189 
0190         event->Clear(true);
0191 
0192         ExampleHitCollection hits2;
0193         auto h2 = hits2.create();
0194         h2.cellID(3);
0195         auto h3 = hits2.create();
0196         h3.cellID(99);
0197         event->InsertCollection<ExampleHit>(std::move(hits2), "hits");
0198         auto clusters2 = event->GetCollection<ExampleCluster>("clusters");
0199         REQUIRE(clusters2->size() == 1);
0200         REQUIRE(clusters2->at(0).Hits_size() == 2);
0201         REQUIRE(clusters2->at(0).Hits().at(0).cellID() == 3);
0202         REQUIRE(clusters2->at(0).Hits().at(1).cellID() == 99);
0203     }
0204 
0205     SECTION("InsertCollectionAlreadyInFrame") {
0206         ExampleHitCollection hits;
0207         auto h1 = hits.create();
0208         h1.cellID(22);
0209         podio::Frame* frame1 = new podio::Frame;
0210         frame1->put(std::move(hits), "hits");
0211         auto const_hits = frame1->get("hits");
0212         event->Insert(frame1, "");
0213         event->InsertCollectionAlreadyInFrame<ExampleHit>(const_hits, "hits");
0214 
0215         auto clusters = event->GetCollection<ExampleCluster>("clusters");
0216 
0217         REQUIRE(clusters->size() == 1);
0218         REQUIRE(clusters->at(0).Hits_size() == 1);
0219         REQUIRE(clusters->at(0).Hits().at(0).cellID() == 22);
0220 
0221         event->Clear(true);
0222 
0223         ExampleHitCollection hits2;
0224         auto h2 = hits2.create();
0225         h2.cellID(3);
0226         auto h3 = hits2.create();
0227         h3.cellID(99);
0228 
0229         podio::Frame* frame2 = new podio::Frame;
0230         frame2->put(std::move(hits2), "hits");
0231         auto const_hits2 = frame2->get("hits");
0232         event->Insert(frame2, "");
0233         event->InsertCollectionAlreadyInFrame<ExampleHit>(const_hits2, "hits");
0234 
0235         auto clusters2 = event->GetCollection<ExampleCluster>("clusters");
0236 
0237         REQUIRE(clusters2->size() == 1);
0238         REQUIRE(clusters2->at(0).Hits_size() == 2);
0239         REQUIRE(clusters2->at(0).Hits().at(0).cellID() == 3);
0240         REQUIRE(clusters2->at(0).Hits().at(1).cellID() == 99);
0241     }
0242 
0243 
0244 
0245 } // TEST_CASE
0246 } // namespace jana2::tests::podio_cleardata
0247 
0248 namespace jana2::tests::podio_multifactory {
0249 
0250 struct MyMultiFac: JMultifactory {
0251 
0252 
0253     MyMultiFac() { 
0254         SetTypeName("MyMultiFac");
0255         DeclarePodioOutput<ExampleCluster>("clusters");
0256         DeclarePodioOutput<ExampleCluster>("other_clusters");
0257     }
0258     void Process(const std::shared_ptr<const JEvent>& event) override {
0259         auto hits = event->GetCollection<ExampleHit>("hits");
0260         ExampleClusterCollection clusters;
0261         auto cluster = clusters.create();
0262         for (auto hit : *hits) {
0263             cluster.addHits(hit);
0264         }
0265         SetCollection<ExampleCluster>("clusters", std::move(clusters));
0266 
0267         ExampleClusterCollection clusters2;
0268         auto cluster2 = clusters2.create();
0269         for (auto hit : *hits) {
0270             cluster2.addHits(hit);
0271         }
0272         SetCollection<ExampleCluster>("other_clusters", std::move(clusters2));
0273     }
0274 };
0275 
0276 TEST_CASE("PodioMultifactoryClearData_Test") {
0277     JApplication app;
0278     app.Add(new JFactoryGeneratorT<MyMultiFac>());
0279     auto event = std::make_shared<JEvent>(&app);
0280 
0281     SECTION("InsertCollection") {
0282         ExampleHitCollection hits;
0283         auto h1 = hits.create();
0284         h1.cellID(22);
0285 
0286         event->InsertCollection<ExampleHit>(std::move(hits), "hits");
0287         auto clusters = event->GetCollection<ExampleCluster>("clusters");
0288         REQUIRE(clusters->size() == 1);
0289         REQUIRE(clusters->at(0).Hits_size() == 1);
0290         REQUIRE(clusters->at(0).Hits().at(0).cellID() == 22);
0291 
0292         //auto other_clusters = event->GetCollection<ExampleCluster>("other_clusters");
0293         //REQUIRE(other_clusters->size() == 1);
0294         //REQUIRE(0 == 1);
0295         auto frame = event->GetSingle<podio::Frame>();
0296         const auto& other_clusters = frame->get<ExampleClusterCollection>("other_clusters");
0297         REQUIRE(other_clusters.size() == 1);
0298 
0299 
0300         event->Clear(true);
0301 
0302         ExampleHitCollection hits2;
0303         auto h2 = hits2.create();
0304         h2.cellID(3);
0305         auto h3 = hits2.create();
0306         h3.cellID(99);
0307         event->InsertCollection<ExampleHit>(std::move(hits2), "hits");
0308         auto clusters2 = event->GetCollection<ExampleCluster>("clusters");
0309         REQUIRE(clusters2->size() == 1);
0310         REQUIRE(clusters2->at(0).Hits_size() == 2);
0311         REQUIRE(clusters2->at(0).Hits().at(0).cellID() == 3);
0312         REQUIRE(clusters2->at(0).Hits().at(1).cellID() == 99);
0313     }
0314     
0315     SECTION("InsertCollectionAlreadyInFrame") {
0316         ExampleHitCollection hits;
0317         auto h1 = hits.create();
0318         h1.cellID(22);
0319         podio::Frame* frame1 = new podio::Frame;
0320         frame1->put(std::move(hits), "hits");
0321         auto const_hits = frame1->get("hits");
0322         event->InsertCollectionAlreadyInFrame<ExampleHit>(const_hits, "hits");
0323         event->Insert(frame1, "");
0324 
0325         auto clusters = event->GetCollection<ExampleCluster>("clusters");
0326         auto clusters3 = event->GetCollection<ExampleCluster>("clusters");
0327         // Ensure that Process() isn't called twice
0328         REQUIRE(clusters3->size() == 1);
0329 
0330         REQUIRE(clusters->size() == 1);
0331         REQUIRE(clusters->at(0).Hits_size() == 1);
0332         REQUIRE(clusters->at(0).Hits().at(0).cellID() == 22);
0333 
0334         event->Clear(true);
0335 
0336         ExampleHitCollection hits2;
0337         auto h2 = hits2.create();
0338         h2.cellID(3);
0339         auto h3 = hits2.create();
0340         h3.cellID(99);
0341 
0342         podio::Frame* frame2 = new podio::Frame;
0343         frame2->put(std::move(hits2), "hits");
0344         auto const_hits2 = frame2->get("hits");
0345         event->Insert(frame2, "");
0346         event->InsertCollectionAlreadyInFrame<ExampleHit>(const_hits2, "hits");
0347 
0348         auto clusters2 = event->GetCollection<ExampleCluster>("clusters");
0349 
0350         REQUIRE(clusters2->size() == 1);
0351         REQUIRE(clusters2->at(0).Hits_size() == 2);
0352         REQUIRE(clusters2->at(0).Hits().at(0).cellID() == 3);
0353         REQUIRE(clusters2->at(0).Hits().at(1).cellID() == 99);
0354     }
0355 
0356 } // TEST_CASE
0357 } // namespace
0358 
0359 namespace podio_exception_tests {
0360 
0361 class ExceptingPodioFactory : public JFactory {
0362 
0363     PodioOutput<ExampleHit> hits_out {this};
0364     Parameter<int> except {this, "except", 0, "0: None, 1: in Init(), 2: start of Process(), 3: end of Process()"};
0365 
0366 public:
0367     ExceptingPodioFactory() {
0368         SetPrefix("myfac");
0369     }
0370     void Init() override {
0371         LOG_INFO(GetLogger()) << "except=" << *except;
0372         if (*except == 1) {
0373             throw JException("Exception in Init()");
0374         }
0375     }
0376     void Process(const JEvent& event) override {
0377         if (*except == 2) {
0378             throw JException("Exception in Process() before some data is written");
0379         }
0380         MutableExampleHit hit;
0381         hit.x(event.GetEventNumber());
0382         hits_out->push_back(hit);
0383         if (*except == 3) {
0384             throw JException("Exception in Process() after some data is written");
0385         }
0386     }
0387 };
0388 
0389 
0390 TEST_CASE("PodioTests_ExceptionInFactoryInit") {
0391     SECTION("ExceptionInInit") {
0392         JApplication app;
0393         app.Add(new JFactoryGeneratorT<ExceptingPodioFactory>);
0394         app.SetParameterValue("myfac:except", 1);
0395         app.Initialize();
0396 
0397         JEvent event(&app);
0398 
0399         try {
0400             event.GetCollectionBase("ExampleHit");
0401             REQUIRE(0 == 1);
0402         } catch (...) { }
0403 
0404         try {
0405             event.GetCollectionBase("ExampleHit");
0406             REQUIRE(0 == 1);
0407         } catch (...) { }
0408 
0409         auto frame = event.Get<podio::Frame>().at(0);
0410         REQUIRE(frame->get<ExampleHitCollection>("ExampleHit").size() == 0);
0411 
0412         event.Clear(true);
0413 
0414         try {
0415             event.GetCollectionBase("ExampleHit");
0416             REQUIRE(0 == 1);
0417         } catch (...) { }
0418 
0419         frame = event.Get<podio::Frame>().at(0);
0420         REQUIRE(frame->get<ExampleHitCollection>("ExampleHit").size() == 0);
0421     }
0422     SECTION("ExceptionAtStartOfProcess") {
0423         JApplication app;
0424         app.Add(new JFactoryGeneratorT<ExceptingPodioFactory>);
0425         app.SetParameterValue("myfac:except", 2);
0426         app.Initialize();
0427 
0428         JEvent event(&app);
0429 
0430         try {
0431             event.GetCollectionBase("ExampleHit");
0432             REQUIRE(0 == 1);
0433         } catch (...) { }
0434 
0435         try {
0436             event.GetCollectionBase("ExampleHit");
0437             REQUIRE(0 == 1);
0438         } catch (...) { }
0439 
0440         auto frame = event.Get<podio::Frame>().at(0);
0441         REQUIRE(frame->get<ExampleHitCollection>("ExampleHit").size() == 0);
0442 
0443         event.Clear(true);
0444 
0445         try {
0446             event.GetCollectionBase("ExampleHit");
0447             REQUIRE(0 == 1);
0448         } catch (...) { }
0449 
0450         frame = event.Get<podio::Frame>().at(0);
0451         REQUIRE(frame->get<ExampleHitCollection>("ExampleHit").size() == 0);
0452     }
0453 
0454     SECTION("ExceptionAtEndOfProcess") {
0455         JApplication app;
0456         app.Add(new JFactoryGeneratorT<ExceptingPodioFactory>);
0457         app.SetParameterValue("myfac:except", 3);
0458         app.Initialize();
0459 
0460         JEvent event(&app);
0461         event.SetEventNumber(22);
0462 
0463         std::cout << "Calling failing factory" << std::endl;
0464         try {
0465             event.GetCollectionBase("ExampleHit");
0466             REQUIRE(0 == 1);
0467         } catch (...) { }
0468 
0469         std::cout << "Calling failing factory" << std::endl;
0470 
0471         try {
0472             event.GetCollectionBase("ExampleHit");
0473             REQUIRE(0 == 1);
0474         } catch (...) { }
0475 
0476         std::cout << "Retrieving collection from frame" << std::endl;
0477         auto frame = event.Get<podio::Frame>().at(0);
0478         REQUIRE(frame->get<ExampleHitCollection>("ExampleHit").size() == 1);
0479 
0480         std::cout << "Clearing event" << std::endl;
0481         event.Clear(true);
0482         event.SetEventNumber(23);
0483 
0484         std::cout << "Calling failing factory" << std::endl;
0485         try {
0486             event.GetCollectionBase("ExampleHit");
0487             REQUIRE(0 == 1);
0488         } catch (...) { }
0489 
0490         std::cout << "Retrieving collection from frame" << std::endl;
0491 
0492         frame = event.Get<podio::Frame>().at(0);
0493         for (const auto& hit : frame->get<ExampleHitCollection>("ExampleHit")) {
0494             std::cout << "Hit x=" << hit.x() << std::endl;
0495         }
0496         REQUIRE(frame->get<ExampleHitCollection>("ExampleHit").size() == 1);
0497     }
0498 }
0499 
0500 TEST_CASE("PodioTests_InterleavedInsertAndProcess") {
0501     JApplication app;
0502     app.Add(new JFactoryGeneratorT<ExceptingPodioFactory>);
0503     app.SetParameterValue("myfac:except", 0); // Disable exceptions
0504     app.Initialize();
0505 
0506     JEvent event(&app);
0507 
0508     auto databundle = event.GetFactorySet()->GetDatabundle("ExampleHit");
0509     REQUIRE(databundle->GetStatus() == JDatabundle::Status::Empty);
0510     REQUIRE(databundle->GetFactory() != nullptr);
0511     REQUIRE(databundle->GetFactory()->GetStatus() == JFactory::Status::Empty);
0512     REQUIRE(databundle->GetFactory()->GetInitStatus() == JFactory::InitStatus::InitNotRun);
0513 
0514 
0515     // Insert hits. This will NOT trigger Init
0516     ExampleHitCollection hits;
0517     hits.push_back(MutableExampleHit());
0518     event.InsertCollection<ExampleHit>(std::move(hits), "ExampleHit");
0519 
0520     event.GetCollectionBase("ExampleHit");
0521     REQUIRE(databundle->GetFactory()->GetInitStatus() == JFactory::InitStatus::InitNotRun);
0522 
0523     event.Clear();
0524 
0525     // Trigger Init and Process
0526     event.GetCollectionBase("ExampleHit");
0527     REQUIRE(databundle->GetFactory()->GetInitStatus() == JFactory::InitStatus::InitRun);
0528 }
0529 
0530 } // namespace
0531 
0532