File indexing completed on 2025-01-18 09:12:56
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/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* , 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
0159
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
0181
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
0213
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* ) {
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
0240
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
0258 BOOST_CHECK_EQUAL(destructorCalled, false);
0259
0260 {
0261 BOOST_CHECK_EQUAL(destructorCalled, false);
0262 Delegate<int(), void, DelegateType::Owning> d;
0263
0264
0265 BOOST_CHECK_EQUAL(destructorCalled, false);
0266
0267
0268
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
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
0283
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
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
0315
0316 BOOST_CHECK_EQUAL(destructorCalled, false);
0317
0318
0319
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
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
0364 {
0365 Delegate<std::string(), void> d;
0366 ConcreteDelegate c;
0367 d.connect<&ConcreteDelegate::func>(&c);
0368 BOOST_CHECK_EQUAL(d(), "derived");
0369
0370
0371
0372 }
0373 {
0374 Delegate<std::string(), void> d;
0375 ConcreteDelegate c;
0376 d.connect<&DelegateInterface::func>(&c);
0377 BOOST_CHECK_EQUAL(
0378 d(), "derived");
0379
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
0451
0452 (void)d;
0453 (void)c;
0454 }
0455
0456 { OwningDelegate<std::string(), DelegateInterface> d; }
0457 }
0458
0459 BOOST_AUTO_TEST_SUITE_END()