Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:25:27

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 #include <boost/test/unit_test_log.hpp>
0011 
0012 #include "Acts/Utilities/Logger.hpp"
0013 #include "ActsExamples/Framework/DataHandle.hpp"
0014 #include "ActsExamples/Framework/Sequencer.hpp"
0015 #include "ActsExamples/Framework/WhiteBoard.hpp"
0016 #include "ActsTests/CommonHelpers/WhiteBoardUtilities.hpp"
0017 
0018 using namespace Acts;
0019 using namespace ActsExamples;
0020 using Logging::ScopedFailureThreshold;
0021 
0022 // Global logger instance for all tests
0023 const Logger& logger() {
0024   static const auto logger =
0025       getDefaultLogger("DataHandleTest", Logging::VERBOSE);
0026   return *logger;
0027 }
0028 
0029 namespace ActsTests {
0030 
0031 BOOST_AUTO_TEST_SUITE(FrameworkSuite)
0032 
0033 BOOST_AUTO_TEST_CASE(BasicOperations) {
0034   WhiteBoard wb;
0035   DummySequenceElement dummyElement;
0036 
0037   BOOST_TEST_CHECKPOINT("Test adding and retrieving objects");
0038   {
0039     WriteDataHandle<int> writeHandle(&dummyElement, "test");
0040     writeHandle.initialize("test_key");
0041     writeHandle(wb, 42);
0042 
0043     ReadDataHandle<int> readHandle(&dummyElement, "test");
0044     readHandle.initialize("test_key");
0045     BOOST_CHECK_EQUAL(readHandle(wb), 42);
0046   }
0047 
0048   BOOST_TEST_CHECKPOINT("Test initialize with empty key");
0049   {
0050     WriteDataHandle<int> writeHandle(&dummyElement, "test");
0051     BOOST_CHECK_THROW(writeHandle.initialize(""), std::invalid_argument);
0052   }
0053 
0054   BOOST_TEST_CHECKPOINT("Test maybeInitialize");
0055   {
0056     WriteDataHandle<int> writeHandle(&dummyElement, "test");
0057     writeHandle.maybeInitialize("");  // Should not throw
0058     BOOST_CHECK(!writeHandle.isInitialized());
0059 
0060     writeHandle.maybeInitialize("maybe_key");  // Should initialize
0061     BOOST_CHECK(writeHandle.isInitialized());
0062     writeHandle(wb, 42);
0063 
0064     ReadDataHandle<int> readHandle(&dummyElement, "test");
0065     readHandle.maybeInitialize("maybe_key");
0066     BOOST_CHECK(readHandle.isInitialized());
0067     BOOST_CHECK_EQUAL(readHandle(wb), 42);
0068   }
0069 
0070   BOOST_TEST_CHECKPOINT("Test uninitialized handles");
0071   {
0072     WriteDataHandle<int> writeHandle(&dummyElement, "test");
0073     BOOST_CHECK_THROW(writeHandle(wb, 42), std::runtime_error);
0074 
0075     ReadDataHandle<int> readHandle(&dummyElement, "test");
0076     BOOST_CHECK_THROW(readHandle(wb), std::runtime_error);
0077   }
0078 
0079   BOOST_TEST_CHECKPOINT("Test adding duplicate objects");
0080   {
0081     WriteDataHandle<int> writeHandle(&dummyElement, "test");
0082     writeHandle.initialize("duplicate_key");
0083     writeHandle(wb, 42);
0084     BOOST_CHECK_THROW(writeHandle(wb, 43), std::invalid_argument);
0085   }
0086 
0087   BOOST_TEST_CHECKPOINT("Test getting non-existent objects");
0088   {
0089     ReadDataHandle<int> readHandle(&dummyElement, "test");
0090     readHandle.initialize("missing_key");
0091     BOOST_CHECK_THROW(readHandle(wb), std::out_of_range);
0092   }
0093 
0094   BOOST_TEST_CHECKPOINT("Test getting objects with wrong type");
0095   {
0096     WriteDataHandle<int> writeHandle(&dummyElement, "test");
0097     writeHandle.initialize("type_key");
0098     writeHandle(wb, 42);
0099 
0100     ReadDataHandle<std::string> readHandle(&dummyElement, "test");
0101     readHandle.initialize("type_key");
0102     BOOST_CHECK_THROW(readHandle(wb), std::out_of_range);
0103   }
0104 
0105   BOOST_TEST_CHECKPOINT("Test similar name suggestions");
0106   {
0107     WriteDataHandle<int> writeHandle(&dummyElement, "test");
0108     writeHandle.initialize("similar_key");
0109     writeHandle(wb, 42);
0110 
0111     ReadDataHandle<int> readHandle(&dummyElement, "test");
0112     readHandle.initialize("similr_key");  // Typo in key
0113     BOOST_CHECK_THROW(readHandle(wb), std::out_of_range);
0114   }
0115 }
0116 
0117 BOOST_AUTO_TEST_CASE(ComplexTypes) {
0118   WhiteBoard wb;
0119   DummySequenceElement dummyElement;
0120 
0121   BOOST_TEST_CHECKPOINT("Test with vector type");
0122   {
0123     std::vector<int> data = {1, 2, 3};
0124     WriteDataHandle<std::vector<int>> writeHandle(&dummyElement, "test");
0125     writeHandle.initialize("vector_key");
0126     writeHandle(wb, std::move(data));
0127 
0128     ReadDataHandle<std::vector<int>> readHandle(&dummyElement, "test");
0129     readHandle.initialize("vector_key");
0130     const auto& result = readHandle(wb);
0131     BOOST_CHECK_EQUAL(result.size(), 3);
0132     BOOST_CHECK_EQUAL(result[0], 1);
0133     BOOST_CHECK_EQUAL(result[1], 2);
0134     BOOST_CHECK_EQUAL(result[2], 3);
0135   }
0136 
0137   BOOST_TEST_CHECKPOINT("Test with string type");
0138   {
0139     std::string data = "test string";
0140     WriteDataHandle<std::string> writeHandle(&dummyElement, "test");
0141     writeHandle.initialize("string_key");
0142     writeHandle(wb, std::move(data));
0143 
0144     ReadDataHandle<std::string> readHandle(&dummyElement, "test");
0145     readHandle.initialize("string_key");
0146     BOOST_CHECK_EQUAL(readHandle(wb), "test string");
0147   }
0148 }
0149 
0150 BOOST_AUTO_TEST_CASE(DataHandleCompatibility) {
0151   WhiteBoard wb;
0152   DummySequenceElement dummyElement;
0153 
0154   BOOST_TEST_CHECKPOINT("Test write handle with same type");
0155   {
0156     WriteDataHandle<int> writeHandle1(&dummyElement, "test1");
0157     writeHandle1.initialize("same_key");
0158     writeHandle1(wb, 42);
0159 
0160     WriteDataHandle<int> writeHandle2(&dummyElement, "test2");
0161     writeHandle2.initialize("same_key");
0162     BOOST_CHECK_THROW(writeHandle2(wb, 43), std::invalid_argument);
0163   }
0164 
0165   BOOST_TEST_CHECKPOINT("Test write handle with different type");
0166   {
0167     WriteDataHandle<int> writeHandle1(&dummyElement, "test1");
0168     writeHandle1.initialize("diff_key");
0169     writeHandle1(wb, 42);
0170 
0171     WriteDataHandle<std::string> writeHandle2(&dummyElement, "test2");
0172     writeHandle2.initialize("diff_key");
0173     BOOST_CHECK_THROW(writeHandle2(wb, "test"), std::invalid_argument);
0174   }
0175 
0176   BOOST_TEST_CHECKPOINT("Test read handle with same type");
0177   {
0178     WriteDataHandle<int> writeHandle(&dummyElement, "test");
0179     writeHandle.initialize("read_key");
0180     writeHandle(wb, 42);
0181 
0182     ReadDataHandle<int> readHandle1(&dummyElement, "test1");
0183     readHandle1.initialize("read_key");
0184     BOOST_CHECK_EQUAL(readHandle1(wb), 42);
0185 
0186     ReadDataHandle<int> readHandle2(&dummyElement, "test2");
0187     readHandle2.initialize("read_key");
0188     BOOST_CHECK_EQUAL(readHandle2(wb), 42);
0189   }
0190 
0191   BOOST_TEST_CHECKPOINT("Test read handle with different type");
0192   {
0193     WriteDataHandle<int> writeHandle(&dummyElement, "test");
0194     writeHandle.initialize("type_key");
0195     writeHandle(wb, 42);
0196 
0197     ReadDataHandle<std::string> readHandle(&dummyElement, "test");
0198     readHandle.initialize("type_key");
0199     BOOST_CHECK_THROW(readHandle(wb), std::out_of_range);
0200   }
0201 }
0202 
0203 BOOST_AUTO_TEST_CASE(WhiteBoardCopy) {
0204   WhiteBoard wb1;
0205   WhiteBoard wb2;
0206   DummySequenceElement dummyElement;
0207 
0208   BOOST_TEST_CHECKPOINT("Test copying from another whiteboard");
0209   {
0210     WriteDataHandle<int> writeHandle(&dummyElement, "test");
0211     writeHandle.initialize("copy_key");
0212     writeHandle(wb1, 42);
0213 
0214     wb2.copyFrom(wb1);
0215 
0216     ReadDataHandle<int> readHandle(&dummyElement, "test");
0217     readHandle.initialize("copy_key");
0218     BOOST_CHECK_EQUAL(readHandle(wb2), 42);
0219   }
0220 
0221   BOOST_TEST_CHECKPOINT("Test copying with duplicate keys");
0222   {
0223     WriteDataHandle<int> writeHandle1(&dummyElement, "test1");
0224     writeHandle1.initialize("duplicate_key");
0225     writeHandle1(wb1, 42);
0226 
0227     WriteDataHandle<int> writeHandle2(&dummyElement, "test2");
0228     writeHandle2.initialize("duplicate_key");
0229     writeHandle2(wb2, 43);
0230 
0231     BOOST_CHECK_THROW(wb2.copyFrom(wb1), std::invalid_argument);
0232   }
0233 }
0234 
0235 BOOST_AUTO_TEST_CASE(EmulateStateConsistency) {
0236   DummySequenceElement dummyElement;
0237   DataHandleBase::StateMapType state;
0238   WhiteBoard::AliasMapType aliases;
0239   std::vector<std::unique_ptr<WriteDataHandleBase>> writeHandles;
0240   std::vector<std::unique_ptr<ReadDataHandleBase>> readHandles;
0241 
0242   BOOST_TEST_CHECKPOINT("Test write handle emulation");
0243   {
0244     auto& writeHandle = *writeHandles.emplace_back(
0245         std::make_unique<WriteDataHandle<int>>(&dummyElement, "test"));
0246     writeHandle.initialize("test_key");
0247     writeHandle.emulate(state, aliases, logger());
0248 
0249     // Verify state after write handle emulation
0250     BOOST_CHECK(state.contains("test_key"));
0251     BOOST_CHECK_EQUAL(state["test_key"], &writeHandle);
0252   }
0253 
0254   BOOST_TEST_CHECKPOINT(
0255       "Test read handle emulation with compatible write handle");
0256   {
0257     auto& readHandle = *readHandles.emplace_back(
0258         std::make_unique<ReadDataHandle<int>>(&dummyElement, "test"));
0259     readHandle.initialize("test_key");
0260     readHandle.emulate(state, aliases, logger());
0261     // Should not throw as write handle exists with same type
0262   }
0263 
0264   BOOST_TEST_CHECKPOINT(
0265       "Test read handle emulation with incompatible write handle");
0266   {
0267     state.clear();
0268     aliases.clear();
0269 
0270     auto& writeHandle = *writeHandles.emplace_back(
0271         std::make_unique<WriteDataHandle<std::string>>(&dummyElement, "test"));
0272     writeHandle.initialize("test_key");
0273     writeHandle.emulate(state, aliases, logger());
0274 
0275     auto& readHandle = *readHandles.emplace_back(
0276         std::make_unique<ReadDataHandle<int>>(&dummyElement, "test"));
0277     readHandle.initialize("test_key");
0278     ScopedFailureThreshold st(Logging::Level::FATAL);
0279     BOOST_CHECK_THROW(readHandle.emulate(state, aliases, logger()),
0280                       SequenceConfigurationException);
0281   }
0282 
0283   BOOST_TEST_CHECKPOINT("Test read handle emulation with missing write handle");
0284   {
0285     state.clear();
0286     aliases.clear();
0287     auto& readHandle = *readHandles.emplace_back(
0288         std::make_unique<ReadDataHandle<int>>(&dummyElement, "test"));
0289     readHandle.initialize("missing_key");
0290     ScopedFailureThreshold st(Logging::Level::FATAL);
0291     BOOST_CHECK_THROW(readHandle.emulate(state, aliases, logger()),
0292                       SequenceConfigurationException);
0293   }
0294 
0295   BOOST_TEST_CHECKPOINT("Test write handle emulation with duplicate key");
0296   {
0297     state.clear();
0298     aliases.clear();
0299     auto& writeHandle1 = *writeHandles.emplace_back(
0300         std::make_unique<WriteDataHandle<int>>(&dummyElement, "test1"));
0301     writeHandle1.initialize("duplicate_key");
0302     writeHandle1.emulate(state, aliases, logger());
0303 
0304     auto& writeHandle2 = *writeHandles.emplace_back(
0305         std::make_unique<WriteDataHandle<int>>(&dummyElement, "test2"));
0306     writeHandle2.initialize("duplicate_key");
0307     ScopedFailureThreshold st(Logging::Level::FATAL);
0308     BOOST_CHECK_THROW(writeHandle2.emulate(state, aliases, logger()),
0309                       SequenceConfigurationException);
0310   }
0311 
0312   BOOST_TEST_CHECKPOINT("Test alias handling");
0313   {
0314     state.clear();
0315     aliases.clear();
0316 
0317     auto& writeHandle = *writeHandles.emplace_back(
0318         std::make_unique<WriteDataHandle<int>>(&dummyElement, "test"));
0319     writeHandle.initialize("original_key");
0320     writeHandle.emulate(state, aliases, logger());
0321 
0322     // Add alias
0323     aliases.insert({"original_key", "alias_key"});
0324     state.insert({"alias_key", &writeHandle});
0325 
0326     // Verify read handle works with alias
0327     auto& readHandle = *readHandles.emplace_back(
0328         std::make_unique<ReadDataHandle<int>>(&dummyElement, "test"));
0329     readHandle.initialize("alias_key");
0330     readHandle.emulate(state, aliases, logger());
0331     // Should not throw as alias exists and points to compatible handle
0332   }
0333 }
0334 
0335 BOOST_AUTO_TEST_CASE(ConsumeDataHandleTest) {
0336   WhiteBoard wb;
0337   DummySequenceElement dummyElement;
0338 
0339   BOOST_TEST_CHECKPOINT("Test basic consume functionality");
0340   {
0341     WriteDataHandle<int> writeHandle(&dummyElement, "test");
0342     writeHandle.initialize("consume_key");
0343     writeHandle(wb, 42);
0344 
0345     ConsumeDataHandle<int> consumeHandle(&dummyElement, "test");
0346     consumeHandle.initialize("consume_key");
0347     BOOST_CHECK_EQUAL(consumeHandle(wb), 42);
0348 
0349     // Verify data is removed after consumption
0350     BOOST_CHECK(!wb.exists("consume_key"));
0351     ReadDataHandle<int> readHandle(&dummyElement, "test");
0352     readHandle.initialize("consume_key");
0353     BOOST_CHECK_THROW(readHandle(wb), std::out_of_range);
0354   }
0355 
0356   BOOST_TEST_CHECKPOINT("Test consume handle emulation");
0357   {
0358     DataHandleBase::StateMapType state;
0359     WhiteBoard::AliasMapType aliases;
0360     std::vector<std::unique_ptr<WriteDataHandleBase>> writeHandles;
0361     std::vector<std::unique_ptr<ReadDataHandleBase>> readHandles;
0362 
0363     // Add write handle to state
0364     auto& writeHandle = *writeHandles.emplace_back(
0365         std::make_unique<WriteDataHandle<int>>(&dummyElement, "test"));
0366     writeHandle.initialize("consume_key");
0367     writeHandle.emulate(state, aliases, logger());
0368 
0369     // Verify consume handle removes key from state
0370     auto& consumeHandle = *readHandles.emplace_back(
0371         std::make_unique<ConsumeDataHandle<int>>(&dummyElement, "test"));
0372     consumeHandle.initialize("consume_key");
0373     consumeHandle.emulate(state, aliases, logger());
0374     BOOST_CHECK(!state.contains("consume_key"));
0375 
0376     // Verify another consume handle fails
0377     auto& consumeHandle2 = *readHandles.emplace_back(
0378         std::make_unique<ConsumeDataHandle<int>>(&dummyElement, "test2"));
0379     consumeHandle2.initialize("consume_key");
0380     ScopedFailureThreshold st(Logging::Level::FATAL);
0381     BOOST_CHECK_THROW(consumeHandle2.emulate(state, aliases, logger()),
0382                       SequenceConfigurationException);
0383   }
0384 
0385   BOOST_TEST_CHECKPOINT("Test consume handle with incompatible type");
0386   {
0387     WriteDataHandle<std::string> writeHandle(&dummyElement, "test");
0388     writeHandle.initialize("type_key");
0389     writeHandle(wb, "test string");
0390 
0391     ConsumeDataHandle<int> consumeHandle(&dummyElement, "test");
0392     consumeHandle.initialize("type_key");
0393     BOOST_CHECK_THROW(consumeHandle(wb), std::out_of_range);
0394   }
0395 
0396   BOOST_TEST_CHECKPOINT("Test consume handle with missing data");
0397   {
0398     ConsumeDataHandle<int> consumeHandle(&dummyElement, "test");
0399     consumeHandle.initialize("missing_key");
0400     BOOST_CHECK_THROW(consumeHandle(wb), std::out_of_range);
0401   }
0402 
0403   BOOST_TEST_CHECKPOINT("Test consume handle with uninitialized key");
0404   {
0405     ConsumeDataHandle<int> consumeHandle(&dummyElement, "test");
0406     BOOST_CHECK_THROW(consumeHandle(wb), std::runtime_error);
0407   }
0408 }
0409 
0410 BOOST_AUTO_TEST_CASE(ConsumeDataHandleWithAliases) {
0411   DummySequenceElement dummyElement;
0412   DataHandleBase::StateMapType state;
0413   WhiteBoard::AliasMapType aliases;
0414   std::vector<std::unique_ptr<WriteDataHandleBase>> writeHandles;
0415   std::vector<std::unique_ptr<ReadDataHandleBase>> readHandles;
0416 
0417   BOOST_TEST_CHECKPOINT("Test consume handle emulation with aliases");
0418   {
0419     aliases.insert({"original_key", "alias_key"});
0420     // Set up write handle with original key
0421     auto& writeHandle = *writeHandles.emplace_back(
0422         std::make_unique<WriteDataHandle<int>>(&dummyElement, "test"));
0423     writeHandle.initialize("original_key");
0424     writeHandle.emulate(state, aliases, logger());
0425 
0426     // Verify initial state
0427     BOOST_CHECK(state.contains("original_key"));
0428     BOOST_CHECK(state.contains("alias_key"));
0429     BOOST_CHECK_EQUAL(state["original_key"], &writeHandle);
0430     BOOST_CHECK_EQUAL(state["alias_key"], &writeHandle);
0431 
0432     // Emulate consume handle with alias
0433     auto& consumeHandle = *readHandles.emplace_back(
0434         std::make_unique<ConsumeDataHandle<int>>(&dummyElement, "test"));
0435     consumeHandle.initialize("alias_key");
0436     consumeHandle.emulate(state, aliases, logger());
0437 
0438     // Verify both original and alias keys are removed from state
0439     BOOST_CHECK(!state.contains("original_key"));
0440     BOOST_CHECK(!state.contains("alias_key"));
0441   }
0442 
0443   BOOST_TEST_CHECKPOINT("Test consume handle emulation with original key");
0444   {
0445     state.clear();
0446     aliases.clear();
0447     aliases.insert({"original_key", "alias_key"});
0448 
0449     // Set up write handle with original key
0450     auto& writeHandle = *writeHandles.emplace_back(
0451         std::make_unique<WriteDataHandle<int>>(&dummyElement, "test"));
0452     writeHandle.initialize("original_key");
0453     writeHandle.emulate(state, aliases, logger());
0454 
0455     // Verify initial state
0456     BOOST_CHECK(state.contains("original_key"));
0457     BOOST_CHECK(state.contains("alias_key"));
0458     BOOST_CHECK_EQUAL(state["original_key"], &writeHandle);
0459     BOOST_CHECK_EQUAL(state["alias_key"], &writeHandle);
0460 
0461     // Emulate consume handle with original key
0462     auto& consumeHandle = *readHandles.emplace_back(
0463         std::make_unique<ConsumeDataHandle<int>>(&dummyElement, "test"));
0464     consumeHandle.initialize("original_key");
0465     consumeHandle.emulate(state, aliases, logger());
0466 
0467     // Verify both original and alias keys are removed from state
0468     BOOST_CHECK(!state.contains("original_key"));
0469     BOOST_CHECK(!state.contains("alias_key"));
0470   }
0471 }
0472 
0473 // Custom type with destructor counter for testing
0474 struct DestructorCounter {
0475   static int count;
0476   int value;
0477   explicit DestructorCounter(int v) : value(v) {}
0478   ~DestructorCounter() { count++; }
0479 };
0480 int DestructorCounter::count = 0;
0481 
0482 BOOST_AUTO_TEST_CASE(ConsumeDataHandleDestructor) {
0483   WhiteBoard wb;
0484   DummySequenceElement dummyElement;
0485 
0486   BOOST_TEST_CHECKPOINT("Test value destructor is not called when popping");
0487   {
0488     // Reset counter
0489     DestructorCounter::count = 0;
0490 
0491     // Write value to store
0492     WriteDataHandle<std::unique_ptr<DestructorCounter>> writeHandle(
0493         &dummyElement, "test");
0494     writeHandle.initialize("destructor_key");
0495     writeHandle(wb, std::make_unique<DestructorCounter>(42));
0496 
0497     // Verify initial state
0498     BOOST_CHECK_EQUAL(DestructorCounter::count, 0);
0499 
0500     // Consume value
0501     ConsumeDataHandle<std::unique_ptr<DestructorCounter>> consumeHandle(
0502         &dummyElement, "test");
0503     consumeHandle.initialize("destructor_key");
0504     auto value = consumeHandle(wb);
0505 
0506     // Verify value was moved correctly
0507     BOOST_CHECK_EQUAL(value->value, 42);
0508     // Verify destructor was not called during pop
0509     BOOST_CHECK_EQUAL(DestructorCounter::count, 0);
0510 
0511     // Verify value is removed from store
0512     BOOST_CHECK(!wb.exists("destructor_key"));
0513 
0514     // Value destructor will be called when unique_ptr is destroyed
0515     value.reset();
0516     BOOST_CHECK_EQUAL(DestructorCounter::count, 1);
0517   }
0518 }
0519 
0520 BOOST_AUTO_TEST_SUITE_END()
0521 
0522 }  // namespace ActsTests