9#include "catch2/catch_test_macros.hpp"
17#include "podio/podioVersion.h"
25#include "datamodel/EventInfoCollection.h"
26#include "datamodel/ExampleClusterCollection.h"
27#include "datamodel/ExampleForCyclicDependency1Collection.h"
28#include "datamodel/ExampleForCyclicDependency2Collection.h"
29#include "datamodel/ExampleHitCollection.h"
30#include "datamodel/ExampleWithOneRelationCollection.h"
31#include "datamodel/ExampleWithUserInitCollection.h"
32#include "datamodel/ExampleWithVectorMemberCollection.h"
33#include "datamodel/MutableExampleWithComponent.h"
36TEST_CASE(
"AutoDelete",
"[basics][memory-management]") {
38 auto hit1 = MutableEventInfo();
39 auto hit2 = MutableEventInfo();
40 auto hit3 = MutableEventInfo();
41 auto& coll = store.create<EventInfoCollection>(
"info");
49 auto& collection = store.create<ExampleHitCollection>(
"name");
50 auto hit1 = collection.create(0xcaffeeULL, 0., 0., 0., 0.);
51 auto hit2 = collection.create();
54 const ExampleHitCollection* coll2(
nullptr);
55 REQUIRE(store.get(
"name", coll2));
56 const ExampleHitCollection* coll3(
nullptr);
57 REQUIRE_FALSE(store.get(
"wrongName", coll3));
60TEST_CASE(
"Assignment-operator ref count",
"[basics][memory-management]") {
64 std::map<int, ExampleHit> hitMap;
65 for (
int i = 0; i < 10; ++i) {
66 auto hit = ExampleHit(0x42ULL, i, i, i, i);
71 for (
int i = 0; i < 10; ++i) {
72 const auto hit = hitMap[i];
73 REQUIRE(hit.energy() == i);
77TEST_CASE(
"Clearing",
"[ASAN-FAIL][THREAD-FAIL][basics][memory-management]") {
80 auto& hits = store.create<ExampleHitCollection>(
"hits");
81 auto& clusters = store.create<ExampleClusterCollection>(
"clusters");
82 auto& oneRels = store.create<ExampleWithOneRelationCollection>(
"OneRelation");
83 auto nevents = unsigned(1000);
84 for (
unsigned i = 0; i < nevents; ++i) {
87 auto hit1 = hits.create();
88 auto hit2 = ExampleHit();
89 hit1.energy(
double(i));
90 auto cluster = clusters.create();
91 cluster.addHits(hit1);
92 cluster.addHits(hit2);
94 auto oneRel = MutableExampleWithOneRelation();
95 oneRel.cluster(cluster);
96 oneRel.cluster(cluster);
97 oneRels.push_back(oneRel);
100 if (hits.size() != 0) {
108 auto hit = MutableExampleHit();
110 auto hit2 = hit.clone();
112 if (hit.energy() == hit2.energy()) {
115 auto cluster = MutableExampleCluster();
116 cluster.addHits(hit);
117 auto cluster2 = cluster.clone();
118 cluster.addHits(hit2);
120 auto const_hit = ExampleHit();
121 auto const_hit_clone = const_hit.clone();
122 const_hit_clone.energy(30);
127 auto info = MutableExampleWithComponent();
128 info.component().data.x = 3;
129 REQUIRE(3 == info.component().data.x);
132TEST_CASE(
"Cyclic",
"[LEAK-FAIL][basics][relations][memory-management]") {
133 auto start = MutableExampleForCyclicDependency1();
134 auto isAvailable = start.ref().isAvailable();
135 REQUIRE_FALSE(isAvailable);
136 auto end = MutableExampleForCyclicDependency2();
138 isAvailable = start.ref().isAvailable();
139 REQUIRE(isAvailable);
141 REQUIRE(start == end.ref());
142 auto end_eq = start.ref();
143 auto start_eq = end_eq.ref();
144 REQUIRE(start == start_eq);
145 REQUIRE(start == start.ref().ref());
148TEST_CASE(
"Invalid_refs",
"[LEAK-FAIL][basics][relations]") {
150 auto& hits = store.create<ExampleHitCollection>(
"hits");
151 auto hit1 = hits.create(0xcaffeeULL, 0., 0., 0., 0.);
152 auto hit2 = ExampleHit();
153 auto& clusters = store.create<ExampleClusterCollection>(
"clusters");
154 auto cluster = clusters.create();
155 cluster.addHits(hit1);
156 cluster.addHits(hit2);
157 REQUIRE_THROWS_AS(clusters.prepareForWrite(), std::runtime_error);
162 auto& coll = store.create<ExampleHitCollection>(
"name");
163 auto hit1 = coll.create(0xbadULL, 0., 0., 0., 0.);
164 auto hit2 = coll.create(0xcaffeeULL, 1., 1., 1., 1.);
165 for (
auto&& i : coll) {
169 REQUIRE(hit1.energy() == 42);
170 REQUIRE(hit2.energy() == 42);
172 for (
int i = 0, end = coll.size(); i != end; ++i) {
176 REQUIRE(coll[0].energy() == 0);
177 REQUIRE(coll[1].energy() == 1);
179 auto& constColl = store.get<ExampleHitCollection>(
"name");
181 for (
auto hit : constColl) {
182 auto energy = hit.energy();
183 REQUIRE(energy == index++);
189 auto& hits = store.create<ExampleHitCollection>(
"hits");
190 for (
unsigned i = 0; i < 12; ++i) {
191 auto hit = hits.create(0xcaffeeULL, 0., 0., 0.,
double(i));
195 auto energies = hits.energy(10);
196 REQUIRE(energies.size() == 10);
198 for (
auto energy : energies) {
199 REQUIRE(
double(index) == energy);
204 REQUIRE(hits.energy(24).size() == hits.size());
205 REQUIRE(hits.energy().size() == hits.size());
210 auto cluster = ExampleCluster();
211 auto rel = MutableExampleWithOneRelation();
212 rel.cluster(cluster);
218 STATIC_REQUIRE(std::is_standard_layout_v<ExampleClusterData>);
219 STATIC_REQUIRE(std::is_trivially_copyable_v<ExampleClusterData>);
220 STATIC_REQUIRE(std::is_standard_layout_v<ExampleHitData>);
221 STATIC_REQUIRE(std::is_trivially_copyable_v<ExampleHitData>);
222 STATIC_REQUIRE(std::is_standard_layout_v<ExampleWithOneRelationData>);
224 STATIC_REQUIRE(std::is_trivially_copyable_v<ExampleWithOneRelationData>);
230 auto& hits = store.create<ExampleHitCollection>(
"hits");
231 auto hit1 = hits.create(0x42ULL, 0., 0., 0., 0.);
232 auto hit2 = hits.create(0x42ULL, 1., 1., 1., 1.);
233 auto& clusters = store.create<ExampleClusterCollection>(
"clusters");
234 auto cluster = clusters.create();
235 cluster.addHits(hit1);
236 cluster.addHits(hit2);
238 for (
auto i = cluster.Hits_begin(), end = cluster.Hits_end(); i != end; ++i) {
239 REQUIRE(i->energy() == index);
247 auto& clusters = store.create<ExampleClusterCollection>(
"clusters");
249 auto variadic_cluster = clusters.create(3.14f);
250 auto normal_cluster = clusters.create();
251 normal_cluster.energy(42);
253 variadic_cluster.addClusters(normal_cluster);
254 REQUIRE(variadic_cluster.Clusters_size() == 1);
255 REQUIRE(variadic_cluster.Clusters(0) == normal_cluster);
260 auto& coll = store.create<ExampleHitCollection>(
"data");
261 auto hit1 = coll.create(0x42ULL, 0., 0., 0., 0.);
262 auto hit2 = coll.create(0x42ULL, 1., 1., 1., 1.);
263 auto& clusters = store.create<ExampleClusterCollection>(
"clusters");
264 auto cluster = clusters.create();
266 cluster.addHits(hit1);
267 cluster.addHits(hit2);
269 REQUIRE_NOTHROW(clusters.prepareForWrite());
270 auto buffers = clusters.getBuffers();
271 REQUIRE(buffers.dataAsVector<ExampleClusterData>()->size() == clusters.size());
274 REQUIRE_NOTHROW(clusters.prepareForWrite());
275 REQUIRE(clusters.getBuffers().data == buffers.data);
277 auto& ref_coll = store.create<ExampleWithOneRelationCollection>(
"onerel");
278 auto withRef = ref_coll.create();
279 REQUIRE_NOTHROW(ref_coll.prepareForWrite());
282TEST_CASE(
"thread-safe prepareForWrite",
"[basics][multithread]") {
284 constexpr auto nElements = 100u;
285 ExampleHitCollection hits{};
287 for (
size_t i = 0; i < nElements; ++i) {
288 hits.create(i, i * 0.5, i * 1.5, i * 2.5, 3.14);
292 constexpr int nThreads = 10;
293 std::vector<std::thread> threads{};
294 threads.reserve(nThreads);
296 for (
int i = 0; i < nThreads; ++i) {
297 threads.emplace_back([&hits, &userInts]() {
298 hits.prepareForWrite();
299 userInts.prepareForWrite();
303 for (
auto& t : threads) {
308 auto buffers = hits.getBuffers();
309 auto* dataVec = buffers.dataAsVector<ExampleHitData>();
310 REQUIRE(dataVec->size() == nElements);
312 auto intBuffers = userInts.getBuffers();
313 auto* intVec = intBuffers.dataAsVector<std::uint64_t>();
314 REQUIRE(intVec->size() == nElements);
317 for (
const auto& h : *dataVec) {
318 REQUIRE(h.energy == 3.14);
319 REQUIRE(h.cellID == i);
320 REQUIRE(h.x == i * 0.5);
321 REQUIRE(h.y == i * 1.5);
322 REQUIRE(h.z == i * 2.5);
324 REQUIRE((*intVec)[i] == i);
339 auto ev = MutableEventInfo();
341 REQUIRE(ev.getNumber() == 42);
343 int ia[3] = {1, 2, 3};
344 auto simple = SimpleStruct(ia);
345 REQUIRE(simple.x == 1);
346 REQUIRE(simple.y == 2);
347 REQUIRE(simple.z == 3);
351 auto clu1 = ExampleCluster();
352 auto clu2 = ExampleCluster();
353 auto clu3 = ExampleCluster();
354 auto clu4 = ExampleCluster();
355 auto clu5 = ExampleCluster();
357 std::set<ExampleCluster> cSet;
369 REQUIRE(cSet.size() == 5);
371 std::map<ExampleCluster, int> cMap;
378 REQUIRE(cMap[clu3] == 3);
382 REQUIRE(cMap[clu3] == 42);
386 auto cluster = ExampleCluster();
387 auto rel = MutableExampleWithOneRelation();
388 rel.cluster(cluster);
389 auto returned_cluster = rel.cluster();
390 REQUIRE(cluster == returned_cluster);
391 REQUIRE(returned_cluster == cluster);
395 ExampleWithUserInitCollection coll;
397 auto elem = coll.create();
398 REQUIRE(elem.i16Val() == 42);
399 REQUIRE(elem.floats()[0] == 3.14f);
400 REQUIRE(elem.floats()[1] == 1.23f);
401 REQUIRE(elem.s().x == 10);
402 REQUIRE(elem.s().y == 11);
403 REQUIRE(elem.d() == 9.876e5);
404 REQUIRE(elem.comp().i == 42);
405 REQUIRE(elem.comp().arr[0] == 1.2);
406 REQUIRE(elem.comp().arr[1] == 3.4);
409 auto ex = ExampleWithUserInit{};
410 REQUIRE(ex.i16Val() == 42);
411 REQUIRE(ex.floats()[0] == 3.14f);
412 REQUIRE(ex.floats()[1] == 1.23f);
413 REQUIRE(ex.s().x == 10);
414 REQUIRE(ex.s().y == 11);
415 REQUIRE(ex.d() == 9.876e5);
416 REQUIRE(ex.comp().i == 42);
417 REQUIRE(ex.comp().arr[0] == 1.2);
418 REQUIRE(ex.comp().arr[1] == 3.4);
421TEST_CASE(
"NonPresentCollection",
"[basics][event-store]") {
423 REQUIRE_THROWS_AS(store.get<ExampleHitCollection>(
"NonPresentCollection"), std::runtime_error);
426TEST_CASE(
"const correct indexed access to const collections",
"[const-correctness]") {
427 STATIC_REQUIRE(std::is_same_v<
decltype(std::declval<const ExampleClusterCollection>()[0]),
430 STATIC_REQUIRE(std::is_same_v<
decltype(std::declval<const ExampleClusterCollection>().at(0)),
435TEST_CASE(
"const correct indexed access to collections",
"[const-correctness]") {
437 auto& collection = store.create<ExampleHitCollection>(
"irrelevant name");
439 STATIC_REQUIRE(std::is_same_v<
decltype(collection), ExampleHitCollection&>);
442 STATIC_REQUIRE(std::is_same_v<
decltype(collection[0]), MutableExampleHit>);
445 STATIC_REQUIRE(std::is_same_v<
decltype(std::declval<ExampleClusterCollection>()[0]),
446 MutableExampleCluster>);
448 STATIC_REQUIRE(std::is_same_v<
decltype(std::declval<ExampleClusterCollection>().at(0)),
449 MutableExampleCluster>);
452TEST_CASE(
"const correct iterators on const collections",
"[const-correctness]") {
453 const auto collection = ExampleHitCollection();
456 for (
auto hit : collection) {
457 STATIC_REQUIRE(std::is_same_v<
decltype(hit), ExampleHit>);
463 STATIC_REQUIRE(std::is_same_v<
decltype(std::declval<const ExampleHitCollection>().begin()),
464 ExampleHitCollectionIterator>);
467 STATIC_REQUIRE(std::is_same_v<
decltype(std::declval<const ExampleHitCollection>().end()),
468 ExampleHitCollectionIterator>);
471 STATIC_REQUIRE(std::is_same_v<
decltype(*std::declval<const ExampleHitCollection>().begin()),
474 STATIC_REQUIRE(std::is_same_v<
decltype(std::declval<ExampleHitCollectionIterator>().operator->()),
478TEST_CASE(
"const correct iterators on collections",
"[const-correctness]") {
479 auto collection = ExampleClusterCollection();
480 for (
auto cluster : collection) {
481 STATIC_REQUIRE(std::is_same_v<
decltype(cluster), MutableExampleCluster>);
487 STATIC_REQUIRE(std::is_same_v<
decltype(std::declval<ExampleClusterCollection>().end()),
488 ExampleClusterMutableCollectionIterator>);
491 STATIC_REQUIRE(std::is_same_v<
decltype(std::declval<ExampleClusterCollection>().end()),
492 ExampleClusterMutableCollectionIterator>);
495 STATIC_REQUIRE(std::is_same_v<
decltype(std::declval<ExampleClusterCollection>().end()),
496 ExampleClusterMutableCollectionIterator>);
499 STATIC_REQUIRE(std::is_same_v<
decltype(*std::declval<ExampleClusterCollection>().begin()),
500 MutableExampleCluster>);
503 STATIC_REQUIRE(std::is_same_v<
decltype(std::declval<ExampleClusterMutableCollectionIterator>().operator->()),
504 MutableExampleCluster*>);
508TEST_CASE(
"Subset collection basics",
"[subset-colls]") {
509 auto clusterRefs = ExampleClusterCollection();
510 clusterRefs.setSubsetCollection();
513 REQUIRE(clusterRefs.isSubsetCollection());
514 const auto refCollBuffers = clusterRefs.getBuffers();
515 REQUIRE(refCollBuffers.data ==
nullptr);
516 REQUIRE(refCollBuffers.vectorMembers->empty());
517 REQUIRE(refCollBuffers.references->size() == 1u);
520TEST_CASE(
"Subset collection can handle subsets",
"[subset-colls]") {
522 auto clusters = ExampleClusterCollection();
523 auto cluster = clusters.create();
525 auto clusterRefs = ExampleClusterCollection();
526 clusterRefs.setSubsetCollection();
527 clusterRefs.push_back(cluster);
529 auto clusterRef = clusterRefs[0];
530 STATIC_REQUIRE(std::is_same_v<
decltype(clusterRef),
decltype(cluster)>);
534 REQUIRE(clusterRef == cluster);
538 REQUIRE(clusterRef.energy() == 42);
540 clusterRef.energy(-42);
541 REQUIRE(cluster.energy() == -42);
544 for (
auto c : clusters) {
545 REQUIRE(c.getObjectID().collectionID == 42);
550 clusterRefs.setID(314);
551 REQUIRE(clusterRefs.getID() == 314);
552 for (
auto c : clusterRefs) {
553 REQUIRE(c.getObjectID().collectionID == 42);
557TEST_CASE(
"Collection iterators work with subset collections",
"[LEAK-FAIL][subset-colls]") {
558 auto hits = ExampleHitCollection();
559 auto hit1 = hits.create(0x42ULL, 0., 0., 0., 0.);
560 auto hit2 = hits.create(0x42ULL, 1., 1., 1., 1.);
562 auto hitRefs = ExampleHitCollection();
563 hitRefs.setSubsetCollection();
564 for (
const auto h : hits) {
565 hitRefs.push_back(h);
569 for (
size_t i = 0; i < hitRefs.size(); ++i) {
570 REQUIRE(hitRefs[i].energy() == i);
575 for (
const auto h : hitRefs) {
576 REQUIRE(h.energy() == index++);
580TEST_CASE(
"Canont convert a normal collection into a subset collection",
"[subset-colls]") {
581 auto clusterRefs = ExampleClusterCollection();
582 auto cluster = clusterRefs.create();
584 REQUIRE_THROWS_AS(clusterRefs.setSubsetCollection(), std::logic_error);
587TEST_CASE(
"Cannot convert a subset collection into a normal collection",
"[subset-colls]") {
588 auto clusterRefs = ExampleClusterCollection();
589 clusterRefs.setSubsetCollection();
591 auto clusters = ExampleClusterCollection();
592 auto cluster = clusters.create();
593 clusterRefs.push_back(cluster);
595 REQUIRE_THROWS_AS(clusterRefs.setSubsetCollection(
false), std::logic_error);
598TEST_CASE(
"Subset collection only handles tracked objects",
"[subset-colls]") {
599 auto clusterRefs = ExampleClusterCollection();
600 clusterRefs.setSubsetCollection();
601 auto cluster = ExampleCluster();
603 REQUIRE_THROWS_AS(clusterRefs.push_back(cluster), std::invalid_argument);
604 REQUIRE_THROWS_AS(clusterRefs.create(), std::logic_error);
609 auto colls = std::make_tuple(ExampleHitCollection(), ExampleClusterCollection(), ExampleWithVectorMemberCollection(),
611 auto& [hitColl, clusterColl, vecMemColl, userDataColl] = colls;
613 for (
auto i = 0u; i < nElements; ++i) {
614 auto hit = hitColl.create();
616 hit.energy(100.f * i);
617 auto cluster = clusterColl.create();
619 cluster.addHits(hit);
621 auto vecMem = vecMemColl.create();
623 vecMem.addcount(42 + i);
625 userDataColl.push_back(3.14f * i);
628 vecMemColl.prepareForWrite();
629 auto buffers = vecMemColl.getBuffers();
630 auto vecBuffers = buffers.vectorMembers;
631 auto thisVec = (*vecBuffers)[0].second;
634 const auto floatVec2 = podio::CollectionReadBuffers::asVector<float>(thisVec);
637 std::cout <<
"** " << floatVec2->size() <<
" vs " << vecMemColl.size() <<
'\n';
644 ExampleWithVectorMemberCollection& vectors,
647 REQUIRE(hits.size() == nElements);
648 REQUIRE(clusters.size() == nElements);
649 REQUIRE(vectors.size() == nElements);
650 REQUIRE(userData.
size() == nElements);
653 for (
auto cluster : clusters) {
654 REQUIRE(cluster.Hits(0) == hits[i++]);
658 for (
const auto vec : vectors) {
659 const auto counts = vec.count();
660 REQUIRE(counts.size() == 2);
661 REQUIRE(counts[0] == i);
662 REQUIRE(counts[1] == i + 42);
667 for (
const auto v : userData) {
668 REQUIRE(v == 3.14f * i++);
672 hits.prepareForWrite();
673 auto hitBuffers = hits.getBuffers();
674 if (!hits.isSubsetCollection()) {
675 auto* hitPODBuffers = hitBuffers.dataAsVector<ExampleHitData>();
676 REQUIRE(hitPODBuffers->size() == nElements);
677 for (
size_t iHit = 0; iHit < nElements; ++iHit) {
678 const auto& hitPOD = (*hitPODBuffers)[iHit];
679 REQUIRE(hitPOD.cellID ==
static_cast<unsigned long long>(iHit));
680 REQUIRE(hitPOD.energy == 100.f * iHit);
684 clusters.prepareForWrite();
685 auto clusterBuffers = clusters.getBuffers();
686 auto* clusterRelationBuffers = clusterBuffers.references;
688 if (!clusters.isSubsetCollection()) {
689 REQUIRE(clusterRelationBuffers->size() == 2);
690 const auto& hitRelationBuffer = (*clusterRelationBuffers)[0];
691 REQUIRE(hitRelationBuffer->size() == nElements * 1);
692 for (
size_t iHit = 0; iHit < nElements * 1; ++iHit) {
693 const auto& hitID = (*hitRelationBuffer)[iHit];
694 REQUIRE(hitID.index == (
int)iHit);
695 REQUIRE(
static_cast<unsigned>(hitID.collectionID) == hits.getID());
699 vectors.prepareForWrite();
700 auto vecMemBuffers = vectors.getBuffers();
701 if (!vectors.isSubsetCollection()) {
702 auto* vecMemVecBuffers = vecMemBuffers.vectorMembers;
703 REQUIRE(vecMemVecBuffers->size() == 1);
705 const auto* countBuffer = *
static_cast<std::vector<int>**
>((*vecMemVecBuffers)[0].second);
706 REQUIRE(countBuffer->size() == nElements * 2);
707 for (
int iC = 0; iC < (int)nElements; ++iC) {
708 REQUIRE((*countBuffer)[iC * 2] == iC);
709 REQUIRE((*countBuffer)[iC * 2 + 1] == 42 + iC);
717TEST_CASE(
"Move-only collections",
"[collections][move-semantics]") {
724 SECTION(
"Move constructor") {
726 auto newHits = std::move(hitColl);
727 auto newClusters = std::move(clusterColl);
728 auto newVecMems = std::move(vecMemColl);
729 auto newUserData = std::move(userDataColl);
734 SECTION(
"Move assignment") {
736 auto newHits = ExampleHitCollection();
737 newHits = std::move(hitColl);
739 auto newClusters = ExampleClusterCollection();
740 newClusters = std::move(clusterColl);
742 auto newVecMems = ExampleWithVectorMemberCollection();
743 newVecMems = std::move(vecMemColl);
746 newUserData = std::move(userDataColl);
751 SECTION(
"Prepared collections can be move constructed") {
752 hitColl.prepareForWrite();
753 auto newHits = std::move(hitColl);
755 clusterColl.prepareForWrite();
756 auto newClusters = std::move(clusterColl);
758 vecMemColl.prepareForWrite();
759 auto buffers = vecMemColl.getBuffers();
760 auto vecBuffers = buffers.vectorMembers;
761 auto thisVec = (*vecBuffers)[0].second;
763 const auto floatVec = podio::CollectionWriteBuffers::asVector<float>(thisVec);
764 const auto floatVec2 = podio::CollectionReadBuffers::asVector<float>(thisVec);
766 std::cout << floatVec->size() <<
'\n';
767 std::cout << floatVec2->size() <<
'\n';
773 auto newVecMems = std::move(vecMemColl);
775 userDataColl.prepareForWrite();
776 auto newUserData = std::move(userDataColl);
781 SECTION(
"Moved collections can be prepared") {
784 SECTION(
"Prepared collections can be move assigned") {
785 hitColl.prepareForWrite();
786 clusterColl.prepareForWrite();
787 vecMemColl.prepareForWrite();
789 auto newHits = ExampleHitCollection();
790 newHits = std::move(hitColl);
792 auto newClusters = ExampleClusterCollection();
793 newClusters = std::move(clusterColl);
795 auto newVecMems = ExampleWithVectorMemberCollection();
796 newVecMems = std::move(vecMemColl);
799 newUserData = std::move(userDataColl);
804 SECTION(
"Subset collections can be moved") {
806 auto subsetHits = ExampleHitCollection();
807 subsetHits.setSubsetCollection();
808 for (
auto hit : hitColl) {
809 subsetHits.push_back(hit);
813 auto newSubsetHits = std::move(subsetHits);
814 REQUIRE(newSubsetHits.isSubsetCollection());
817 auto subsetClusters = ExampleClusterCollection();
818 subsetClusters.setSubsetCollection();
819 for (
auto cluster : clusterColl) {
820 subsetClusters.push_back(cluster);
825 auto newSubsetClusters = ExampleClusterCollection();
826 newSubsetClusters = std::move(subsetClusters);
827 REQUIRE(newSubsetClusters.isSubsetCollection());
828 checkCollections(newSubsetHits, newSubsetClusters, vecMemColl, userDataColl);
830 auto subsetVecs = ExampleWithVectorMemberCollection();
831 subsetVecs.setSubsetCollection();
832 for (
auto vec : vecMemColl) {
833 subsetVecs.push_back(vec);
835 checkCollections(newSubsetHits, newSubsetClusters, subsetVecs, userDataColl);
837 auto newSubsetVecs = std::move(subsetVecs);
838 REQUIRE(newSubsetVecs.isSubsetCollection());
850 constexpr Version ver_1_1{1, 1};
851 constexpr Version ver_2_1{2, 1};
852 constexpr Version ver_1_1_1{1, 1, 1};
853 constexpr Version ver_1_0_2{1, 0, 2};
854 constexpr Version ver_2_0_2{2, 0, 2};
856 SECTION(
"Equality") {
857 STATIC_REQUIRE(ver_1 ==
Version{1, 0, 0});
858 STATIC_REQUIRE(ver_1 != ver_2);
859 STATIC_REQUIRE(ver_1_1_1 ==
Version{1, 1, 1});
860 STATIC_REQUIRE(ver_2_1 != ver_1_1);
861 STATIC_REQUIRE(ver_1_0_2 != ver_2_0_2);
864 SECTION(
"Major version") {
865 STATIC_REQUIRE(ver_1 < ver_2);
866 STATIC_REQUIRE(
Version{3} > ver_2);
869 SECTION(
"Minor version") {
870 STATIC_REQUIRE(ver_1 < ver_1_1);
871 STATIC_REQUIRE(ver_2_1 > ver_2);
872 STATIC_REQUIRE(ver_1_1 < ver_2);
875 SECTION(
"Patch version") {
876 STATIC_REQUIRE(ver_1 < ver_1_0_2);
877 STATIC_REQUIRE(ver_1 < ver_1_1_1);
878 STATIC_REQUIRE(ver_1_1_1 > ver_1_1);
879 STATIC_REQUIRE(ver_2_0_2 < ver_2_1);
883TEST_CASE(
"Preprocessor version tests",
"[versioning]") {
884 SECTION(
"Basic functionality") {
888#if PODIO_BUILD_VERSION == PODIO_VERSION(podio_VERSION_MAJOR, podio_VERSION_MINOR, podio_VERSION_PATCH)
889 STATIC_REQUIRE(
true);
891 STATIC_REQUIRE(
false);
907 SECTION(
"Comparing") {
930 REQUIRE(gp.getValue<
int>(
"anInt") == 42);
932 gp.setValue(
"anInt", -42);
933 REQUIRE(gp.getValue<
int>(
"anInt") == -42);
936 gp.setValue(
"aString",
"const char initialized");
937 REQUIRE(gp.getValue<std::string>(
"aString") ==
"const char initialized");
939 gp.setValue(
"aStringVec", {
"init",
"from",
"const",
"chars"});
940 const auto& stringVec = gp.getValue<std::vector<std::string>>(
"aStringVec");
941 REQUIRE(stringVec.size() == 4);
942 REQUIRE(stringVec[0] ==
"init");
943 REQUIRE(stringVec[3] ==
"chars");
946 gp.setValue(
"double", 1.234);
947 gp.setValue(
"manyDoubles", {1.23, 4.56, 7.89});
948 REQUIRE(gp.getValue<
double>(
"double") == 1.234);
949 const auto& storedDoubles = gp.getValue<std::vector<double>>(
"manyDoubles");
950 REQUIRE(storedDoubles.size() == 3);
951 REQUIRE(storedDoubles[0] == 1.23);
952 REQUIRE(storedDoubles[1] == 4.56);
953 REQUIRE(storedDoubles[2] == 7.89);
956 gp.setValue(
"manyInts", {1, 2, 3, 4});
957 const auto& ints = gp.getValue<std::vector<int>>(
"manyInts");
958 REQUIRE(ints.size() == 4);
959 for (
int i = 0; i < 4; ++i) {
960 REQUIRE(ints[i] == i + 1);
963 auto floats = std::vector<float>{3.14f, 2.718f};
965 gp.setValue(
"someFloats", floats);
967 floats.push_back(42.f);
968 REQUIRE(floats.size() == 3);
970 const auto& storedFloats = gp.getValue<std::vector<float>>(
"someFloats");
971 REQUIRE(storedFloats.size() == 2);
972 REQUIRE(storedFloats[0] == 3.14f);
973 REQUIRE(storedFloats[1] == 2.718f);
977 gp.setValue(
"someFloats", 12.34f);
978 REQUIRE(gp.getValue<
float>(
"someFloats") == 12.34f);
981 REQUIRE(gp.getValue<
int>(
"MissingValue") ==
int{});
982 REQUIRE(gp.getValue<
float>(
"MissingValue") ==
float{});
983 REQUIRE(gp.getValue<std::string>(
"MissingValue") == std::string{});
987 REQUIRE(gp.getValue<std::vector<int>>(
"MissingValue").empty());
988 REQUIRE(gp.getValue<std::vector<float>>(
"MissingValue").empty());
989 REQUIRE(gp.getValue<std::vector<std::string>>(
"MissingValue").empty());
992TEST_CASE(
"GenericParameters constructors",
"[generic-parameters]") {
996 originalParams.setValue(
"ints", {1, 2});
997 originalParams.setValue(
"float", 3.14f);
998 originalParams.setValue(
"double", 2 * 3.14);
999 originalParams.setValue(
"strings", {
"one",
"two",
"three"});
1001 SECTION(
"Copy constructor") {
1002 auto copiedParams = originalParams;
1003 REQUIRE(copiedParams.getValue<
int>(
"int") == 42);
1004 REQUIRE(copiedParams.getValue<std::vector<int>>(
"ints")[1] == 2);
1005 REQUIRE(copiedParams.getValue<
float>(
"float") == 3.14f);
1006 REQUIRE(copiedParams.getValue<
double>(
"double") == 2 * 3.14);
1007 REQUIRE(copiedParams.getValue<std::vector<std::string>>(
"strings")[0] ==
"one");
1010 copiedParams.setValue(
"anotherDouble", 1.2345);
1011 REQUIRE(originalParams.getValue<
double>(
"anotherDouble") ==
double{});
1014 SECTION(
"Move constructor") {
1015 auto copiedParams = std::move(originalParams);
1016 REQUIRE(copiedParams.getValue<
int>(
"int") == 42);
1017 REQUIRE(copiedParams.getValue<std::vector<int>>(
"ints")[1] == 2);
1018 REQUIRE(copiedParams.getValue<
float>(
"float") == 3.14f);
1019 REQUIRE(copiedParams.getValue<
double>(
"double") == 2 * 3.14);
1020 REQUIRE(copiedParams.getValue<std::vector<std::string>>(
"strings")[0] ==
"one");
1023 SECTION(
"Move assignment") {
1025 copiedParams = std::move(originalParams);
1026 REQUIRE(copiedParams.getValue<
int>(
"int") == 42);
1027 REQUIRE(copiedParams.getValue<std::vector<int>>(
"ints")[1] == 2);
1028 REQUIRE(copiedParams.getValue<
float>(
"float") == 3.14f);
1029 REQUIRE(copiedParams.getValue<
double>(
"double") == 2 * 3.14);
1030 REQUIRE(copiedParams.getValue<std::vector<std::string>>(
"strings")[0] ==
"one");
1036template <
typename T>
1037using GPGetValue =
decltype(std::declval<podio::GenericParameters>().getValue<T>(std::declval<std::string>()));
1039TEST_CASE(
"GenericParameters return types",
"[generic-parameters][static-checks]") {
1043 STATIC_REQUIRE(std::is_same_v<
GPGetValue<std::vector<int>>,
const std::vector<int>&>);
1048 STATIC_REQUIRE(std::is_same_v<
GPGetValue<std::vector<std::string>>,
const std::vector<std::string>&>);
1055 REQUIRE_THROWS_AS(root_reader.openFile(
"NonExistentFile.root"), std::runtime_error);
1058 REQUIRE_THROWS_AS(root_legacy_reader.openFile(
"NonExistentFile.root"), std::runtime_error);
1061 REQUIRE_THROWS_AS(root_frame_reader.openFile(
"NonExistentFile.root"), std::runtime_error);
1064#ifdef PODIO_WITH_SIO
1065TEST_CASE(
"Missing files (SIO readers)",
"[basics]") {
1067 REQUIRE_THROWS_AS(sio_reader.openFile(
"NonExistentFile.sio"), std::runtime_error);
1070 REQUIRE_THROWS_AS(sio_legacy_reader.openFile(
"NonExistentFile.sio"), std::runtime_error);
1073 REQUIRE_THROWS_AS(sio_frame_reader.openFile(
"NonExistentFile.root"), std::runtime_error);
1077#ifdef PODIO_JSON_OUTPUT
1078 #include "nlohmann/json.hpp"
1081 const auto& [hitColl, clusterColl, vecMemColl, userDataColl] =
createCollections();
1082 const nlohmann::json json{
1083 {
"clusters", clusterColl}, {
"hits", hitColl}, {
"vectors", vecMemColl}, {
"userData", userDataColl}};
1085 REQUIRE(json[
"clusters"].size() == 3);
1088 for (
const auto& clu : json[
"clusters"]) {
1089 REQUIRE(clu[
"Hits"][0][
"index"] == i++);
1093 REQUIRE(json[
"hits"].size() == 3);
1094 for (
const auto& hit : json[
"hits"]) {
1095 REQUIRE(hit[
"cellID"] == i);
1096 REQUIRE(hit[
"energy"] == 100.f * i);
1101 REQUIRE(json[
"vectors"].size() == 3);
1102 for (
const auto& vec : json[
"vectors"]) {
1103 REQUIRE(vec[
"count"].size() == 2);
1104 REQUIRE(vec[
"count"][0] == i);
1105 REQUIRE(vec[
"count"][1] == i + 42);
1109 REQUIRE(json[
"userData"].size() == 3);
1110 for (
size_t j = 0; j < 3; ++j) {
1111 REQUIRE(json[
"userData"][j] == 3.14f * j);
void setValue(const std::string &key, T value)
Store (a copy of) the passed value under the given key.
void push_back(const BasicType &value)
size_t size() const override
number of elements in the collection
#define PODIO_MAJOR_VERSION(v)
Get the major version from a preprocessor defined version.
#define PODIO_VERSION(major, minor, patch)
Define a version to be used in podio.
#define PODIO_PATCH_VERSION(v)
Get the patch version from a preprocessor defined version.
#define PODIO_MINOR_VERSION(v)
Get the minor version from a preprocessor defined version.
#define PODIO_BUILD_VERSION
The encoded version with which podio has been built.
TEST_CASE("AutoDelete", "[basics][memory-management]")
auto createCollections(const size_t nElements=3u)
decltype(std::declval< podio::GenericParameters >().getValue< T >(std::declval< std::string >())) GPGetValue
void checkCollections(ExampleHitCollection &hits, ExampleClusterCollection &clusters, ExampleWithVectorMemberCollection &vectors, podio::UserDataCollection< float > &userData, const size_t nElements=3u)