Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-07-31 02:19:16

0001 /*----------------------------------------------------------------------
0002 
0003 Test program for edm::SoATuple class.
0004 Changed by Viji on 29-06-2005
0005 
0006  ----------------------------------------------------------------------*/
0007 
0008 #include <catch.hpp>
0009 #include <cassert>
0010 #include <cstdint>
0011 #include <iostream>
0012 #include <string>
0013 #include <utility>
0014 #include "FWCore/Utilities/interface/SoATuple.h"
0015 
0016 namespace {
0017   struct ConstructDestructCounter {
0018     static unsigned int s_constructorCalls;
0019     static unsigned int s_destructorCalls;
0020 
0021     //make sure the destructor is being called on the correct memory location
0022     void* originalThis;
0023 
0024     ConstructDestructCounter() : originalThis(this) { ++s_constructorCalls; }
0025     ConstructDestructCounter(ConstructDestructCounter const&) : originalThis(this) { ++s_constructorCalls; }
0026     ConstructDestructCounter(ConstructDestructCounter&&) : originalThis(this) { ++s_constructorCalls; }
0027     ~ConstructDestructCounter() {
0028       REQUIRE(originalThis == this);
0029       ++s_destructorCalls;
0030     }
0031   };
0032   unsigned int ConstructDestructCounter::s_constructorCalls = 0;
0033   unsigned int ConstructDestructCounter::s_destructorCalls = 0;
0034 
0035   struct CharDummy {
0036     char i;
0037     char j;
0038   };
0039 
0040   struct ComplexDummy {
0041     char* p;
0042     double f;
0043   };
0044 }  // namespace
0045 
0046 TEST_CASE("edm::SoATuple", "[SoATuple]") {
0047   SECTION("builtinTest") {
0048     edm::SoATuple<int, float, bool> s;
0049     s.reserve(3);
0050     REQUIRE(s.size() == 0);
0051 
0052     s.push_back(std::make_tuple(int{1}, float{3.2}, false));
0053     REQUIRE(s.size() == 1);
0054     REQUIRE(1 == s.get<0>(0));
0055     REQUIRE(float{3.2} == s.get<1>(0));
0056     REQUIRE(false == s.get<2>(0));
0057 
0058     s.push_back(std::make_tuple(int{2}, float{3.1415}, true));
0059     REQUIRE(s.size() == 2);
0060     REQUIRE(1 == s.get<0>(0));
0061     REQUIRE(float{3.2} == s.get<1>(0));
0062     REQUIRE(false == s.get<2>(0));
0063     REQUIRE(2 == s.get<0>(1));
0064     REQUIRE(float{3.1415} == s.get<1>(1));
0065     REQUIRE(true == s.get<2>(1));
0066 
0067     s.push_back(std::make_tuple(int{-1}, float{58.6}, true));
0068     REQUIRE(s.size() == 3);
0069     REQUIRE(1 == s.get<0>(0));
0070     REQUIRE(float{3.2} == s.get<1>(0));
0071     REQUIRE(false == s.get<2>(0));
0072     REQUIRE(2 == s.get<0>(1));
0073     REQUIRE(float{3.1415} == s.get<1>(1));
0074     REQUIRE(true == s.get<2>(1));
0075     REQUIRE(-1 == s.get<0>(2));
0076     REQUIRE(float{58.6} == s.get<1>(2));
0077     REQUIRE(true == s.get<2>(2));
0078   }
0079 
0080   SECTION("badPaddingTest") {
0081     edm::SoATuple<bool, int, double> s;
0082     s.reserve(3);
0083     REQUIRE(s.size() == 0);
0084 
0085     s.push_back(std::make_tuple(false, int{1}, double{3.2}));
0086     REQUIRE(s.size() == 1);
0087     REQUIRE(1 == s.get<1>(0));
0088     REQUIRE(double{3.2} == s.get<2>(0));
0089     REQUIRE(false == s.get<0>(0));
0090 
0091     s.push_back(std::make_tuple(true, int{2}, double{3.1415}));
0092     REQUIRE(s.size() == 2);
0093     REQUIRE(1 == s.get<1>(0));
0094     REQUIRE(double{3.2} == s.get<2>(0));
0095     REQUIRE(false == s.get<0>(0));
0096     REQUIRE(2 == s.get<1>(1));
0097     REQUIRE(double{3.1415} == s.get<2>(1));
0098     REQUIRE(true == s.get<0>(1));
0099 
0100     s.push_back(std::make_tuple(true, int{-1}, double{58.6}));
0101     REQUIRE(s.size() == 3);
0102     REQUIRE(1 == s.get<1>(0));
0103     REQUIRE(double{3.2} == s.get<2>(0));
0104     REQUIRE(false == s.get<0>(0));
0105     REQUIRE(2 == s.get<1>(1));
0106     REQUIRE(double{3.1415} == s.get<2>(1));
0107     REQUIRE(true == s.get<0>(1));
0108     REQUIRE(-1 == s.get<1>(2));
0109     REQUIRE(double{58.6} == s.get<2>(2));
0110     REQUIRE(true == s.get<0>(2));
0111   }
0112 
0113   SECTION("classTest") {
0114     ConstructDestructCounter::s_constructorCalls = 0;
0115     ConstructDestructCounter::s_destructorCalls = 0;
0116     REQUIRE(ConstructDestructCounter::s_constructorCalls == ConstructDestructCounter::s_destructorCalls);
0117     {
0118       edm::SoATuple<std::string, ConstructDestructCounter> s;
0119       s.reserve(3);
0120       const std::string kFoo{"foo"};
0121       REQUIRE(s.size() == 0);
0122       {
0123         ConstructDestructCounter dummy;
0124         s.push_back(std::make_tuple(kFoo, dummy));
0125       }
0126       REQUIRE(ConstructDestructCounter::s_constructorCalls == ConstructDestructCounter::s_destructorCalls + 1);
0127       REQUIRE(s.size() == 1);
0128       REQUIRE(kFoo == s.get<0>(0));
0129 
0130       const std::string kBar{"bar"};
0131       {
0132         ConstructDestructCounter dummy;
0133         s.push_back(std::make_tuple(kBar, dummy));
0134       }
0135       REQUIRE(ConstructDestructCounter::s_constructorCalls == ConstructDestructCounter::s_destructorCalls + 2);
0136       REQUIRE(s.size() == 2);
0137       REQUIRE(kFoo == s.get<0>(0));
0138       REQUIRE(kBar == s.get<0>(1));
0139     }
0140     REQUIRE(ConstructDestructCounter::s_constructorCalls == ConstructDestructCounter::s_destructorCalls);
0141   }
0142 
0143   SECTION("growthTest") {
0144     ConstructDestructCounter::s_constructorCalls = 0;
0145     ConstructDestructCounter::s_destructorCalls = 0;
0146     REQUIRE(ConstructDestructCounter::s_constructorCalls == ConstructDestructCounter::s_destructorCalls);
0147     {
0148       edm::SoATuple<unsigned int, ConstructDestructCounter> s;
0149       REQUIRE(s.size() == 0);
0150       REQUIRE(s.capacity() == 0);
0151       for (unsigned int i = 0; i < 100; ++i) {
0152         {
0153           ConstructDestructCounter dummy;
0154           s.push_back(std::make_tuple(i, dummy));
0155         }
0156         REQUIRE(ConstructDestructCounter::s_constructorCalls == ConstructDestructCounter::s_destructorCalls + i + 1);
0157         REQUIRE(s.size() == i + 1);
0158         REQUIRE(s.capacity() >= i + 1);
0159         for (unsigned int j = 0; j < s.size(); ++j) {
0160           REQUIRE(j == s.get<0>(j));
0161         }
0162       }
0163 
0164       s.shrink_to_fit();
0165       REQUIRE(s.capacity() == s.size());
0166       REQUIRE(ConstructDestructCounter::s_constructorCalls - ConstructDestructCounter::s_destructorCalls == s.size());
0167       for (unsigned int j = 0; j < s.size(); ++j) {
0168         REQUIRE(j == s.get<0>(j));
0169       }
0170     }
0171 
0172     REQUIRE(ConstructDestructCounter::s_constructorCalls == ConstructDestructCounter::s_destructorCalls);
0173   }
0174 
0175   SECTION("copyConstructorTest") {
0176     ConstructDestructCounter::s_constructorCalls = 0;
0177     ConstructDestructCounter::s_destructorCalls = 0;
0178     REQUIRE(ConstructDestructCounter::s_constructorCalls == ConstructDestructCounter::s_destructorCalls);
0179     {
0180       edm::SoATuple<unsigned int, ConstructDestructCounter> s;
0181       REQUIRE(s.size() == 0);
0182       REQUIRE(s.capacity() == 0);
0183       for (unsigned int i = 0; i < 100; ++i) {
0184         {
0185           ConstructDestructCounter dummy;
0186           s.push_back(std::make_tuple(i, dummy));
0187         }
0188         edm::SoATuple<unsigned int, ConstructDestructCounter> sCopy(s);
0189         REQUIRE(ConstructDestructCounter::s_constructorCalls ==
0190                 ConstructDestructCounter::s_destructorCalls + 2 * i + 2);
0191         REQUIRE(s.size() == i + 1);
0192         REQUIRE(s.capacity() >= i + 1);
0193         REQUIRE(sCopy.size() == i + 1);
0194         REQUIRE(sCopy.capacity() >= i + 1);
0195 
0196         for (unsigned int j = 0; j < s.size(); ++j) {
0197           REQUIRE(j == s.get<0>(j));
0198           REQUIRE(j == sCopy.get<0>(j));
0199         }
0200       }
0201     }
0202     REQUIRE(ConstructDestructCounter::s_constructorCalls == ConstructDestructCounter::s_destructorCalls);
0203   }
0204 
0205   SECTION("assignmentTest") {
0206     const std::vector<std::string> sValues = {"foo", "fii", "fee"};
0207     edm::SoATuple<std::string, int> s;
0208     s.reserve(sValues.size());
0209     int i = 0;
0210     for (auto const& v : sValues) {
0211       s.push_back(std::make_tuple(v, i));
0212       ++i;
0213     }
0214 
0215     edm::SoATuple<std::string, int> sAssign;
0216     sAssign.reserve(2);
0217     sAssign.push_back(std::make_tuple("barney", 10));
0218     sAssign.push_back(std::make_tuple("fred", 7));
0219     REQUIRE(sAssign.size() == 2);
0220 
0221     sAssign = s;
0222     REQUIRE(sAssign.size() == s.size());
0223     REQUIRE(sAssign.size() == sValues.size());
0224 
0225     i = 0;
0226     for (auto const& v : sValues) {
0227       REQUIRE(v == sAssign.get<0>(i));
0228       REQUIRE(i == sAssign.get<1>(i));
0229       ++i;
0230     }
0231   }
0232 
0233   SECTION("moveAssignmentTest") {
0234     const std::vector<std::string> sValues = {"foo", "fii", "fee"};
0235     edm::SoATuple<std::string, int> s;
0236     s.reserve(sValues.size());
0237     int i = 0;
0238     for (auto const& v : sValues) {
0239       s.push_back(std::make_tuple(v, i));
0240       ++i;
0241     }
0242 
0243     edm::SoATuple<std::string, int> sAssign;
0244     sAssign.reserve(2);
0245     sAssign.push_back(std::make_tuple("barney", 10));
0246     sAssign.push_back(std::make_tuple("fred", 7));
0247     REQUIRE(sAssign.size() == 2);
0248 
0249     sAssign = std::move(s);
0250     REQUIRE(0 == s.size());
0251     REQUIRE(sAssign.size() == sValues.size());
0252 
0253     i = 0;
0254     for (auto const& v : sValues) {
0255       REQUIRE(v == sAssign.get<0>(i));
0256       REQUIRE(i == sAssign.get<1>(i));
0257       ++i;
0258     }
0259   }
0260 
0261   SECTION("loopTest") {
0262     edm::SoATuple<int, int, int> s;
0263     s.reserve(50);
0264     for (int i = 0; i < 50; ++i) {
0265       s.push_back(std::make_tuple(i, i + 1, i + 2));
0266     }
0267     REQUIRE(50 == s.size());
0268     int index = 0;
0269     for (auto it = s.begin<0>(), itEnd = s.end<0>(); it != itEnd; ++it, ++index) {
0270       REQUIRE(index == *it);
0271     }
0272     index = 1;
0273     for (auto it = s.begin<1>(), itEnd = s.end<1>(); it != itEnd; ++it, ++index) {
0274       REQUIRE(index == *it);
0275     }
0276 
0277     index = 2;
0278     for (auto it = s.begin<2>(), itEnd = s.end<2>(); it != itEnd; ++it, ++index) {
0279       REQUIRE(index == *it);
0280     }
0281   }
0282 
0283   SECTION("emplace_backTest") {
0284     const std::vector<std::string> sValues = {"foo", "fii", "fee"};
0285     edm::SoATuple<std::string, int> s;
0286     s.reserve(sValues.size());
0287     int i = 0;
0288     for (auto const& v : sValues) {
0289       s.emplace_back(v, i);
0290       ++i;
0291     }
0292     i = 0;
0293     for (auto const& v : sValues) {
0294       REQUIRE(v == s.get<0>(i));
0295       REQUIRE(i == s.get<1>(i));
0296       ++i;
0297     }
0298   }
0299 
0300   SECTION("alignmentTest") {
0301     REQUIRE((alignof(double) == edm::soahelper::SoATupleHelper<2, double, bool>::max_alignment));
0302     REQUIRE((alignof(double) == edm::soahelper::SoATupleHelper<2, bool, double>::max_alignment));
0303     REQUIRE((alignof(float) == edm::soahelper::SoATupleHelper<2, float, bool>::max_alignment));
0304     REQUIRE((alignof(float) == edm::soahelper::SoATupleHelper<2, bool, float>::max_alignment));
0305     REQUIRE((alignof(CharDummy) == edm::soahelper::SoATupleHelper<2, char, CharDummy>::max_alignment));
0306     REQUIRE((alignof(CharDummy) == edm::soahelper::SoATupleHelper<2, CharDummy, char>::max_alignment));
0307     REQUIRE((alignof(ComplexDummy) == edm::soahelper::SoATupleHelper<2, char, ComplexDummy>::max_alignment));
0308     REQUIRE((alignof(ComplexDummy) == edm::soahelper::SoATupleHelper<2, ComplexDummy, char>::max_alignment));
0309 
0310     REQUIRE((alignof(float) == edm::soahelper::SoATupleHelper<2, float, float>::max_alignment));
0311     REQUIRE((16 == edm::soahelper::SoATupleHelper<2, edm::AlignedVec<float>, edm::AlignedVec<float>>::max_alignment));
0312 
0313     REQUIRE((alignof(double) == edm::soahelper::SoATupleHelper<2, double, double>::max_alignment));
0314     REQUIRE((16 == edm::soahelper::SoATupleHelper<2, edm::AlignedVec<double>, edm::AlignedVec<double>>::max_alignment));
0315 
0316     edm::SoATuple<edm::AlignedVec<float>, edm::AlignedVec<float>, edm::AlignedVec<float>> vFloats;
0317     vFloats.reserve(50);
0318     for (unsigned int i = 0; i < 50; ++i) {
0319       vFloats.emplace_back(1.0f, 2.0f, 3.0f);
0320     }
0321     REQUIRE(reinterpret_cast<std::intptr_t>(vFloats.begin<0>()) % 16 == 0);
0322     REQUIRE(reinterpret_cast<std::intptr_t>(vFloats.begin<1>()) % 16 == 0);
0323     REQUIRE(reinterpret_cast<std::intptr_t>(vFloats.begin<2>()) % 16 == 0);
0324   }
0325 }