File indexing completed on 2023-03-17 11:03:55
0001
0002
0003
0004
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
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
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
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
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 }
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 }
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
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 }