Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:12:56

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