From fb700fe09d3ae21aee9bfbbce321f3d2459ec471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Kozaryna?= Date: Sat, 27 Jan 2024 00:17:08 +0100 Subject: [PATCH] iox-eclipse-iceoryx#2157 Add tests and incorporate suggestions from review --- doc/design/chunk_header.md | 8 +- .../release-notes/iceoryx-unreleased.md | 30 +--- .../iceoryx_posh/mepoo/chunk_settings.hpp | 7 +- .../iceoryx_posh/mepoo/mepoo_config.hpp | 8 +- .../roudi/introspection_types.hpp | 2 +- .../roudi_env/minimal_roudi_config.hpp | 2 +- iceoryx_posh/source/mepoo/chunk_settings.cpp | 39 ++++- iceoryx_posh/source/mepoo/mem_pool.cpp | 6 +- iceoryx_posh/source/mepoo/memory_manager.cpp | 4 +- iceoryx_posh/source/mepoo/mepoo_config.cpp | 4 +- .../integrationtests/test_client_server.cpp | 155 ++++++++++++++++++ ...est_publisher_subscriber_communication.cpp | 62 +++++++ .../moduletests/test_mepoo_chunk_settings.cpp | 49 ++++++ .../test/moduletests/test_mepoo_mempool.cpp | 2 +- .../moduletests/test_popo_chunk_sender.cpp | 2 +- .../moduletests/test_popo_client_port.cpp | 2 +- .../moduletests/test_popo_publisher_port.cpp | 4 +- .../test_popo_server_port_common.hpp | 2 +- 18 files changed, 328 insertions(+), 60 deletions(-) diff --git a/doc/design/chunk_header.md b/doc/design/chunk_header.md index 63564be1e9..3de914bf28 100644 --- a/doc/design/chunk_header.md +++ b/doc/design/chunk_header.md @@ -43,26 +43,26 @@ Framing with terminology ``` class ChunkHeader { - uint32_t chunkSize; + uint32_t userHeaderSize{0U}; uint8_t chunkHeaderVersion; uint8_t reserved{0}; uint16_t userHeaderId; popo::UniquePortId originId; // underlying type = uint64_t uint64_t sequenceNumber; - uint32_t userHeaderSize{0U}; + uint64_t chunkSize; uint32_t userPayloadSize{0U}; uint32_t userPayloadAlignment{1U}; UserPayloadOffset_t userPayloadOffset; // alias to uint32_t }; ``` -- **chunkSize** is the size of the whole chunk +- **userHeaderSize** is the size of the chunk occupied by the user-header - **chunkHeaderVersion** is used to detect incompatibilities for record&replay functionality - **reserved** is currently not used and set to `0` - **userHeaderId** is currently not used and set to `NO_USER_HEADER` - **originId** is the unique identifier of the publisher the chunk was sent from - **sequenceNumber** is a serial number for the sent chunks -- **userHeaderSize** is the size of the chunk occupied by the user-header +- **chunkSize** is the size of the whole chunk - **userPayloadSize** is the size of the chunk occupied by the user-payload - **userPayloadAlignment** is the alignment of the chunk occupied by the user-payload - **userPayloadOffset** is the offset of the user-payload relative to the begin of the chunk diff --git a/doc/website/release-notes/iceoryx-unreleased.md b/doc/website/release-notes/iceoryx-unreleased.md index c915a97314..ae2ce776bf 100644 --- a/doc/website/release-notes/iceoryx-unreleased.md +++ b/doc/website/release-notes/iceoryx-unreleased.md @@ -1293,30 +1293,8 @@ iox::concurrent::MpmcLockFreeQueue q; ``` -59. Payload Size for Memory Chunks is now `uin64_t`. Therefore the `ChunkHeader` layout changes: +59. Payload Size for Memory Chunks is now `uin64_t`. + Hence the `ChunkHeader` (iceoryx_posh/mepoo/chunk_header.hpp) layout changes + and `m_chunkHeaderVersion` is getting increased. + Moreover many functions' signatures are also affected by this change. - ```cpp - // before - uint32_t m_chunkSize; - uint8_t m_chunkHeaderVersion; - uint8_t m_reserved; - uint16_t m_userHeaderId; - popo::UniquePortId m_originId; - uint64_t m_sequenceNumber; - uint32_t m_userHeaderSize; - uint64_t m_userPayloadSize; - uint32_t m_userPayloadAlignment; - UserPayloadOffset_t m_userPayloadOffset; - - // after - uint32_t m_userHeaderSize; - uint8_t m_chunkHeaderVersion; - uint8_t m_reserved; - uint16_t m_userHeaderId; - popo::UniquePortId m_originId; - uint64_t m_sequenceNumber; - uint64_t m_chunkSize; - uint64_t m_userPayloadSize; - uint32_t m_userPayloadAlignment; - UserPayloadOffset_t m_userPayloadOffset; - ``` diff --git a/iceoryx_posh/include/iceoryx_posh/mepoo/chunk_settings.hpp b/iceoryx_posh/include/iceoryx_posh/mepoo/chunk_settings.hpp index df9993b468..90184fb154 100644 --- a/iceoryx_posh/include/iceoryx_posh/mepoo/chunk_settings.hpp +++ b/iceoryx_posh/include/iceoryx_posh/mepoo/chunk_settings.hpp @@ -35,6 +35,7 @@ class ChunkSettings ALIGNMENT_NOT_POWER_OF_TWO, USER_HEADER_ALIGNMENT_EXCEEDS_CHUNK_HEADER_ALIGNMENT, USER_HEADER_SIZE_NOT_MULTIPLE_OF_ITS_ALIGNMENT, + REQUIRED_CHUNK_SIZE_EXCEEDS_MAX_CHUNK_SIZE, }; /// @brief constructs and initializes a ChunkSettings @@ -76,9 +77,9 @@ class ChunkSettings const uint32_t userHeaderAlignment, const uint64_t requiredChunkSize) noexcept; - static uint64_t calculateRequiredChunkSize(const uint64_t userPayloadSize, - const uint32_t userPayloadAlignment, - const uint32_t userHeaderSize) noexcept; + static expected calculateRequiredChunkSize(const uint64_t userPayloadSize, + const uint32_t userPayloadAlignment, + const uint32_t userHeaderSize) noexcept; private: uint64_t m_userPayloadSize{0U}; diff --git a/iceoryx_posh/include/iceoryx_posh/mepoo/mepoo_config.hpp b/iceoryx_posh/include/iceoryx_posh/mepoo/mepoo_config.hpp index 422729d2d9..2a254ce160 100644 --- a/iceoryx_posh/include/iceoryx_posh/mepoo/mepoo_config.hpp +++ b/iceoryx_posh/include/iceoryx_posh/mepoo/mepoo_config.hpp @@ -35,9 +35,9 @@ struct MePooConfig struct Entry { /// @brief set the size and count of memory chunks - Entry(uint64_t f_size, uint32_t f_chunkCount) noexcept - : m_size(f_size) - , m_chunkCount(f_chunkCount) + Entry(uint64_t size, uint32_t chunkCount) noexcept + : m_size(size) + , m_chunkCount(chunkCount) { } uint64_t m_size{0}; @@ -56,7 +56,7 @@ struct MePooConfig /// @brief Function for adding new entry /// @param[in] Entry structure of mempool configuration - void addMemPool(Entry f_entry) noexcept; + void addMemPool(Entry entry) noexcept; /// @brief Function for creating default memory pools MePooConfig& setDefaults() noexcept; diff --git a/iceoryx_posh/include/iceoryx_posh/roudi/introspection_types.hpp b/iceoryx_posh/include/iceoryx_posh/roudi/introspection_types.hpp index 92978fc73b..5185bc2177 100644 --- a/iceoryx_posh/include/iceoryx_posh/roudi/introspection_types.hpp +++ b/iceoryx_posh/include/iceoryx_posh/roudi/introspection_types.hpp @@ -95,7 +95,7 @@ const capro::ServiceDescription struct PortThroughputData { uint64_t m_publisherPortID{0}; - uint32_t m_sampleSize{0}; + uint64_t m_sampleSize{0}; uint64_t m_chunkSize{0}; double m_chunksPerMinute{0}; uint64_t m_lastSendIntervalInNanoseconds{0}; diff --git a/iceoryx_posh/roudi_env/include/iceoryx_posh/roudi_env/minimal_roudi_config.hpp b/iceoryx_posh/roudi_env/include/iceoryx_posh/roudi_env/minimal_roudi_config.hpp index 7035694d32..dccebdf701 100644 --- a/iceoryx_posh/roudi_env/include/iceoryx_posh/roudi_env/minimal_roudi_config.hpp +++ b/iceoryx_posh/roudi_env/include/iceoryx_posh/roudi_env/minimal_roudi_config.hpp @@ -29,7 +29,7 @@ namespace roudi_env class MinimalRouDiConfigBuilder { /// @brief Set the payload chunk size. Default = 128 - IOX_BUILDER_PARAMETER(uint32_t, payloadChunkSize, 128) + IOX_BUILDER_PARAMETER(uint64_t, payloadChunkSize, 128) /// @brief Set the payload chunk count. Default = 10 IOX_BUILDER_PARAMETER(uint32_t, payloadChunkCount, 10) diff --git a/iceoryx_posh/source/mepoo/chunk_settings.cpp b/iceoryx_posh/source/mepoo/chunk_settings.cpp index 07a651e5d4..624e1dafd0 100644 --- a/iceoryx_posh/source/mepoo/chunk_settings.cpp +++ b/iceoryx_posh/source/mepoo/chunk_settings.cpp @@ -63,15 +63,20 @@ expected ChunkSettings::create(const uint64 return err(ChunkSettings::Error::USER_HEADER_SIZE_NOT_MULTIPLE_OF_ITS_ALIGNMENT); } - uint64_t requiredChunkSize = - calculateRequiredChunkSize(userPayloadSize, adjustedUserPayloadAlignment, userHeaderSize); + auto expectChunkSize = calculateRequiredChunkSize(userPayloadSize, adjustedUserPayloadAlignment, userHeaderSize); + if (expectChunkSize.has_error()) + { + return err(expectChunkSize.get_error()); + } + uint64_t requiredChunkSize = expectChunkSize.value(); + return ok(ChunkSettings{ userPayloadSize, adjustedUserPayloadAlignment, userHeaderSize, adjustedUserHeaderAlignment, requiredChunkSize}); } -uint64_t ChunkSettings::calculateRequiredChunkSize(const uint64_t userPayloadSize, - const uint32_t userPayloadAlignment, - const uint32_t userHeaderSize) noexcept + +expected ChunkSettings::calculateRequiredChunkSize( + const uint64_t userPayloadSize, const uint32_t userPayloadAlignment, const uint32_t userHeaderSize) noexcept { // have a look at »Required Chunk Size Calculation« in chunk_header.md for more details regarding the calculation if (userHeaderSize == 0) @@ -79,17 +84,29 @@ uint64_t ChunkSettings::calculateRequiredChunkSize(const uint64_t userPayloadSiz // the most simple case with no user-header and the user-payload adjacent to the ChunkHeader if (userPayloadAlignment <= alignof(mepoo::ChunkHeader)) { + if (userPayloadSize > std::numeric_limits::max() - sizeof(ChunkHeader)) + { + return err(ChunkSettings::Error::REQUIRED_CHUNK_SIZE_EXCEEDS_MAX_CHUNK_SIZE); + } + uint64_t requiredChunkSize = sizeof(ChunkHeader) + userPayloadSize; - return requiredChunkSize; + return ok(requiredChunkSize); } // the second most simple case with no user-header but the user-payload alignment // exceeds the ChunkHeader alignment and is therefore not necessarily adjacent uint64_t preUserPayloadAlignmentOverhang = sizeof(ChunkHeader) - alignof(ChunkHeader); + + if (userPayloadSize + > std::numeric_limits::max() - preUserPayloadAlignmentOverhang - userPayloadAlignment) + { + return err(ChunkSettings::Error::REQUIRED_CHUNK_SIZE_EXCEEDS_MAX_CHUNK_SIZE); + } + uint64_t requiredChunkSize = preUserPayloadAlignmentOverhang + userPayloadAlignment + userPayloadSize; - return requiredChunkSize; + return ok(requiredChunkSize); } // the most complex case with a user-header @@ -98,9 +115,15 @@ uint64_t ChunkSettings::calculateRequiredChunkSize(const uint64_t userPayloadSiz uint64_t headerSize = sizeof(ChunkHeader) + userHeaderSize; uint64_t preUserPayloadAlignmentOverhang = align(headerSize, ALIGNMENT_OF_USER_PAYLOAD_OFFSET_T); uint64_t maxPadding = algorithm::maxVal(SIZE_OF_USER_PAYLOAD_OFFSET_T, static_cast(userPayloadAlignment)); + + if (userPayloadSize > std::numeric_limits::max() - preUserPayloadAlignmentOverhang - maxPadding) + { + return err(ChunkSettings::Error::REQUIRED_CHUNK_SIZE_EXCEEDS_MAX_CHUNK_SIZE); + } + uint64_t requiredChunkSize = preUserPayloadAlignmentOverhang + maxPadding + userPayloadSize; - return requiredChunkSize; + return ok(requiredChunkSize); } uint64_t ChunkSettings::requiredChunkSize() const noexcept diff --git a/iceoryx_posh/source/mepoo/mem_pool.cpp b/iceoryx_posh/source/mepoo/mem_pool.cpp index dc8d689d14..0e1a3a0ad6 100644 --- a/iceoryx_posh/source/mepoo/mem_pool.cpp +++ b/iceoryx_posh/source/mepoo/mem_pool.cpp @@ -49,6 +49,7 @@ MemPool::MemPool(const greater_or_equal chunkS { if (isMultipleOfAlignment(chunkSize)) { + IOX_EXPECTS(m_chunkSize <= std::numeric_limits::max() / m_numberOfChunks); auto allocationResult = chunkMemoryAllocator.allocate(static_cast(m_numberOfChunks) * m_chunkSize, CHUNK_MEMORY_ALIGNMENT); IOX_EXPECTS(allocationResult.has_value()); @@ -63,9 +64,8 @@ MemPool::MemPool(const greater_or_equal chunkS else { IOX_LOG(FATAL, - "Chunk size must be multiple of '" << CHUNK_MEMORY_ALIGNMENT << "'! Requested size is " - << static_cast(chunkSize) << " for " - << static_cast(numberOfChunks) << " chunks!"); + "Chunk size must be multiple of '" << CHUNK_MEMORY_ALIGNMENT << "'! Requested size is " << chunkSize + << " for " << numberOfChunks << " chunks!"); errorHandler(PoshError::MEPOO__MEMPOOL_CHUNKSIZE_MUST_BE_MULTIPLE_OF_CHUNK_MEMORY_ALIGNMENT); } } diff --git a/iceoryx_posh/source/mepoo/memory_manager.cpp b/iceoryx_posh/source/mepoo/memory_manager.cpp index 076bb03e8c..509ad935eb 100644 --- a/iceoryx_posh/source/mepoo/memory_manager.cpp +++ b/iceoryx_posh/source/mepoo/memory_manager.cpp @@ -58,8 +58,8 @@ void MemoryManager::addMemPool(BumpAllocator& managementAllocator, return log; } << "These mempools must be added in an increasing chunk size ordering. The newly added MemPool [ " "ChunkSize = " - << adjustedChunkSize << ", ChunkPayloadSize = " << static_cast(chunkPayloadSize) - << ", ChunkCount = " << static_cast(numberOfChunks) << "] breaks that requirement!"); + << adjustedChunkSize << ", ChunkPayloadSize = " << chunkPayloadSize << ", ChunkCount = " << numberOfChunks + << "] breaks that requirement!"); errorHandler(iox::PoshError::MEPOO__MEMPOOL_CONFIG_MUST_BE_ORDERED_BY_INCREASING_SIZE); } diff --git a/iceoryx_posh/source/mepoo/mepoo_config.cpp b/iceoryx_posh/source/mepoo/mepoo_config.cpp index 2f6809e04e..090ee26a1d 100644 --- a/iceoryx_posh/source/mepoo/mepoo_config.cpp +++ b/iceoryx_posh/source/mepoo/mepoo_config.cpp @@ -28,11 +28,11 @@ const MePooConfig::MePooConfigContainerType* MePooConfig::getMemPoolConfig() con return &m_mempoolConfig; } -void MePooConfig::addMemPool(MePooConfig::Entry f_entry) noexcept +void MePooConfig::addMemPool(MePooConfig::Entry entry) noexcept { if (m_mempoolConfig.size() < m_mempoolConfig.capacity()) { - m_mempoolConfig.push_back(f_entry); + m_mempoolConfig.push_back(entry); } else { diff --git a/iceoryx_posh/test/integrationtests/test_client_server.cpp b/iceoryx_posh/test/integrationtests/test_client_server.cpp index 7ca80fcd78..49d99a6a60 100644 --- a/iceoryx_posh/test/integrationtests/test_client_server.cpp +++ b/iceoryx_posh/test/integrationtests/test_client_server.cpp @@ -35,6 +35,8 @@ using namespace iox::capro; using namespace iox::runtime; using namespace iox::roudi_env; +constexpr uint64_t BIG_PAYLOAD_SIZE = std::numeric_limits::max() + 105UL; + class DummyRequest { public: @@ -59,8 +61,19 @@ class DummyResponse uint64_t sum{0U}; }; +struct BigPayloadStruct +{ + uint8_t bigPayload[BIG_PAYLOAD_SIZE]{0U}; +}; + class ClientServer_test : public RouDi_GTest { + protected: + ClientServer_test(iox::RouDiConfig_t&& roudiConfig) + : RouDi_GTest(std::move(roudiConfig)) + { + } + public: ClientServer_test() : RouDi_GTest(MinimalRouDiConfigBuilder().create()) @@ -82,6 +95,25 @@ class ClientServer_test : public RouDi_GTest }; constexpr iox::units::Duration ClientServer_test::DEADLOCK_TIMEOUT; +class BigPayloadClientServer_test : public ClientServer_test +{ + public: + BigPayloadClientServer_test() + : ClientServer_test( + MinimalRouDiConfigBuilder().payloadChunkSize(BIG_PAYLOAD_SIZE + 128).payloadChunkCount(2).create()) + { + } + + void SetUp() override + { + PoshRuntime::initRuntime("together"); + deadlockWatchdog.watchAndActOnFailure([] { std::terminate(); }); + } + + static constexpr iox::units::Duration DEADLOCK_TIMEOUT{10_s}; + Watchdog deadlockWatchdog{DEADLOCK_TIMEOUT}; +}; + TEST_F(ClientServer_test, TypedApiWithMatchingOptionsWorks) { ::testing::Test::RecordProperty("TEST_ID", "a14eb330-1b7d-4243-be4d-009f9e67a232"); @@ -450,4 +482,127 @@ TEST_F(ClientServer_test, ClientTakesResponseUnblocksServerSendingResponse) EXPECT_THAT(wasResponseSent.load(), Eq(true)); } +#ifdef RUN_BIG_PAYLOAD_TESTS + +TEST_F(BigPayloadClientServer_test, TypedApiWithBigPayloadWithMatchingOptionsWorks) +{ + ::testing::Test::RecordProperty("TEST_ID", "9838d2dc-bd87-42aa-b581-a9526e35e46a"); + + constexpr int64_t SEQUENCE_ID{73}; + constexpr uint64_t START{1337}; + constexpr uint64_t END{2137}; + constexpr uint8_t SHIFT{13U}; + + Client client{sd}; + Server server{sd}; + + // send request + { + auto loanResult = client.loan(); + ASSERT_FALSE(loanResult.has_error()); + auto& request = loanResult.value(); + request.getRequestHeader().setSequenceId(SEQUENCE_ID); + for (uint64_t i = START; i < END; ++i) + { + request->bigPayload[i] = static_cast(i % 256U); + } + ASSERT_FALSE(client.send(std::move(request)).has_error()); + } + + // take request and send response + { + auto takeResult = server.take(); + ASSERT_FALSE(takeResult.has_error()); + auto& request = takeResult.value(); + + auto loanResult = server.loan(request); + ASSERT_FALSE(loanResult.has_error()); + auto& response = loanResult.value(); + for (uint64_t i = START; i < END; ++i) + { + response->bigPayload[i] = request->bigPayload[i] + SHIFT; + } + ASSERT_FALSE(server.send(std::move(response)).has_error()); + } + + // take response + { + auto takeResult = client.take(); + ASSERT_FALSE(takeResult.has_error()); + auto& response = takeResult.value(); + EXPECT_THAT(response.getResponseHeader().getSequenceId(), Eq(SEQUENCE_ID)); + for (uint64_t i = START; i < END; ++i) + { + if (response->bigPayload[i] != static_cast((i % 256U) + SHIFT)) + { + EXPECT_THAT(response->bigPayload[i], Eq(static_cast((i % 256U) + SHIFT))); + break; + } + } + } +} + +TEST_F(BigPayloadClientServer_test, UntypedApiWithBigPayloadWithMatchingOptionsWorks) +{ + ::testing::Test::RecordProperty("TEST_ID", "3c784d7f-6fe8-2137-b267-7f3e70a307f3"); + + constexpr int64_t SEQUENCE_ID{37}; + constexpr uint64_t START{1337}; + constexpr uint64_t END{2137}; + constexpr uint8_t SHIFT{13U}; + + UntypedClient client{sd}; + UntypedServer server{sd}; + + // send request + { + auto loanResult = client.loan(sizeof(BigPayloadStruct), alignof(BigPayloadStruct)); + ASSERT_FALSE(loanResult.has_error()); + auto request = static_cast(loanResult.value()); + RequestHeader::fromPayload(request)->setSequenceId(SEQUENCE_ID); + for (uint64_t i = START; i < END; ++i) + { + request->bigPayload[i] = static_cast(i % 256U); + } + ASSERT_FALSE(client.send(request).has_error()); + } + + // take request and send response + { + auto takeResult = server.take(); + ASSERT_FALSE(takeResult.has_error()); + auto request = static_cast(takeResult.value()); + + auto loanResult = + server.loan(RequestHeader::fromPayload(request), sizeof(BigPayloadStruct), alignof(BigPayloadStruct)); + ASSERT_FALSE(loanResult.has_error()); + auto response = static_cast(loanResult.value()); + for (uint64_t i = START; i < END; ++i) + { + response->bigPayload[i] = request->bigPayload[i] + SHIFT; + } + ASSERT_FALSE(server.send(response).has_error()); + server.releaseRequest(request); + } + + // take response + { + auto takeResult = client.take(); + ASSERT_FALSE(takeResult.has_error()); + auto response = static_cast(takeResult.value()); + EXPECT_THAT(ResponseHeader::fromPayload(response)->getSequenceId(), Eq(SEQUENCE_ID)); + for (uint64_t i = START; i < END; ++i) + { + if (response->bigPayload[i] != static_cast((i % 256U) + SHIFT)) + { + EXPECT_THAT(response->bigPayload[i], Eq(static_cast((i % 256U) + SHIFT))); + break; + } + } + client.releaseResponse(response); + } +} + +#endif // RUN_BIG_PAYLOAD_TESTS + } // namespace diff --git a/iceoryx_posh/test/integrationtests/test_publisher_subscriber_communication.cpp b/iceoryx_posh/test/integrationtests/test_publisher_subscriber_communication.cpp index 23bbdf5941..76d048cb2a 100644 --- a/iceoryx_posh/test/integrationtests/test_publisher_subscriber_communication.cpp +++ b/iceoryx_posh/test/integrationtests/test_publisher_subscriber_communication.cpp @@ -41,6 +41,8 @@ using namespace iox::popo; using namespace iox::roudi_env; using namespace iox::testing; +constexpr uint64_t BIG_PAYLOAD_SIZE = std::numeric_limits::max() + 105UL; + template struct ComplexDataType { @@ -48,8 +50,19 @@ struct ComplexDataType T complexType; }; +struct BigPayloadStruct +{ + uint8_t bigPayload[BIG_PAYLOAD_SIZE]; +}; + class PublisherSubscriberCommunication_test : public RouDi_GTest { + protected: + PublisherSubscriberCommunication_test(iox::RouDiConfig_t&& roudiConfig) + : RouDi_GTest(std::move(roudiConfig)) + { + } + public: PublisherSubscriberCommunication_test() : RouDi_GTest(MinimalRouDiConfigBuilder().payloadChunkSize(512).create()) @@ -134,6 +147,23 @@ class PublisherSubscriberCommunication_test : public RouDi_GTest "PublisherSubscriberCommunication", "IntegrationTest", "AllHailHypnotoad"}; }; +class PublisherSubscriberCommunicationWithBigPayload_test : public PublisherSubscriberCommunication_test +{ + public: + PublisherSubscriberCommunicationWithBigPayload_test() + : PublisherSubscriberCommunication_test( + MinimalRouDiConfigBuilder().payloadChunkSize(BIG_PAYLOAD_SIZE + 128).payloadChunkCount(2).create()) + { + } + + void SetUp() + { + runtime::PoshRuntime::initRuntime("PublisherSubscriberCommunication_test"); + m_watchdog.watchAndActOnFailure([] { std::terminate(); }); + }; + Watchdog m_watchdog{units::Duration::fromSeconds(10)}; +}; + // intentional reference to unique pointer, we do not want to pass ownership in this helper function // and at call site we already have unique pointers template @@ -713,4 +743,36 @@ TEST_F(PublisherSubscriberCommunication_test, PublisherUniqueIdMatchesReceivedSa } } +#ifdef RUN_BIG_PAYLOAD_TESTS + +TEST_F(PublisherSubscriberCommunicationWithBigPayload_test, SendingComplexDataType_BigPayloadStruct) +{ + ::testing::Test::RecordProperty("TEST_ID", "f612a4ef-5f3a-4951-8f2e-bbc28f6b1a66"); + + using Type_t = ComplexDataType; + auto publisher = createPublisher(); + auto subscriber = createSubscriber(); + + ASSERT_FALSE(publisher->loan() + .and_then([](auto& sample) { + for (uint64_t i = 4242; i < 5353; ++i) + { + sample->complexType.bigPayload[i] = static_cast(i % 256U); + } + sample.publish(); + }) + .has_error()); + + EXPECT_FALSE(subscriber->take() + .and_then([](auto& sample) { + for (uint64_t i = 4242; i < 5353; ++i) + { + EXPECT_THAT(sample->complexType.bigPayload[i], Eq(static_cast(i % 256U))); + } + }) + .has_error()); +} + +#endif + } // namespace diff --git a/iceoryx_posh/test/moduletests/test_mepoo_chunk_settings.cpp b/iceoryx_posh/test/moduletests/test_mepoo_chunk_settings.cpp index 03a772f5dc..2a4ca2f4af 100644 --- a/iceoryx_posh/test/moduletests/test_mepoo_chunk_settings.cpp +++ b/iceoryx_posh/test/moduletests/test_mepoo_chunk_settings.cpp @@ -115,6 +115,55 @@ TEST(ChunkSettings_test, CallingRequiredChunkSizeReturnsCorrectValue) // END GETTER METHOD TESTS +// BEGIN EXCEEDING CHUNK SIZE TESTS + +TEST(ChunkSettings_test, NoCustomUserPayloadAlignmentAndTooLargeUserPayload_Fails) +{ + ::testing::Test::RecordProperty("TEST_ID", "1ac315d5-fb8d-4529-b141-110fe7c7988d"); + constexpr uint64_t USER_PAYLOAD_SIZE{std::numeric_limits::max()}; + constexpr uint32_t USER_PAYLOAD_ALIGNMENT{iox::CHUNK_DEFAULT_USER_PAYLOAD_ALIGNMENT}; + constexpr uint32_t USER_HEADER_SIZE{iox::CHUNK_NO_USER_HEADER_SIZE}; + constexpr uint32_t USER_HEADER_ALIGNMENT{iox::CHUNK_NO_USER_HEADER_ALIGNMENT}; + + auto sutResult = + ChunkSettings::create(USER_PAYLOAD_SIZE, USER_PAYLOAD_ALIGNMENT, USER_HEADER_SIZE, USER_HEADER_ALIGNMENT); + + ASSERT_TRUE(sutResult.has_error()); + EXPECT_THAT(sutResult.error(), Eq(ChunkSettings::Error::REQUIRED_CHUNK_SIZE_EXCEEDS_MAX_CHUNK_SIZE)); +} + +TEST(ChunkSettings_test, CustomUserPayloadAlignmentAndTooLargeUserPayload_Fails) +{ + ::testing::Test::RecordProperty("TEST_ID", "fade135d-636f-4b06-8f5d-b33eece1175c"); + constexpr uint64_t USER_PAYLOAD_SIZE{std::numeric_limits::max()}; + constexpr uint32_t USER_PAYLOAD_ALIGNMENT{alignof(ChunkHeader) * 2}; + constexpr uint32_t USER_HEADER_SIZE{iox::CHUNK_NO_USER_HEADER_SIZE}; + constexpr uint32_t USER_HEADER_ALIGNMENT{iox::CHUNK_NO_USER_HEADER_ALIGNMENT}; + + auto sutResult = + ChunkSettings::create(USER_PAYLOAD_SIZE, USER_PAYLOAD_ALIGNMENT, USER_HEADER_SIZE, USER_HEADER_ALIGNMENT); + + ASSERT_TRUE(sutResult.has_error()); + EXPECT_THAT(sutResult.error(), Eq(ChunkSettings::Error::REQUIRED_CHUNK_SIZE_EXCEEDS_MAX_CHUNK_SIZE)); +} + +TEST(ChunkSettings_test, UserHeaderAndTooLargeUserPayload_Fails) +{ + ::testing::Test::RecordProperty("TEST_ID", "b61df037-6dae-4350-896e-9ffad96db028"); + constexpr uint64_t USER_PAYLOAD_SIZE{std::numeric_limits::max()}; + constexpr uint32_t USER_PAYLOAD_ALIGNMENT{alignof(ChunkHeader) * 2}; + constexpr uint32_t USER_HEADER_SIZE{8U}; + constexpr uint32_t USER_HEADER_ALIGNMENT{8U}; + + auto sutResult = + ChunkSettings::create(USER_PAYLOAD_SIZE, USER_PAYLOAD_ALIGNMENT, USER_HEADER_SIZE, USER_HEADER_ALIGNMENT); + + ASSERT_TRUE(sutResult.has_error()); + EXPECT_THAT(sutResult.error(), Eq(ChunkSettings::Error::REQUIRED_CHUNK_SIZE_EXCEEDS_MAX_CHUNK_SIZE)); +} + +// END EXCEEDING CHUNK SIZE TESTS + // BEGIN INVALID USER-HEADER AND USER-PAYLOAD ALIGNMENT TESTS TEST(ChunkSettings_test, UserPayloadAlignmentNotPowerOfTwo_Fails) diff --git a/iceoryx_posh/test/moduletests/test_mepoo_mempool.cpp b/iceoryx_posh/test/moduletests/test_mepoo_mempool.cpp index 2e5ca09acc..07cf283957 100644 --- a/iceoryx_posh/test/moduletests/test_mepoo_mempool.cpp +++ b/iceoryx_posh/test/moduletests/test_mepoo_mempool.cpp @@ -183,7 +183,7 @@ TEST_F(MemPool_test, MempoolCtorWhenChunkSizeIsNotAMultipleOfAlignmentReturnErro TEST_F(MemPool_test, MempoolCtorWhenChunkSizeIsSmallerThanChunkMemoryAlignmentGetsTerminated) { ::testing::Test::RecordProperty("TEST_ID", "52df897a-0847-476c-9d2f-99cb16432199"); - constexpr uint64_t CHUNK_SIZE_SMALLER_THAN_MEMORY_ALIGNMENT = iox::mepoo::MemPool::CHUNK_MEMORY_ALIGNMENT - 1U; + constexpr uint32_t CHUNK_SIZE_SMALLER_THAN_MEMORY_ALIGNMENT = iox::mepoo::MemPool::CHUNK_MEMORY_ALIGNMENT - 1U; IOX_EXPECT_FATAL_FAILURE( [&] { diff --git a/iceoryx_posh/test/moduletests/test_popo_chunk_sender.cpp b/iceoryx_posh/test/moduletests/test_popo_chunk_sender.cpp index b1d11a481d..60a1b96fb5 100644 --- a/iceoryx_posh/test/moduletests/test_popo_chunk_sender.cpp +++ b/iceoryx_posh/test/moduletests/test_popo_chunk_sender.cpp @@ -77,7 +77,7 @@ class ChunkSender_test : public Test static constexpr uint64_t HISTORY_CAPACITY = 4; static constexpr uint32_t MAX_NUMBER_QUEUES = 128; - static constexpr uint64_t USER_PAYLOAD_ALIGNMENT = iox::CHUNK_DEFAULT_USER_PAYLOAD_ALIGNMENT; + static constexpr uint32_t USER_PAYLOAD_ALIGNMENT = iox::CHUNK_DEFAULT_USER_PAYLOAD_ALIGNMENT; static constexpr uint32_t USER_HEADER_SIZE = iox::CHUNK_NO_USER_HEADER_SIZE; static constexpr uint32_t USER_HEADER_ALIGNMENT = iox::CHUNK_NO_USER_HEADER_ALIGNMENT; diff --git a/iceoryx_posh/test/moduletests/test_popo_client_port.cpp b/iceoryx_posh/test/moduletests/test_popo_client_port.cpp index 0a6ae22f95..5f6d8e7c4b 100644 --- a/iceoryx_posh/test/moduletests/test_popo_client_port.cpp +++ b/iceoryx_posh/test/moduletests/test_popo_client_port.cpp @@ -207,7 +207,7 @@ class ClientPort_test : public Test public: static constexpr uint64_t USER_PAYLOAD_SIZE{32U}; - static constexpr uint64_t USER_PAYLOAD_ALIGNMENT{8U}; + static constexpr uint32_t USER_PAYLOAD_ALIGNMENT{8U}; ServerChunkQueueData_t serverChunkQueueData{iox::popo::QueueFullPolicy::DISCARD_OLDEST_DATA, iox::popo::VariantQueueTypes::SoFi_MultiProducerSingleConsumer}; diff --git a/iceoryx_posh/test/moduletests/test_popo_publisher_port.cpp b/iceoryx_posh/test/moduletests/test_popo_publisher_port.cpp index 5d21cc8e2b..f7147b0dc5 100644 --- a/iceoryx_posh/test/moduletests/test_popo_publisher_port.cpp +++ b/iceoryx_posh/test/moduletests/test_popo_publisher_port.cpp @@ -66,7 +66,7 @@ class PublisherPort_test : public Test static constexpr uint64_t SMALL_CHUNK = 128; static constexpr uint64_t BIG_CHUNK = 256; - static constexpr uint64_t USER_PAYLOAD_ALIGNMENT = iox::CHUNK_DEFAULT_USER_PAYLOAD_ALIGNMENT; + static constexpr uint32_t USER_PAYLOAD_ALIGNMENT = iox::CHUNK_DEFAULT_USER_PAYLOAD_ALIGNMENT; static constexpr uint32_t USER_HEADER_SIZE = iox::CHUNK_NO_USER_HEADER_SIZE; static constexpr uint32_t USER_HEADER_ALIGNMENT = iox::CHUNK_NO_USER_HEADER_ALIGNMENT; @@ -262,7 +262,7 @@ TEST_F(PublisherPort_test, allocatingAChunkWithLargeUserHeaderResultsInLargeChun { ::testing::Test::RecordProperty("TEST_ID", "598e04d8-8a37-43ef-b686-64e7b2723ffe"); constexpr uint64_t USER_PAYLOAD_SIZE{SMALL_CHUNK / 2}; - constexpr uint64_t LARGE_USER_HEADER_SIZE{SMALL_CHUNK}; + constexpr uint32_t LARGE_USER_HEADER_SIZE{SMALL_CHUNK}; auto maybeChunkHeader = m_sutNoOfferOnCreateUserSide.tryAllocateChunk( USER_PAYLOAD_SIZE, USER_PAYLOAD_ALIGNMENT, LARGE_USER_HEADER_SIZE, USER_HEADER_ALIGNMENT); diff --git a/iceoryx_posh/test/moduletests/test_popo_server_port_common.hpp b/iceoryx_posh/test/moduletests/test_popo_server_port_common.hpp index bff704510b..c18536534c 100644 --- a/iceoryx_posh/test/moduletests/test_popo_server_port_common.hpp +++ b/iceoryx_posh/test/moduletests/test_popo_server_port_common.hpp @@ -223,7 +223,7 @@ class ServerPort_test : public Test public: static constexpr uint64_t USER_PAYLOAD_SIZE{32U}; - static constexpr uint64_t USER_PAYLOAD_ALIGNMENT{8U}; + static constexpr uint32_t USER_PAYLOAD_ALIGNMENT{8U}; ClientChunkQueueData_t clientChunkQueueData{iox::popo::QueueFullPolicy::DISCARD_OLDEST_DATA, iox::popo::VariantQueueTypes::SoFi_MultiProducerSingleConsumer};