Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-03-17 11:03:55

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