File indexing completed on 2025-12-20 10:33:48
0001
0002 #include "JANA/Components/JOmniFactory.h"
0003 #include "JANA/Components/JWiredFactoryGeneratorT.h"
0004 #include "JANA/JEventProcessor.h"
0005 #include "JANA/JException.h"
0006 #include "JANA/Utils/JEventLevel.h"
0007 #include <JANA/Services/JWiringService.h>
0008 #include <catch.hpp>
0009 #include <memory>
0010 #include <toml.hpp>
0011 #include <iostream>
0012
0013
0014 static constexpr std::string_view some_wiring = R"(
0015 include = ["asdf.toml"]
0016
0017 [[wiring]]
0018 action = "add"
0019 plugin_name = "BCAL"
0020 type_name = "MyFac"
0021 prefix = "myfac"
0022 input_names = ["input_coll_1", "input_coll_2"]
0023 input_levels = ["Run", "Subrun"]
0024 output_names = ["output_coll_1", "output_coll_2"]
0025
0026 [wiring.configs]
0027 x = "22"
0028 y = "verbose"
0029
0030 [[wiring]]
0031 action = "add"
0032 plugin_name = "BCAL"
0033 type_name = "MyFac"
0034 prefix = "myfac_modified"
0035 input_names = ["input_coll_1", "input_coll_3"]
0036 output_names = ["output_coll_1_modified", "output_coll_2_modified"]
0037
0038 [wiring.configs]
0039 x = "100"
0040 y = "verbose"
0041
0042 )";
0043
0044 TEST_CASE("WiringTests") {
0045
0046 jana::services::JWiringService sut;
0047 toml::table table = toml::parse(some_wiring);
0048 sut.ApplyWiringSet(sut.ParseWiringSet(table));
0049
0050 const auto& wirings = sut.GetAllWirings();
0051 REQUIRE(wirings.size() == 2);
0052 auto& w0 = wirings.at("myfac");
0053 auto& w1 = wirings.at("myfac_modified");
0054
0055 REQUIRE(w0->prefix == "myfac");
0056 REQUIRE(w1->prefix == "myfac_modified");
0057 REQUIRE(w0->plugin_name == "BCAL");
0058 REQUIRE(w0->input_names[1] == "input_coll_2");
0059 REQUIRE(w1->input_names[1] == "input_coll_3");
0060 REQUIRE(w0->input_levels.size() == 2);
0061 REQUIRE(w0->input_levels[0] == JEventLevel::Run);
0062 REQUIRE(w0->input_levels[1] == JEventLevel::Subrun);
0063 REQUIRE(w1->input_levels.size() == 0);
0064 REQUIRE(w0->configs.size() == 2);
0065 REQUIRE(w0->configs["x"] == "22");
0066 REQUIRE(w0->configs["y"] == "verbose");
0067
0068 }
0069
0070 static constexpr std::string_view duplicate_prefixes = R"(
0071 [[wiring]]
0072 action = "add"
0073 plugin_name = "BCAL"
0074 type_name = "MyFac"
0075 prefix = "myfac"
0076
0077 [[wiring]]
0078 action = "add"
0079 plugin_name = "BCAL"
0080 type_name = "MyFac"
0081 prefix = "myfac"
0082 )";
0083
0084 TEST_CASE("WiringTests_DuplicatePrefixes") {
0085
0086 jana::services::JWiringService sut;
0087 toml::table table = toml::parse(duplicate_prefixes);
0088 try {
0089 sut.ApplyWiringSet(sut.ParseWiringSet(table));
0090 REQUIRE(1 == 0);
0091 }
0092 catch (const JException& e) {
0093 std::cout << e << std::endl;
0094 }
0095 }
0096
0097 TEST_CASE("WiringTests_Overlay") {
0098 using Wiring = jana::services::JWiringService::Wiring;
0099 auto above = std::make_unique<Wiring>();
0100 above->prefix = "myfac";
0101 above->type_name = "ClusteringFac";
0102 above->plugin_name = "FCAL";
0103 above->input_names = {"this", "should", "make", "it"};
0104 above->configs["x"] = "6.18";
0105
0106 auto below = std::make_unique<Wiring>();
0107 below->prefix = "myfac";
0108 below->type_name = "ClusteringFac";
0109 below->plugin_name = "FCAL";
0110 below->input_names = {"this", "should", "NOT", "make", "it"};
0111 below->input_levels = {JEventLevel::Run, JEventLevel::PhysicsEvent};
0112 below->configs["x"] = "7.6";
0113 below->configs["y"] = "42";
0114
0115 auto sut = jana::services::JWiringService();
0116 sut.Overlay(*above, *below);
0117 REQUIRE(above->input_names[2] == "make");
0118 REQUIRE(above->input_levels[1] == JEventLevel::PhysicsEvent);
0119 REQUIRE(above->configs["x"] == "6.18");
0120 REQUIRE(above->configs["y"] == "42");
0121 }
0122
0123 static constexpr std::string_view fake_wiring_file = R"(
0124 [[wiring]]
0125 action = "add"
0126 plugin_name = "ECAL"
0127 type_name = "ClusteringFac"
0128 prefix = "myfac"
0129
0130 [wiring.configs]
0131 x = "22"
0132 y = "verbose"
0133
0134 [[wiring]]
0135 action = "update"
0136 plugin_name = "ECAL"
0137 type_name = "ClusteringFac"
0138 prefix = "variantfac"
0139
0140 [wiring.configs]
0141 x = "49"
0142 y = "silent"
0143
0144 [[wiring]]
0145 action = "add"
0146 plugin_name = "BCAL"
0147 type_name = "ClusteringFac"
0148 prefix = "sillyfac"
0149
0150 [wiring.configs]
0151 x = "618"
0152 y = "mediocre"
0153 )";
0154
0155
0156 TEST_CASE("WiringTests_FakeFacGen") {
0157 jana::services::JWiringService sut;
0158 toml::table table = toml::parse(fake_wiring_file);
0159 auto wiring_set_file = sut.ParseWiringSet(table);
0160
0161 using Wiring = jana::services::JWiringService::Wiring;
0162 using WiringSet = jana::services::JWiringService::WiringSet;
0163 WiringSet wiring_set_facgen;
0164
0165
0166 auto a = std::make_unique<Wiring>();
0167 a->plugin_name = "ECAL";
0168 a->type_name = "ClusteringFac";
0169 a->prefix = "variantfac";
0170 a->configs["x"] = "42";
0171 wiring_set_facgen.wirings["variantfac"] = std::move(a);
0172
0173
0174 auto b = std::make_unique<Wiring>();
0175 b->plugin_name = "ECAL";
0176 b->type_name = "ClusteringFac";
0177 b->prefix = "exuberantfac";
0178 b->configs["x"] = "27";
0179 wiring_set_facgen.wirings["exuberantfac"] = std::move(b);
0180
0181 sut.OverlayWiringSet(wiring_set_file, wiring_set_facgen);
0182 sut.ApplyWiringSet(std::move(wiring_set_file));
0183
0184 auto myfac = sut.GetWiring("myfac");
0185 auto variantfac = sut.GetWiring("variantfac");
0186 auto exuberantfac = sut.GetWiring("exuberantfac");
0187
0188 REQUIRE(myfac != nullptr);
0189 REQUIRE(variantfac != nullptr);
0190 REQUIRE(exuberantfac != nullptr);
0191
0192 REQUIRE(myfac->configs["x"] == "22");
0193 REQUIRE(variantfac->configs["x"] == "49");
0194 REQUIRE(exuberantfac->configs["x"] == "27");
0195 }
0196
0197 struct Cluster { double x,y,E; };
0198
0199 struct WiredOmniFac : jana::components::JOmniFactory<WiredOmniFac> {
0200 Input<Cluster> m_protoclusters_in {this};
0201 Output<Cluster> m_clusters_out {this};
0202
0203 Parameter<int> m_x {this, "x", 1, "x"};
0204 Parameter<std::string> m_y {this, "y", "silent", "y" };
0205
0206 void Configure() {
0207 }
0208
0209 void ChangeRun(int32_t ) {
0210 }
0211
0212 void Execute(int32_t , uint64_t ) {
0213
0214 for (auto protocluster : *m_protoclusters_in) {
0215 m_clusters_out().push_back(new Cluster {protocluster->x, protocluster->y, protocluster->E + 1});
0216 }
0217 }
0218 };
0219
0220 static constexpr std::string_view realfacgen_wiring = R"(
0221 [[wiring]]
0222 action = "add"
0223 type_name = "WiredOmniFac"
0224 prefix = "myfac"
0225 input_names = ["usual_input"]
0226 output_names = ["usual_output"]
0227
0228 [wiring.configs]
0229 x = "22"
0230 y = "verbose"
0231
0232 [[wiring]]
0233 action = "add"
0234 type_name = "WiredOmniFac"
0235 prefix = "myfac_modified"
0236 input_names = ["different_input"]
0237 output_names = ["different_output"]
0238
0239 [wiring.configs]
0240 x = "100"
0241 y = "silent"
0242
0243 )";
0244
0245 TEST_CASE("WiringTests_RealFacGen") {
0246
0247 JApplication app;
0248
0249 auto wiring_svc = app.GetService<jana::services::JWiringService>();
0250 toml::table table = toml::parse(realfacgen_wiring);
0251 wiring_svc->ApplyWiringSet(wiring_svc->ParseWiringSet(table));
0252
0253 auto gen = new jana::components::JWiredFactoryGeneratorT<WiredOmniFac>;
0254 app.Add(gen);
0255 app.Initialize();
0256
0257 auto& summary = app.GetComponentSummary();
0258 jout << summary;
0259 auto vf = summary.FindComponents("myfac");
0260 REQUIRE(vf.size() == 1);
0261 REQUIRE(vf.at(0)->GetOutputs().at(0)->GetName() == "usual_output");
0262
0263 auto ef = summary.FindComponents("myfac_modified");
0264 REQUIRE(ef.size() == 1);
0265 REQUIRE(ef.at(0)->GetOutputs().at(0)->GetName() == "different_output");
0266
0267
0268 REQUIRE(app.GetParameterValue<int>("myfac:x") == 22);
0269 REQUIRE(app.GetParameterValue<std::string>("myfac:y") == "verbose");
0270 REQUIRE(app.GetParameterValue<int>("myfac_modified:x") == 100);
0271 REQUIRE(app.GetParameterValue<std::string>("myfac_modified:y") == "silent");
0272
0273
0274
0275
0276
0277 }
0278
0279 struct WiredOmniFacConfig {
0280 int shared = 0;
0281 int isolated = 2;
0282 };
0283
0284 struct WiredOmniFacWithShared : jana::components::JOmniFactory<WiredOmniFacWithShared, WiredOmniFacConfig> {
0285 Input<Cluster> m_protoclusters_in {this};
0286 Output<Cluster> m_clusters_out {this};
0287
0288 ParameterRef<int> m_shared {this, "shared", config().shared, "shared", true};
0289 ParameterRef<int> m_isolated {this, "isolated", config().isolated, "isolated" };
0290
0291 void Configure() {
0292 }
0293
0294 void ChangeRun(int32_t ) {
0295 }
0296
0297 void Execute(int32_t , uint64_t ) {
0298
0299 for (auto protocluster : *m_protoclusters_in) {
0300 m_clusters_out().push_back(new Cluster {protocluster->x, protocluster->y, protocluster->E + 1});
0301 }
0302 }
0303 };
0304
0305 static constexpr std::string_view sharedparam_wiring = R"(
0306 [configs]
0307 shared = "28"
0308
0309 [[wiring]]
0310 action = "add"
0311 type_name = "WiredOmniFacWithShared"
0312 prefix = "myfac"
0313 input_names = ["usual_input"]
0314 output_names = ["usual_output"]
0315
0316 [wiring.configs]
0317 isolated = "22"
0318
0319 [[wiring]]
0320 action = "add"
0321 type_name = "WiredOmniFacWithShared"
0322 prefix = "myfac_modified"
0323 input_names = ["different_input"]
0324 output_names = ["different_output"]
0325
0326 [wiring.configs]
0327 isolated = "100"
0328 )";
0329
0330 TEST_CASE("WiringTests_SharedParam") {
0331
0332 JApplication app;
0333
0334 auto wiring_svc = app.GetService<jana::services::JWiringService>();
0335 toml::table table = toml::parse(sharedparam_wiring);
0336 wiring_svc->ApplyWiringSet(wiring_svc->ParseWiringSet(table));
0337
0338 auto gen = new jana::components::JWiredFactoryGeneratorT<WiredOmniFacWithShared>;
0339 app.Add(gen);
0340 app.Initialize();
0341
0342 auto& summary = app.GetComponentSummary();
0343
0344 auto vf = summary.FindComponents("myfac");
0345 REQUIRE(vf.size() == 1);
0346 REQUIRE(vf.at(0)->GetOutputs().at(0)->GetName() == "usual_output");
0347
0348 auto ef = summary.FindComponents("myfac_modified");
0349 REQUIRE(ef.size() == 1);
0350 REQUIRE(ef.at(0)->GetOutputs().at(0)->GetName() == "different_output");
0351
0352
0353 REQUIRE(app.GetParameterValue<int>("shared") == 28);
0354 REQUIRE(app.GetParameterValue<int>("myfac:isolated") == 22);
0355 REQUIRE(app.GetParameterValue<int>("myfac_modified:isolated") == 100);
0356
0357
0358
0359
0360
0361 }
0362
0363
0364 class WiredEvtProc : public JEventProcessor {
0365
0366 Parameter<int> m_x {this, "x", 22};
0367 Input<Cluster> m_cluster_in {this};
0368
0369
0370
0371 public:
0372
0373 WiredEvtProc() {
0374 SetTypeName("WiredEvtProc");
0375 SetPrefix("myproc");
0376 SetCallbackStyle(CallbackStyle::ExpertMode);
0377 }
0378
0379 void Init() override {
0380 REQUIRE(*m_x == 99);
0381 }
0382
0383 void ProcessSequential(const JEvent&) override {
0384
0385
0386 REQUIRE(GetPrefix() == "myproc");
0387 REQUIRE(m_cluster_in.GetDatabundleName() == "myclusters");
0388
0389
0390 REQUIRE(m_cluster_in->size() == 1);
0391 }
0392 };
0393
0394 static constexpr std::string_view evtproc_wiring = R"(
0395 [[wiring]]
0396 action = "update"
0397 type_name = "WiredEvtProc"
0398 prefix = "myproc"
0399 input_names = ["myclusters"]
0400
0401 [wiring.configs]
0402 x = "99"
0403 )";
0404
0405 TEST_CASE("WiringTests_Proc") {
0406
0407 JApplication app;
0408
0409 auto wiring_svc = app.GetService<jana::services::JWiringService>();
0410 toml::table table = toml::parse(evtproc_wiring);
0411 wiring_svc->ApplyWiringSet(wiring_svc->ParseWiringSet(table));
0412
0413 auto proc = new WiredEvtProc;
0414 app.Add(proc);
0415
0416 app.Initialize();
0417 auto event = std::make_shared<JEvent>(&app);
0418 std::vector<Cluster*> test_data;
0419 test_data.push_back(new Cluster{0, 0, 22.2});
0420 event->Insert<Cluster>(test_data, "myclusters");
0421
0422 proc->DoInit();
0423 proc->DoMap(*event);
0424 proc->DoTap(*event);
0425 }
0426
0427
0428 struct WiredFac : public JFactory {
0429 Input<Cluster> m_protoclusters_in {this};
0430 Output<Cluster> m_clusters_out {this};
0431
0432 Parameter<int> m_x {this, "x", 1, "x"};
0433
0434 WiredFac() {
0435 SetPrefix("wiredfac");
0436 m_protoclusters_in.SetDatabundleName("default_protos");
0437 m_clusters_out.SetUniqueName("default_clusters");
0438 }
0439 void Process(const JEvent&) {
0440 for (auto protocluster : *m_protoclusters_in) {
0441 m_clusters_out().push_back(new Cluster {protocluster->x, protocluster->y, protocluster->E + *m_x});
0442 }
0443 }
0444 };
0445
0446 static constexpr std::string_view facgen_wiring = R"(
0447 [[wiring]]
0448 action = "update"
0449 type_name = "WiredFac"
0450 prefix = "wiredfac"
0451 input_names = ["usual_input"]
0452 output_names = ["usual_output"]
0453
0454 [wiring.configs]
0455 x = "22"
0456 )";
0457
0458 TEST_CASE("WiringTests_FacGen") {
0459
0460 JApplication app;
0461
0462 auto wiring_svc = app.GetService<jana::services::JWiringService>();
0463 toml::table table = toml::parse(facgen_wiring);
0464 wiring_svc->ApplyWiringSet(wiring_svc->ParseWiringSet(table));
0465
0466 auto gen = new JFactoryGeneratorT<WiredFac>;
0467 app.Add(gen);
0468 app.Initialize();
0469
0470 auto& summary = app.GetComponentSummary();
0471 jout << summary;
0472 auto vf = summary.FindComponents("wiredfac");
0473 REQUIRE(vf.size() == 1);
0474 REQUIRE(vf.at(0)->GetOutputs().at(0)->GetName() == "usual_output");
0475
0476 REQUIRE(app.GetParameterValue<int>("wiredfac:x") == 22);
0477
0478 auto event = std::make_shared<JEvent>(&app);
0479 std::vector<Cluster*> test_data;
0480 test_data.push_back(new Cluster{0, 0, 22.2});
0481 event->Insert<Cluster>(test_data, "usual_input");
0482
0483 auto results = event->Get<Cluster>("usual_output");
0484 REQUIRE(results.size() == 1);
0485 REQUIRE(results.at(0)->E == 44.2);
0486
0487 }
0488
0489
0490 static constexpr std::string_view facgen_shortnames_true = R"(
0491 use_short_names = true
0492
0493 [[wiring]]
0494 action = "update"
0495 type_name = "WiredFac"
0496 prefix = "wiredfac"
0497 input_names = ["usual_input"]
0498 output_names = ["usual_output"]
0499
0500 [wiring.configs]
0501 x = "22"
0502 )";
0503
0504 TEST_CASE("WiringTests_FacGenShortnames") {
0505
0506 JApplication app;
0507
0508 auto wiring_svc = app.GetService<jana::services::JWiringService>();
0509 toml::table table = toml::parse(facgen_shortnames_true);
0510 wiring_svc->ApplyWiringSet(wiring_svc->ParseWiringSet(table));
0511
0512 REQUIRE(wiring_svc->AreShortNamesUsed() == true);
0513
0514 auto gen = new JFactoryGeneratorT<WiredFac>;
0515 app.Add(gen);
0516 app.Initialize();
0517
0518 auto event = std::make_shared<JEvent>(&app);
0519 std::vector<Cluster*> test_data;
0520 test_data.push_back(new Cluster{0, 0, 22.2});
0521 event->Insert<Cluster>(test_data, "usual_input");
0522
0523 auto results = event->Get<Cluster>("usual_output");
0524 REQUIRE(results.size() == 1);
0525 REQUIRE(results.at(0)->E == 44.2);
0526
0527 }
0528
0529
0530 static constexpr std::string_view facgen_partial_input_names_only = R"(
0531 [[wiring]]
0532 action = "update"
0533 type_name = "WiredFac"
0534 prefix = "wiredfac"
0535 input_names = ["overridden_input"]
0536 )";
0537
0538 TEST_CASE("WiringTests_Partial_InputNamesOnly") {
0539
0540 JApplication app;
0541
0542 auto wiring_svc = app.GetService<jana::services::JWiringService>();
0543 toml::table table = toml::parse(facgen_partial_input_names_only);
0544 wiring_svc->ApplyWiringSet(wiring_svc->ParseWiringSet(table));
0545
0546 auto gen = new JFactoryGeneratorT<WiredFac>;
0547 app.Add(gen);
0548 app.Initialize();
0549
0550 auto event = std::make_shared<JEvent>(&app);
0551 std::vector<Cluster*> test_data;
0552 test_data.push_back(new Cluster{0, 0, 22.2});
0553 event->Insert<Cluster>(test_data, "overridden_input");
0554
0555 auto results = event->Get<Cluster>("default_clusters");
0556 REQUIRE(results.size() == 1);
0557 REQUIRE(results.at(0)->E == 23.2);
0558
0559 }
0560
0561 static constexpr std::string_view facgen_partial_output_names_only = R"(
0562 [[wiring]]
0563 action = "update"
0564 type_name = "WiredFac"
0565 prefix = "wiredfac"
0566 output_names = ["overridden_output"]
0567 )";
0568
0569 TEST_CASE("WiringTests_Partial_OutputNamesOnly") {
0570
0571 JApplication app;
0572
0573 auto wiring_svc = app.GetService<jana::services::JWiringService>();
0574 toml::table table = toml::parse(facgen_partial_output_names_only);
0575 wiring_svc->ApplyWiringSet(wiring_svc->ParseWiringSet(table));
0576
0577 auto gen = new JFactoryGeneratorT<WiredFac>;
0578 app.Add(gen);
0579 app.Initialize();
0580
0581 auto event = std::make_shared<JEvent>(&app);
0582 std::vector<Cluster*> test_data;
0583 test_data.push_back(new Cluster{0, 0, 22.2});
0584 event->Insert<Cluster>(test_data, "default_protos");
0585
0586 auto results = event->Get<Cluster>("overridden_output");
0587 REQUIRE(results.size() == 1);
0588 REQUIRE(results.at(0)->E == 23.2);
0589
0590 }