File indexing completed on 2025-10-27 07:57:17
0001
0002
0003
0004
0005
0006
0007
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* , 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
0161
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
0183
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
0215
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* ) {
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
0242
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
0260 BOOST_CHECK_EQUAL(destructorCalled, false);
0261
0262 {
0263 BOOST_CHECK_EQUAL(destructorCalled, false);
0264 Delegate<int(), void, DelegateType::Owning> d;
0265
0266
0267 BOOST_CHECK_EQUAL(destructorCalled, false);
0268
0269
0270
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
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
0285
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
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
0317
0318 BOOST_CHECK_EQUAL(destructorCalled, false);
0319
0320
0321
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
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
0366 {
0367 Delegate<std::string(), void> d;
0368 ConcreteDelegate c;
0369 d.connect<&ConcreteDelegate::func>(&c);
0370 BOOST_CHECK_EQUAL(d(), "derived");
0371
0372
0373
0374 }
0375 {
0376 Delegate<std::string(), void> d;
0377 ConcreteDelegate c;
0378 d.connect<&DelegateInterface::func>(&c);
0379 BOOST_CHECK_EQUAL(
0380 d(), "derived");
0381
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
0453
0454 (void)d;
0455 (void)c;
0456 }
0457
0458 { OwningDelegate<std::string(), DelegateInterface> d; }
0459 }
0460
0461 BOOST_AUTO_TEST_SUITE_END()
0462
0463 }