Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-27 07:57:17

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include <boost/test/unit_test.hpp>
0010 
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Utilities/Delegate.hpp"
0013 #include "ActsTests/CommonHelpers/FloatComparisons.hpp"
0014 
0015 #include <memory>
0016 #include <string>
0017 #include <type_traits>
0018 #include <utility>
0019 #include <vector>
0020 
0021 using namespace Acts;
0022 
0023 namespace ActsTests {
0024 
0025 BOOST_AUTO_TEST_SUITE(UtilitiesSuite)
0026 
0027 int sumImpl(int a, int b) {
0028   return a + b;
0029 }
0030 
0031 BOOST_AUTO_TEST_CASE(ConnectConstexprLambda) {
0032   Delegate<int(int, int)> sum;
0033   BOOST_CHECK(!sum);
0034   BOOST_CHECK(!sum.connected());
0035 
0036   sum.connect<&sumImpl>();
0037 
0038   BOOST_CHECK_EQUAL(sum(2, 5), 7);
0039   BOOST_CHECK_NE(sum(2, 3), 7);
0040 
0041   sum.connect([](const void*, int a, int b) -> int { return a + b; });
0042 
0043   BOOST_CHECK(sum);
0044   BOOST_CHECK(sum.connected());
0045 
0046   BOOST_CHECK_EQUAL(sum(2, 5), 7);
0047   BOOST_CHECK_NE(sum(2, 3), 7);
0048 }
0049 
0050 float multiply(float a, float b) {
0051   return a * b;
0052 }
0053 
0054 BOOST_AUTO_TEST_CASE(ConnectFunctionPointer) {
0055   Delegate<float(float, float)> mult;
0056 
0057   BOOST_CHECK(!mult);
0058   BOOST_CHECK(!mult.connected());
0059 
0060   mult.connect<multiply>();
0061 
0062   BOOST_CHECK(mult);
0063   BOOST_CHECK(mult.connected());
0064 
0065   CHECK_CLOSE_REL(mult(2, 5.9), 2 * 5.9, 1e-6);
0066   BOOST_CHECK_NE(mult(2, 3.2), 58.9);
0067 }
0068 
0069 struct Subtractor {
0070   int v;
0071   int execute(int a) const { return a - v; }
0072 };
0073 
0074 BOOST_AUTO_TEST_CASE(ConnectStruct) {
0075   Delegate<int(int)> sub;
0076 
0077   BOOST_CHECK(!sub);
0078   BOOST_CHECK(!sub.connected());
0079 
0080   Subtractor s{18};
0081   sub.connect<&Subtractor::execute>(&s);
0082 
0083   BOOST_CHECK(sub);
0084   BOOST_CHECK(sub.connected());
0085 
0086   BOOST_CHECK_EQUAL(sub(7), 7 - 18);
0087 }
0088 
0089 int addition(const void* /*payload*/, int a, int b) {
0090   return a + b;
0091 }
0092 
0093 BOOST_AUTO_TEST_CASE(ConnectRuntime) {
0094   {
0095     Delegate<int(int, int)> add;
0096     BOOST_CHECK(!add);
0097     BOOST_CHECK(!add.connected());
0098 
0099     add.connect(&addition);
0100     BOOST_CHECK(add);
0101     BOOST_CHECK(add.connected());
0102 
0103     BOOST_CHECK_EQUAL(add(4, 4), 8);
0104   }
0105 
0106   {
0107     Delegate<int(int, int)> add{&addition};
0108 
0109     BOOST_CHECK(add);
0110     BOOST_CHECK(add.connected());
0111 
0112     BOOST_CHECK_EQUAL(add(4, 4), 8);
0113   }
0114 
0115   {
0116     Delegate<int(int, int)> add;
0117     BOOST_CHECK(!add);
0118     BOOST_CHECK(!add.connected());
0119 
0120     add = &addition;
0121     BOOST_CHECK(add);
0122     BOOST_CHECK(add.connected());
0123 
0124     BOOST_CHECK_EQUAL(add(4, 4), 8);
0125   }
0126 }
0127 
0128 BOOST_AUTO_TEST_CASE(ConnectConstructFuncPtr) {
0129   Delegate<int(int, int)> add{DelegateFuncTag<&sumImpl>{}};
0130   BOOST_CHECK(add);
0131   BOOST_CHECK(add.connected());
0132   BOOST_CHECK_EQUAL(add(4, 4), 8);
0133 
0134   Subtractor s{18};
0135   Delegate<int(int)> sub{DelegateFuncTag<&Subtractor::execute>{}, &s};
0136 
0137   BOOST_CHECK(sub);
0138   BOOST_CHECK(sub.connected());
0139 
0140   BOOST_CHECK_EQUAL(sub(7), 7 - 18);
0141 }
0142 
0143 void modify(int& v, int a) {
0144   v = a;
0145 }
0146 
0147 void noModify(int v, int a) {
0148   (void)v;
0149   v = a;
0150 }
0151 
0152 BOOST_AUTO_TEST_CASE(DelegateReference) {
0153   Delegate<void(int&, int)> d;
0154   d.connect<&modify>();
0155 
0156   int v = 0;
0157   d(v, 42);
0158   BOOST_CHECK_EQUAL(v, 42);
0159 
0160   // This should not compile since the signature is not exactly matched
0161   // d.connect<&noModify>();
0162 }
0163 
0164 struct SignatureTest {
0165   void modify(int& v, int a) const { v = a; }
0166 
0167   void noModify(int v, int a) const {
0168     (void)v;
0169     v = a;
0170   }
0171 };
0172 
0173 BOOST_AUTO_TEST_CASE(DelegateReferenceMember) {
0174   SignatureTest s;
0175   Delegate<void(int&, int)> d;
0176   d.connect<&SignatureTest::modify>(&s);
0177 
0178   int v = 0;
0179   d(v, 42);
0180   BOOST_CHECK_EQUAL(v, 42);
0181 
0182   // This should not compile since the signature is not exactly matched
0183   // d.connect<&SignatureTest::noModify>(&s);
0184 }
0185 
0186 BOOST_AUTO_TEST_CASE(StatefullLambdas) {
0187   std::vector<int> v;
0188 
0189   auto lambda = [&](int n) -> int {
0190     v.push_back(n);
0191     return v.size();
0192   };
0193 
0194   Delegate<int(int)> d(lambda);
0195 
0196   BOOST_CHECK(d);
0197   BOOST_CHECK(d.connected());
0198   BOOST_CHECK_EQUAL(d(2), 1);
0199 
0200   d.disconnect();
0201   d = lambda;
0202 
0203   BOOST_CHECK(d);
0204   BOOST_CHECK(d.connected());
0205   BOOST_CHECK_EQUAL(d(2), 2);
0206 
0207   d.disconnect();
0208   d.connect(lambda);
0209 
0210   BOOST_CHECK(d);
0211   BOOST_CHECK(d.connected());
0212   BOOST_CHECK_EQUAL(d(2), 3);
0213 
0214   // This should not compile because of deleted && overloads
0215   // d.connect([&](int a){ v.push_back(a); return v.size(); });
0216 }
0217 
0218 struct CheckDestructor {
0219   explicit CheckDestructor(bool* _out) : destructorCalled{_out} {}
0220 
0221   bool* destructorCalled;
0222 
0223   int func() const { return 4; }
0224 
0225   ~CheckDestructor() { (*destructorCalled) = true; }
0226 };
0227 
0228 int owningTest() {
0229   return 8;
0230 }
0231 
0232 int owningTest2(const void* /*payload*/) {
0233   return 8;
0234 }
0235 
0236 BOOST_AUTO_TEST_CASE(OwningDelegateTest) {
0237   {
0238     auto s = std::make_unique<const SignatureTest>();
0239     Delegate<void(int&, int)> d;
0240     (void)d;
0241     // This should not compile, as it would be a memory leak
0242     // d.connect<&SignatureTest::modify>(std::move(s));
0243   }
0244 
0245   {
0246     bool destructorCalled = false;
0247     auto s = std::make_unique<const CheckDestructor>(&destructorCalled);
0248     {
0249       BOOST_CHECK_EQUAL(destructorCalled, false);
0250       Delegate<int(), void, DelegateType::NonOwning> d;
0251       BOOST_CHECK_EQUAL(destructorCalled, false);
0252       d.connect<&CheckDestructor::func>(s.get());
0253       BOOST_CHECK_EQUAL(destructorCalled, false);
0254       Delegate<int(), void, DelegateType::NonOwning> dCopy{d};
0255       BOOST_CHECK_EQUAL(d(), 4);
0256       BOOST_CHECK_EQUAL(dCopy(), 4);
0257       BOOST_CHECK_EQUAL(destructorCalled, false);
0258     }
0259     // destructor not called after non-owning delegate goes out of scope
0260     BOOST_CHECK_EQUAL(destructorCalled, false);
0261 
0262     {
0263       BOOST_CHECK_EQUAL(destructorCalled, false);
0264       Delegate<int(), void, DelegateType::Owning> d;
0265       // This doesn't compile: owning delegate is not copyable
0266       // Delegate<int(), DelegateType::Owning> dCopy = d;
0267       BOOST_CHECK_EQUAL(destructorCalled, false);
0268       // This doesn't compile: owning delegate cannot accept raw pointer
0269       // instance
0270       // d.connect<&CheckDestructor::func>(s.get());
0271       d.connect<&CheckDestructor::func>(std::move(s));
0272       BOOST_CHECK_EQUAL(destructorCalled, false);
0273       BOOST_CHECK_EQUAL(d(), 4);
0274       BOOST_CHECK_EQUAL(destructorCalled, false);
0275     }
0276     // destructor called after owning delegate goes out of scope
0277     BOOST_CHECK_EQUAL(destructorCalled, true);
0278 
0279     destructorCalled = false;
0280     s = std::make_unique<const CheckDestructor>(&destructorCalled);
0281     {
0282       BOOST_CHECK_EQUAL(destructorCalled, false);
0283       OwningDelegate<int()> d;
0284       // This doesn't compile: owning delegate is not copyable
0285       // OwningDelegate<int()> dCopy = d;
0286       BOOST_CHECK_EQUAL(destructorCalled, false);
0287       d.connect<&CheckDestructor::func>(std::move(s));
0288       BOOST_CHECK_EQUAL(destructorCalled, false);
0289       BOOST_CHECK_EQUAL(d(), 4);
0290       BOOST_CHECK_EQUAL(destructorCalled, false);
0291     }
0292     // destructor called after owning delegate goes out of scope
0293     BOOST_CHECK_EQUAL(destructorCalled, true);
0294   }
0295 
0296   {
0297     bool destructorCalled = false;
0298     auto s = std::make_unique<const CheckDestructor>(&destructorCalled);
0299     {
0300       BOOST_CHECK_EQUAL(destructorCalled, false);
0301       Delegate<int(), void, DelegateType::NonOwning> d;
0302       BOOST_CHECK_EQUAL(destructorCalled, false);
0303       d.connect<&CheckDestructor::func>(s.get());
0304       Delegate<int(), void, DelegateType::NonOwning> dCopy{d};
0305       BOOST_CHECK_EQUAL(destructorCalled, false);
0306       BOOST_CHECK_EQUAL(d(), 4);
0307       BOOST_CHECK_EQUAL(dCopy(), 4);
0308       BOOST_CHECK_EQUAL(destructorCalled, false);
0309       d.disconnect();
0310       BOOST_CHECK_EQUAL(destructorCalled, false);
0311     }
0312 
0313     {
0314       BOOST_CHECK_EQUAL(destructorCalled, false);
0315       Delegate<int(), void, DelegateType::Owning> d;
0316       // This doesn't compile: owning delegate is not copyable
0317       // Delegate<int(), DelegateType::Owning> dCopy = d;
0318       BOOST_CHECK_EQUAL(destructorCalled, false);
0319       // This doesn't compile: owning delegate cannot accept raw pointer
0320       // instance
0321       // d.connect<&CheckDestructor::func>(s.get());
0322       d.connect<&CheckDestructor::func>(std::move(s));
0323       BOOST_CHECK_EQUAL(destructorCalled, false);
0324       BOOST_CHECK_EQUAL(d(), 4);
0325       BOOST_CHECK_EQUAL(destructorCalled, false);
0326       d.disconnect();
0327       BOOST_CHECK_EQUAL(destructorCalled, true);
0328     }
0329     // destructor called after owning delegate goes out of scope
0330     BOOST_CHECK_EQUAL(destructorCalled, true);
0331   }
0332 
0333   {
0334     OwningDelegate<int()> d;
0335     d.connect<&owningTest>();
0336     BOOST_CHECK_EQUAL(d(), 8);
0337 
0338     d.disconnect();
0339     d.connect<&owningTest>();
0340     BOOST_CHECK_EQUAL(d(), 8);
0341 
0342     d.disconnect();
0343     d.connect(owningTest2);
0344     BOOST_CHECK_EQUAL(d(), 8);
0345   }
0346 }
0347 
0348 struct DelegateInterface {
0349   DelegateInterface() = default;
0350   virtual ~DelegateInterface() = 0;
0351 
0352   virtual std::string func() const { return "base"; }
0353 };
0354 inline DelegateInterface::~DelegateInterface() = default;
0355 
0356 struct ConcreteDelegate : public DelegateInterface {
0357   std::string func() const final { return "derived"; }
0358 };
0359 
0360 struct SeparateDelegate {
0361   std::string func() const { return "separate"; }
0362 };
0363 
0364 BOOST_AUTO_TEST_CASE(NonVoidDelegateTest) {
0365   // check void behavior with virtuals
0366   {
0367     Delegate<std::string(), void> d;
0368     ConcreteDelegate c;
0369     d.connect<&ConcreteDelegate::func>(&c);
0370     BOOST_CHECK_EQUAL(d(), "derived");
0371 
0372     // does not compile: delegate won't hand out void pointer
0373     // d.instance();
0374   }
0375   {
0376     Delegate<std::string(), void> d;
0377     ConcreteDelegate c;
0378     d.connect<&DelegateInterface::func>(&c);
0379     BOOST_CHECK_EQUAL(
0380         d(), "derived");  // <- even if you plug in the base class member
0381                           // pointer you get the derived class call
0382   }
0383 
0384   {
0385     Delegate<std::string(), DelegateInterface> d;
0386     ConcreteDelegate c;
0387     d.connect<&ConcreteDelegate::func>(&c);
0388     BOOST_CHECK_EQUAL(d(), "derived");
0389 
0390     const auto* instance = d.instance();
0391     static_assert(
0392         std::is_same_v<
0393             std::remove_const_t<std::remove_pointer_t<decltype(instance)>>,
0394             DelegateInterface>,
0395         "Did not get correct instance pointer");
0396     BOOST_CHECK_NE(dynamic_cast<const DelegateInterface*>(instance), nullptr);
0397     BOOST_CHECK_NE(dynamic_cast<const ConcreteDelegate*>(instance), nullptr);
0398   }
0399 
0400   {
0401     Delegate<std::string(), ConcreteDelegate> d;
0402     ConcreteDelegate c;
0403     d.connect<&ConcreteDelegate::func>(&c);
0404     BOOST_CHECK_EQUAL(d(), "derived");
0405 
0406     const auto* instance = d.instance();
0407     static_assert(
0408         std::is_same_v<
0409             std::remove_const_t<std::remove_pointer_t<decltype(instance)>>,
0410             ConcreteDelegate>,
0411         "Did not get correct instance pointer");
0412     BOOST_CHECK_NE(dynamic_cast<const DelegateInterface*>(instance), nullptr);
0413     BOOST_CHECK_NE(dynamic_cast<const ConcreteDelegate*>(instance), nullptr);
0414   }
0415 
0416   {
0417     OwningDelegate<std::string(), DelegateInterface> d;
0418     d.connect<&ConcreteDelegate::func>(
0419         std::make_unique<const ConcreteDelegate>());
0420     BOOST_CHECK_EQUAL(d(), "derived");
0421 
0422     const auto* instance = d.instance();
0423     static_assert(
0424         std::is_same_v<
0425             std::remove_const_t<std::remove_pointer_t<decltype(instance)>>,
0426             DelegateInterface>,
0427         "Did not get correct instance pointer");
0428     BOOST_CHECK_NE(dynamic_cast<const DelegateInterface*>(instance), nullptr);
0429     BOOST_CHECK_NE(dynamic_cast<const ConcreteDelegate*>(instance), nullptr);
0430   }
0431 
0432   {
0433     OwningDelegate<std::string(), ConcreteDelegate> d;
0434     ConcreteDelegate c;
0435     d.connect<&ConcreteDelegate::func>(
0436         std::make_unique<const ConcreteDelegate>());
0437     BOOST_CHECK_EQUAL(d(), "derived");
0438 
0439     const auto* instance = d.instance();
0440     static_assert(
0441         std::is_same_v<
0442             std::remove_const_t<std::remove_pointer_t<decltype(instance)>>,
0443             ConcreteDelegate>,
0444         "Did not get correct instance pointer");
0445     BOOST_CHECK_NE(dynamic_cast<const DelegateInterface*>(instance), nullptr);
0446     BOOST_CHECK_NE(dynamic_cast<const ConcreteDelegate*>(instance), nullptr);
0447   }
0448 
0449   {
0450     Delegate<std::string(), DelegateInterface> d;
0451     SeparateDelegate c;
0452     // Does not compile: cannot assign unrelated type
0453     // d.connect<&SeparateDelegate::func>(&c);
0454     (void)d;
0455     (void)c;
0456   }
0457 
0458   { OwningDelegate<std::string(), DelegateInterface> d; }
0459 }
0460 
0461 BOOST_AUTO_TEST_SUITE_END()
0462 
0463 }  // namespace ActsTests