Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-20 08:03:21

0001 
0002 #include <JANA/JApplication.h>
0003 #include <JANA/JApplicationFwd.h>
0004 #include <JANA/JEvent.h>
0005 #include <JANA/JFactorySet.h>
0006 #include <JANA/JMultifactory.h>
0007 #include <JANA/Services/JComponentManager.h>
0008 #include <JANA/Services/JParameterManager.h>
0009 #include <JANA/Utils/JTypeInfo.h>
0010 #include <catch2/catch_test_macros.hpp>
0011 #include <edm4hep/SimCalorimeterHitCollection.h>
0012 #include <fmt/core.h>
0013 #include <fmt/format.h>
0014 #include <spdlog/logger.h>
0015 #include <cstdint>
0016 #include <iostream>
0017 #include <map>
0018 #include <memory>
0019 #include <string>
0020 #include <utility>
0021 #include <vector>
0022 
0023 #include "extensions/jana/JOmniFactory.h"
0024 #include "extensions/jana/JOmniFactoryGeneratorT.h"
0025 
0026 struct BasicTestAlgConfig {
0027   int bucket_count = 42;
0028   double threshold = 7.6;
0029 };
0030 
0031 struct BasicTestAlg : public JOmniFactory<BasicTestAlg, BasicTestAlgConfig> {
0032 
0033   PodioOutput<edm4hep::SimCalorimeterHit> output_hits_left{this, "output_hits_left"};
0034   PodioOutput<edm4hep::SimCalorimeterHit> output_hits_right{this, "output_hits_right"};
0035   Output<edm4hep::SimCalorimeterHit> output_vechits{this, "output_vechits"};
0036 
0037   ParameterRef<int> bucket_count{this, "bucket_count", config().bucket_count,
0038                                  "The total number of buckets [dimensionless]"};
0039   ParameterRef<double> threshold{this, "threshold", config().threshold,
0040                                  "The max cutoff threshold [V * A * kg^-1 * m^-2 * sec^-3]"};
0041 
0042   std::vector<OutputBase*> GetOutputs() { return this->m_outputs; }
0043 
0044   int m_init_call_count      = 0;
0045   int m_changerun_call_count = 0;
0046   int m_process_call_count   = 0;
0047 
0048   void Configure() {
0049     m_init_call_count++;
0050     logger()->info("Calling BasicTestAlg::Configure");
0051   }
0052 
0053   void ChangeRun(int32_t /* run_number */) override {
0054     m_changerun_call_count++;
0055     logger()->info("Calling BasicTestAlg::ChangeRun");
0056   }
0057 
0058   // NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
0059   void Process(int32_t /* run_number */, uint64_t /* event_number */) override {
0060     m_process_call_count++;
0061     logger()->info("Calling BasicTestAlg::Process with bucket_count={}, threshold={}",
0062                    config().bucket_count, config().threshold);
0063     // Provide empty collections (as opposed to nulls) so that PODIO doesn't crash
0064     output_hits_left()  = std::make_unique<edm4hep::SimCalorimeterHitCollection>();
0065     output_hits_right() = std::make_unique<edm4hep::SimCalorimeterHitCollection>();
0066     output_vechits().push_back(new edm4hep::SimCalorimeterHit());
0067   }
0068 };
0069 
0070 template <typename OutputCollectionT, typename MultifactoryT>
0071 MultifactoryT* RetrieveMultifactory(JFactorySet* facset, std::string output_collection_name) {
0072   auto fac = facset->GetFactory(JTypeInfo::demangle<OutputCollectionT>(), output_collection_name);
0073   REQUIRE(fac != nullptr);
0074   auto helper = dynamic_cast<JMultifactoryHelperPodio<OutputCollectionT>*>(fac);
0075   REQUIRE(helper != nullptr);
0076   auto multifactory = helper->GetMultifactory();
0077   REQUIRE(multifactory != nullptr);
0078   auto typed = dynamic_cast<MultifactoryT*>(multifactory);
0079   REQUIRE(typed != nullptr);
0080   return typed;
0081 }
0082 
0083 TEST_CASE("Registering Podio outputs works") {
0084   BasicTestAlg alg;
0085   REQUIRE(alg.GetOutputs().size() == 3);
0086   REQUIRE(alg.GetOutputs()[0]->collection_names[0] == "output_hits_left");
0087   REQUIRE(alg.GetOutputs()[0]->type_name == "edm4hep::SimCalorimeterHit");
0088   REQUIRE(alg.GetOutputs()[1]->collection_names[0] == "output_hits_right");
0089   REQUIRE(alg.GetOutputs()[1]->type_name == "edm4hep::SimCalorimeterHit");
0090   REQUIRE(alg.GetOutputs()[2]->collection_names[0] == "output_vechits");
0091   REQUIRE(alg.GetOutputs()[2]->type_name == "edm4hep::SimCalorimeterHit");
0092 }
0093 
0094 TEST_CASE("Configuration object is correctly wired from untyped wiring data") {
0095   JApplication app;
0096   app.AddPlugin("log");
0097   app.Initialize();
0098   JOmniFactoryGeneratorT<BasicTestAlg> facgen(&app);
0099   facgen.AddWiring("ECalTestAlg", {}, {"ECalLeftHits", "ECalRightHits", "ECalVecHits"},
0100                    {{"threshold", "6.1"}, {"bucket_count", "22"}});
0101 
0102   JFactorySet facset;
0103   facgen.GenerateFactories(&facset);
0104   // for (auto* fac : facset.GetAllFactories()) {
0105   // std::cout << "typename=" << fac->GetFactoryName() << ", tag=" << fac->GetTag() << std::endl;
0106   // }
0107 
0108   auto* basictestalg =
0109       RetrieveMultifactory<edm4hep::SimCalorimeterHit, BasicTestAlg>(&facset, "ECalLeftHits");
0110 
0111   REQUIRE(basictestalg->threshold() == 6.1);
0112   REQUIRE(basictestalg->bucket_count() == 22);
0113 
0114   REQUIRE(basictestalg->config().threshold == 6.1);
0115   REQUIRE(basictestalg->config().bucket_count == 22);
0116 
0117   REQUIRE(basictestalg->m_init_call_count == 0);
0118 }
0119 
0120 TEST_CASE("Multiple configuration objects are correctly wired from untyped wiring data") {
0121   JApplication app;
0122   app.AddPlugin("log");
0123   app.Initialize();
0124   JOmniFactoryGeneratorT<BasicTestAlg> facgen(&app);
0125   facgen.AddWiring("BCalTestAlg", {}, {"BCalLeftHits", "BCalRightHits", "BCalVecHits"},
0126                    {{"threshold", "6.1"}, {"bucket_count", "22"}});
0127   facgen.AddWiring("CCalTestAlg", {}, {"CCalLeftHits", "CCalRightHits", "CCalVecHits"},
0128                    {{"threshold", "9.0"}, {"bucket_count", "27"}});
0129   facgen.AddWiring("ECalTestAlg", {}, {"ECalLeftHits", "ECalRightHits", "ECalVecHits"},
0130                    {{"threshold", "16.25"}, {"bucket_count", "49"}});
0131 
0132   JFactorySet facset;
0133   facgen.GenerateFactories(&facset);
0134   // for (auto* fac : facset.GetAllFactories()) {
0135   // std::cout << "typename=" << fac->GetFactoryName() << ", tag=" << fac->GetTag() << std::endl;
0136   // }
0137   auto* b = RetrieveMultifactory<edm4hep::SimCalorimeterHit, BasicTestAlg>(&facset, "BCalLeftHits");
0138   auto* c = RetrieveMultifactory<edm4hep::SimCalorimeterHit, BasicTestAlg>(&facset, "CCalLeftHits");
0139   auto* e = RetrieveMultifactory<edm4hep::SimCalorimeterHit, BasicTestAlg>(&facset, "ECalLeftHits");
0140 
0141   REQUIRE(b->threshold() == 6.1);
0142   REQUIRE(b->bucket_count() == 22);
0143   REQUIRE(b->config().threshold == 6.1);
0144   REQUIRE(b->config().bucket_count == 22);
0145 
0146   REQUIRE(c->threshold() == 9.0);
0147   REQUIRE(c->bucket_count() == 27);
0148   REQUIRE(c->config().threshold == 9.0);
0149   REQUIRE(c->config().bucket_count == 27);
0150 
0151   REQUIRE(e->threshold() == 16.25);
0152   REQUIRE(e->bucket_count() == 49);
0153   REQUIRE(e->config().threshold == 16.25);
0154   REQUIRE(e->config().bucket_count == 49);
0155 
0156   REQUIRE(b->m_init_call_count == 0);
0157   REQUIRE(c->m_init_call_count == 0);
0158   REQUIRE(e->m_init_call_count == 0);
0159 }
0160 
0161 TEST_CASE(
0162     "JParameterManager correctly understands which values are defaulted and which are overridden") {
0163   JApplication app;
0164   app.AddPlugin("log");
0165 
0166   auto* facgen = new JOmniFactoryGeneratorT<BasicTestAlg>(&app);
0167   facgen->AddWiring("FunTest", {}, {"BCalLeftHits", "BCalRightHits", "BCalVecHits"},
0168                     {{"threshold", "6.1"}, {"bucket_count", "22"}});
0169   app.Add(facgen);
0170 
0171   app.GetJParameterManager()->SetParameter("FunTest:threshold", 12.0);
0172   app.Initialize();
0173 
0174   auto event = std::make_shared<JEvent>();
0175   app.GetService<JComponentManager>()->configure_event(*event);
0176 
0177   // for (auto* fac : event->GetFactorySet()->GetAllFactories()) {
0178   // std::cout << "typename=" << fac->GetFactoryName() << ", tag=" << fac->GetTag() << std::endl;
0179   // }
0180 
0181   // Retrieve multifactory
0182   auto* b = RetrieveMultifactory<edm4hep::SimCalorimeterHit, BasicTestAlg>(event->GetFactorySet(),
0183                                                                            "BCalLeftHits");
0184 
0185   // Overrides won't happen until factory gets Init()ed. However, defaults will be applied immediately
0186   REQUIRE(b->threshold() == 6.1);
0187   REQUIRE(b->config().threshold == 6.1);
0188 
0189   // Trigger JMF::Execute(), in order to trigger Init(), in order to Configure()s all Parameter fields...
0190   auto lefthits = event->Get<edm4hep::SimCalorimeterHit>("BCalLeftHits");
0191 
0192   REQUIRE(b->threshold() == 12.0);
0193   REQUIRE(b->config().threshold == 12.0);
0194 
0195   std::cout << "Showing the full table of config parameters" << std::endl;
0196   app.GetJParameterManager()->PrintParameters(2, 1); // verbosity, strictness
0197 
0198   std::cout << "Showing only overridden config parameters" << std::endl;
0199   app.GetJParameterManager()->PrintParameters(1, 1); // verbosity, strictness
0200 }
0201 
0202 TEST_CASE("Wiring itself is correctly defaulted") {
0203   JApplication app;
0204   app.AddPlugin("log");
0205 
0206   auto* facgen = new JOmniFactoryGeneratorT<BasicTestAlg>(&app);
0207   facgen->AddWiring("FunTest", {}, {"BCalLeftHits", "BCalRightHits", "BCalVecHits"},
0208                     {{"threshold", "6.1"}});
0209   app.Add(facgen);
0210   app.Initialize();
0211 
0212   auto event = std::make_shared<JEvent>();
0213   app.GetService<JComponentManager>()->configure_event(*event);
0214 
0215   // Retrieve multifactory
0216   auto* b = RetrieveMultifactory<edm4hep::SimCalorimeterHit, BasicTestAlg>(event->GetFactorySet(),
0217                                                                            "BCalLeftHits");
0218 
0219   // Overrides won't happen until factory gets Init()ed. However, defaults will be applied immediately
0220   REQUIRE(b->bucket_count() == 42);        // Not provided by wiring
0221   REQUIRE(b->config().bucket_count == 42); // Not provided by wiring
0222 
0223   REQUIRE(b->threshold() == 6.1);        // Provided by wiring
0224   REQUIRE(b->config().threshold == 6.1); // Provided by wiring
0225 
0226   // Trigger JMF::Execute(), in order to trigger Init(), in order to Configure()s all Parameter fields...
0227   auto lefthits = event->Get<edm4hep::SimCalorimeterHit>("BCalLeftHits");
0228 
0229   // We didn't override the config values via the parameter manager, so all of these should be the same
0230   REQUIRE(b->bucket_count() == 42);        // Not provided by wiring
0231   REQUIRE(b->config().bucket_count == 42); // Not provided by wiring
0232 
0233   REQUIRE(b->threshold() == 6.1);        // Provided by wiring
0234   REQUIRE(b->config().threshold == 6.1); // Provided by wiring
0235 
0236   b->logger()->info("Showing the full table of config parameters");
0237   app.GetJParameterManager()->PrintParameters(2, 1); // verbosity, strictness
0238 
0239   b->logger()->info("Showing only overridden config parameters");
0240   // Should be empty because everything is defaulted
0241   app.GetJParameterManager()->PrintParameters(1, 1); // verbosity, strictness
0242 }
0243 
0244 struct VariadicTestAlg : public JOmniFactory<VariadicTestAlg, BasicTestAlgConfig> {
0245 
0246   PodioInput<edm4hep::SimCalorimeterHit> m_hits_in{this};
0247   VariadicPodioInput<edm4hep::SimCalorimeterHit> m_variadic_hits_in{this};
0248   PodioOutput<edm4hep::SimCalorimeterHit> m_hits_out{this};
0249 
0250   std::vector<OutputBase*> GetOutputs() { return this->m_outputs; }
0251 
0252   int m_init_call_count      = 0;
0253   int m_changerun_call_count = 0;
0254   int m_process_call_count   = 0;
0255 
0256   void Configure() {
0257     m_init_call_count++;
0258     logger()->info("Calling VariadicTestAlg::Configure");
0259   }
0260 
0261   void ChangeRun(int32_t /* run_number */) override {
0262     m_changerun_call_count++;
0263     logger()->info("Calling VariadicTestAlg::ChangeRun");
0264   }
0265 
0266   // NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
0267   void Process(int32_t /* run_number */, uint64_t /* event_number */) override {
0268     m_process_call_count++;
0269     logger()->info("Calling VariadicTestAlg::Process with bucket_count={}, threshold={}",
0270                    config().bucket_count, config().threshold);
0271 
0272     REQUIRE(m_hits_in()->size() == 3);
0273     REQUIRE(m_variadic_hits_in().size() == 2);
0274     REQUIRE(m_variadic_hits_in()[0]->size() == 1);
0275     REQUIRE(m_variadic_hits_in()[1]->size() == 2);
0276 
0277     m_hits_out() = std::make_unique<edm4hep::SimCalorimeterHitCollection>();
0278     m_hits_out()->create();
0279     m_hits_out()->create();
0280     m_hits_out()->create();
0281     m_hits_out()->create();
0282   }
0283 };
0284 
0285 TEST_CASE("VariadicOmniFactoryTests") {
0286   VariadicTestAlg alg;
0287   JApplication app;
0288   app.AddPlugin("log");
0289 
0290   auto* facgen = new JOmniFactoryGeneratorT<VariadicTestAlg>(
0291       "VariadicTest", {"main_hits", "fun_hits", "funner_hits"}, {"processed_hits"}, &app);
0292   app.Add(facgen);
0293   app.Initialize();
0294 
0295   auto event = std::make_shared<JEvent>();
0296   app.GetService<JComponentManager>()->configure_event(*event);
0297 
0298   edm4hep::SimCalorimeterHitCollection mains;
0299   edm4hep::SimCalorimeterHitCollection funs;
0300   edm4hep::SimCalorimeterHitCollection funners;
0301 
0302   mains.create();
0303   mains.create();
0304   mains.create();
0305 
0306   funs.create();
0307   funners.create();
0308   funners.create();
0309 
0310   event->InsertCollection<edm4hep::SimCalorimeterHit>(std::move(mains), "main_hits");
0311   event->InsertCollection<edm4hep::SimCalorimeterHit>(std::move(funs), "fun_hits");
0312   event->InsertCollection<edm4hep::SimCalorimeterHit>(std::move(funners), "funner_hits");
0313 
0314   const auto* processed = event->GetCollection<edm4hep::SimCalorimeterHit>("processed_hits");
0315   REQUIRE(processed->size() == 4);
0316 }
0317 
0318 struct SubsetTestAlg : public JOmniFactory<SubsetTestAlg, BasicTestAlgConfig> {
0319 
0320   VariadicPodioInput<edm4hep::SimCalorimeterHit> m_left_hits_in{this};
0321   PodioInput<edm4hep::SimCalorimeterHit> m_center_hits_in{this};
0322   VariadicPodioInput<edm4hep::SimCalorimeterHit> m_right_hits_in{this};
0323   PodioOutput<edm4hep::SimCalorimeterHit> m_hits_out{this};
0324 
0325   std::vector<OutputBase*> GetOutputs() { return this->m_outputs; }
0326 
0327   void Configure() {}
0328 
0329   // NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
0330   void Process(int32_t /* run_number */, uint64_t /* event_number */) override {
0331 
0332     // Variadic collection count constrained to be same size
0333     REQUIRE(m_left_hits_in().size() == 1);
0334     REQUIRE(m_right_hits_in().size() == 1);
0335 
0336     REQUIRE(m_left_hits_in()[0]->size() == 2);
0337     REQUIRE(m_right_hits_in()[0]->size() == 1);
0338 
0339     REQUIRE(m_center_hits_in()->size() == 3);
0340 
0341     m_hits_out() = std::make_unique<edm4hep::SimCalorimeterHitCollection>();
0342     m_hits_out()->setSubsetCollection();
0343 
0344     const auto* lhi = m_left_hits_in()[0];
0345     for (const auto& hit : *lhi) {
0346       m_hits_out()->push_back(hit);
0347     }
0348     for (const auto& hit : *m_center_hits_in()) {
0349       m_hits_out()->push_back(hit);
0350     }
0351   }
0352 };
0353 
0354 TEST_CASE("SubsetOmniFactoryTests") {
0355   JApplication app;
0356   app.AddPlugin("log");
0357 
0358   auto* facgen = new JOmniFactoryGeneratorT<SubsetTestAlg>(
0359       "SubsetTest", {"left", "center", "right"}, {"processed_hits"}, &app);
0360   app.Add(facgen);
0361   app.Initialize();
0362 
0363   auto event = std::make_shared<JEvent>();
0364   app.GetService<JComponentManager>()->configure_event(*event);
0365 
0366   edm4hep::SimCalorimeterHitCollection left;
0367   edm4hep::SimCalorimeterHitCollection center;
0368   edm4hep::SimCalorimeterHitCollection right;
0369 
0370   left.create();
0371   left.create();
0372   right.create();
0373 
0374   center.create();
0375   center.create();
0376   center.create();
0377 
0378   event->InsertCollection<edm4hep::SimCalorimeterHit>(std::move(left), "left");
0379   event->InsertCollection<edm4hep::SimCalorimeterHit>(std::move(center), "center");
0380   event->InsertCollection<edm4hep::SimCalorimeterHit>(std::move(right), "right");
0381 
0382   const auto* processed = event->GetCollection<edm4hep::SimCalorimeterHit>("processed_hits");
0383   REQUIRE(processed->size() == 5);
0384 }
0385 
0386 struct VariadicOutputTestAlg : public JOmniFactory<VariadicOutputTestAlg, BasicTestAlgConfig> {
0387 
0388   PodioInput<edm4hep::SimCalorimeterHit> m_hits_in{this};
0389 
0390   VariadicPodioOutput<edm4hep::SimCalorimeterHit> m_hits_out{this};
0391 
0392   void Configure() {}
0393 
0394   // NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
0395   void Process(int32_t /* run_number */, uint64_t /* event_number */) override {
0396 
0397     REQUIRE(m_hits_out().size() == 2);
0398     m_hits_out()[0]->setSubsetCollection();
0399     m_hits_out()[1]->setSubsetCollection();
0400 
0401     int i = 0;
0402     for (const auto& hit : *(m_hits_in())) {
0403       m_hits_out()[i]->push_back(hit);
0404       i = (i == 1) ? 0 : 1;
0405     }
0406   }
0407 };
0408 
0409 TEST_CASE("VariadicPodioOutputTests") {
0410   JApplication app;
0411   app.AddPlugin("log");
0412 
0413   auto* facgen = new JOmniFactoryGeneratorT<VariadicOutputTestAlg>(
0414       "VariadicOutputTest", {"all_hits"}, {"left_hits", "right_hits"}, &app);
0415   app.Add(facgen);
0416   app.Initialize();
0417 
0418   auto event = std::make_shared<JEvent>();
0419   app.GetService<JComponentManager>()->configure_event(*event);
0420 
0421   edm4hep::SimCalorimeterHitCollection all_hits;
0422 
0423   all_hits.create();
0424   all_hits.create();
0425   all_hits.create();
0426 
0427   event->InsertCollection<edm4hep::SimCalorimeterHit>(std::move(all_hits), "all_hits");
0428 
0429   const auto* left_hits  = event->GetCollection<edm4hep::SimCalorimeterHit>("left_hits");
0430   const auto* right_hits = event->GetCollection<edm4hep::SimCalorimeterHit>("right_hits");
0431   REQUIRE(left_hits->size() == 2);
0432   REQUIRE(right_hits->size() == 1);
0433 }
0434 
0435 struct OptionalPodioInputTestAlg
0436     : public JOmniFactory<OptionalPodioInputTestAlg, BasicTestAlgConfig> {
0437 
0438   PodioInput<edm4hep::SimCalorimeterHit, true> m_left_hits_in{this};
0439   PodioInput<edm4hep::SimCalorimeterHit, false> m_right_hits_in{this};
0440 
0441   PodioOutput<edm4hep::SimCalorimeterHit> m_left_hits_out{this};
0442   PodioOutput<edm4hep::SimCalorimeterHit> m_right_hits_out{this};
0443 
0444   void Configure() {}
0445 
0446   void Process(int32_t /* run_number */, uint64_t /* event_number */) override {
0447 
0448     logger()->info("Calling OptionalPodioInputTestAlg::Process");
0449 
0450     m_left_hits_out()  = std::make_unique<edm4hep::SimCalorimeterHitCollection>();
0451     m_right_hits_out() = std::make_unique<edm4hep::SimCalorimeterHitCollection>();
0452     //Set the subset flag
0453     m_left_hits_out()->setSubsetCollection();
0454     m_right_hits_out()->setSubsetCollection();
0455 
0456     //Copy hits to output collections
0457     if (m_left_hits_in() != nullptr) {
0458       for (const auto& hit : *(m_left_hits_in())) {
0459         m_left_hits_out()->push_back(hit);
0460       }
0461     }
0462     if (m_right_hits_in() != nullptr) {
0463       for (const auto& hit : *(m_right_hits_in())) {
0464         m_right_hits_out()->push_back(hit);
0465       }
0466     }
0467   }
0468 };
0469 
0470 TEST_CASE("Optional PodioInput") {
0471   JApplication app;
0472   app.AddPlugin("log");
0473 
0474   auto* facgen = new JOmniFactoryGeneratorT<OptionalPodioInputTestAlg>(
0475       "OptionalPodioInputTest", {"left_hits", "right_hits"}, {"left_hits_out", "right_hits_out"},
0476       &app);
0477 
0478   app.Add(facgen);
0479   app.Initialize();
0480 
0481   auto event = std::make_shared<JEvent>();
0482   app.GetService<JComponentManager>()->configure_event(*event);
0483 
0484   SECTION("Both collections are set") {
0485     edm4hep::SimCalorimeterHitCollection left_hits;
0486     edm4hep::SimCalorimeterHitCollection right_hits;
0487     left_hits.create();
0488     left_hits.create();
0489     right_hits.create();
0490     event->InsertCollection<edm4hep::SimCalorimeterHit>(std::move(left_hits), "left_hits");
0491     event->InsertCollection<edm4hep::SimCalorimeterHit>(std::move(right_hits), "right_hits");
0492 
0493     const auto* left_hits_out  = event->GetCollection<edm4hep::SimCalorimeterHit>("left_hits_out");
0494     const auto* right_hits_out = event->GetCollection<edm4hep::SimCalorimeterHit>("right_hits_out");
0495     REQUIRE(left_hits_out->size() == 2);
0496     REQUIRE(right_hits_out->size() == 1);
0497   }
0498   SECTION("Left hits are not set") {
0499     edm4hep::SimCalorimeterHitCollection right_hits;
0500     right_hits.create();
0501     event->InsertCollection<edm4hep::SimCalorimeterHit>(std::move(right_hits), "right_hits");
0502 
0503     const auto* left_hits_out  = event->GetCollection<edm4hep::SimCalorimeterHit>("left_hits_out");
0504     const auto* right_hits_out = event->GetCollection<edm4hep::SimCalorimeterHit>("right_hits_out");
0505     REQUIRE(left_hits_out->empty());
0506     REQUIRE(right_hits_out->size() == 1);
0507   }
0508   SECTION("Right hits are not set") {
0509     edm4hep::SimCalorimeterHitCollection left_hits;
0510     left_hits.create();
0511     left_hits.create();
0512     event->InsertCollection<edm4hep::SimCalorimeterHit>(std::move(left_hits), "left_hits");
0513 
0514     REQUIRE_THROWS(event->GetCollection<edm4hep::SimCalorimeterHit>("left_hits_out"));
0515     REQUIRE_THROWS(event->GetCollection<edm4hep::SimCalorimeterHit>("right_hits_out"));
0516   }
0517 }
0518 
0519 struct OptionalVariadicPodioInputTestAlg
0520     : public JOmniFactory<OptionalVariadicPodioInputTestAlg, BasicTestAlgConfig> {
0521 
0522   VariadicPodioInput<edm4hep::SimCalorimeterHit, true> m_hits_in{this};
0523 
0524   PodioOutput<edm4hep::SimCalorimeterHit> m_hits_out{this};
0525 
0526   void Configure() {}
0527 
0528   void Process(int32_t /* run_number */, uint64_t /* event_number */) override {
0529 
0530     logger()->info("Calling OptionalVariadicPodioInputTestAlg::Process");
0531 
0532     m_hits_out() = std::make_unique<edm4hep::SimCalorimeterHitCollection>();
0533     //Set the subset flag
0534     m_hits_out()->setSubsetCollection();
0535     //Copy hits to output collections
0536     for (const auto& coll : m_hits_in()) {
0537       if (coll != nullptr) {
0538         for (const auto& hit : *coll) {
0539           m_hits_out()->push_back(hit);
0540         }
0541       }
0542     }
0543   }
0544 };
0545 
0546 TEST_CASE("Optional Variadic Podio Input") {
0547   JApplication app;
0548   app.AddPlugin("log");
0549 
0550   auto* facgen = new JOmniFactoryGeneratorT<OptionalVariadicPodioInputTestAlg>(
0551       "OptionalVariadicPodioInputTest", {"left_hits", "center_hits", "right_hits"}, {"hits_out"},
0552       &app);
0553 
0554   app.Add(facgen);
0555   app.Initialize();
0556 
0557   auto event = std::make_shared<JEvent>();
0558   app.GetService<JComponentManager>()->configure_event(*event);
0559 
0560   SECTION("All collections are set") {
0561     edm4hep::SimCalorimeterHitCollection left_hits;
0562     edm4hep::SimCalorimeterHitCollection center_hits;
0563     edm4hep::SimCalorimeterHitCollection right_hits;
0564     left_hits.create();
0565     left_hits.create();
0566     left_hits.create();
0567     center_hits.create();
0568     center_hits.create();
0569     right_hits.create();
0570     event->InsertCollection<edm4hep::SimCalorimeterHit>(std::move(left_hits), "left_hits");
0571     event->InsertCollection<edm4hep::SimCalorimeterHit>(std::move(center_hits), "center_hits");
0572     event->InsertCollection<edm4hep::SimCalorimeterHit>(std::move(right_hits), "right_hits");
0573 
0574     const auto* hits_out = event->GetCollection<edm4hep::SimCalorimeterHit>("hits_out");
0575 
0576     REQUIRE(hits_out->size() == 6);
0577   }
0578 
0579   SECTION("No collections are set") {
0580     const auto* hits_out = event->GetCollection<edm4hep::SimCalorimeterHit>("hits_out");
0581 
0582     REQUIRE(hits_out->empty());
0583   }
0584   SECTION("Only right collection is set") {
0585     edm4hep::SimCalorimeterHitCollection right_hits;
0586     right_hits.create();
0587     event->InsertCollection<edm4hep::SimCalorimeterHit>(std::move(right_hits), "right_hits");
0588 
0589     const auto* hits_out = event->GetCollection<edm4hep::SimCalorimeterHit>("hits_out");
0590     REQUIRE(hits_out->size() == 1);
0591   }
0592 }