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