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 ) {
0069 return true;
0070 }
0071
0072 template <typename T, typename std::enable_if_t<!is_podio_v<T>>* = nullptr>
0073 bool DeclareOutput(std::string ) {
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
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 }
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};
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 }
0246 }
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
0293
0294
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
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 }
0357 }
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);
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
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
0526 event.GetCollectionBase("ExampleHit");
0527 REQUIRE(databundle->GetFactory()->GetInitStatus() == JFactory::InitStatus::InitRun);
0528 }
0529
0530 }
0531
0532