Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-04-10 08:00:12

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