// Copyright (c) 2019 by Robert Bosch GmbH. All rights reserved. // Copyright (c) 2021 - 2022 by Apex.AI Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // SPDX-License-Identifier: Apache-2.0 #include "iceoryx_hoofs/cxx/expected.hpp" #include "iceoryx_hoofs/internal/posix_wrapper/shared_memory_object.hpp" #include "iceoryx_hoofs/internal/posix_wrapper/shared_memory_object/allocator.hpp" #include "iceoryx_hoofs/platform/fcntl.hpp" #include "iceoryx_hoofs/platform/stat.hpp" #include "iceoryx_hoofs/platform/types.hpp" #include "iceoryx_hoofs/posix_wrapper/posix_access_rights.hpp" #include "iceoryx_hoofs/testing/test_definitions.hpp" #include "iceoryx_posh/internal/mepoo/memory_manager.hpp" #include "iceoryx_posh/internal/mepoo/mepoo_segment.hpp" #include "test.hpp" #include #include namespace { using namespace ::testing; using namespace iox::mepoo; using namespace iox::posix; class MePooSegment_test : public Test { public: struct SharedMemoryObject_MOCK : public DesignPattern::Creation { using createFct = std::function; SharedMemoryObject_MOCK(const SharedMemory::Name_t& name, const uint64_t memorySizeInBytes, const AccessMode accessMode, const OpenMode openMode, const void* baseAddressHint, const iox::cxx::perms permissions) : m_memorySizeInBytes(memorySizeInBytes) , m_baseAddressHint(const_cast(baseAddressHint)) { if (createVerificator) { createVerificator(name, memorySizeInBytes, accessMode, openMode, baseAddressHint, permissions); } filehandle = creat("/tmp/roudi_segment_test", S_IRWXU); m_isInitialized = true; } ~SharedMemoryObject_MOCK() { remove("/tmp/roudi_segment_test"); } iox::posix::Allocator* getAllocator() { return allocator.get(); } void finalizeAllocation() { } void* allocate(const uint64_t, const uint64_t = 0) { return nullptr; } int getFileHandle() { return filehandle; } uint64_t getSizeInBytes() const { return m_memorySizeInBytes; } void* getBaseAddress() const { return m_baseAddressHint; } uint64_t m_memorySizeInBytes{0}; void* m_baseAddressHint{nullptr}; static constexpr int MEM_SIZE = 100000; char memory[MEM_SIZE]; std::shared_ptr allocator{new iox::posix::Allocator(memory, MEM_SIZE)}; int filehandle; static createFct createVerificator; }; void SetUp(){}; void TearDown(){}; MePooConfig setupMepooConfig() { MePooConfig config; config.addMemPool({128, 100}); return config; } static constexpr uint64_t RawMemorySize{20000}; uint8_t m_rawMemory[RawMemorySize]; iox::posix::Allocator m_managementAllocator{iox::posix::Allocator(m_rawMemory, RawMemorySize)}; MePooConfig mepooConfig = setupMepooConfig(); MePooSegment sut{ mepooConfig, m_managementAllocator, PosixGroup{"iox_roudi_test1"}, PosixGroup{"iox_roudi_test2"}}; }; MePooSegment_test::SharedMemoryObject_MOCK::createFct MePooSegment_test::SharedMemoryObject_MOCK::createVerificator; TEST_F(MePooSegment_test, DISABLED_sharedMemoryFileHandleRightsAfterConstructor) { ::testing::Test::RecordProperty("TEST_ID", "4719f767-3413-46cd-8d1e-92a3ca92760e"); /// @todo } TEST_F(MePooSegment_test, ADD_TEST_WITH_ADDITIONAL_USER(SharedMemoryCreationParameter)) { ::testing::Test::RecordProperty("TEST_ID", "0fcfefd4-3a84-43a5-9805-057a60239184"); MePooSegment_test::SharedMemoryObject_MOCK::createVerificator = [](const SharedMemory::Name_t f_name, const uint64_t, const iox::posix::AccessMode f_accessMode, const iox::posix::OpenMode openMode, const void*, const iox::cxx::perms) { EXPECT_THAT(std::string(f_name), Eq(std::string("iox_roudi_test2"))); EXPECT_THAT(f_accessMode, Eq(iox::posix::AccessMode::READ_WRITE)); EXPECT_THAT(openMode, Eq(iox::posix::OpenMode::PURGE_AND_CREATE)); }; MePooSegment sut2{ mepooConfig, m_managementAllocator, PosixGroup{"iox_roudi_test1"}, PosixGroup{"iox_roudi_test2"}}; MePooSegment_test::SharedMemoryObject_MOCK::createVerificator = MePooSegment_test::SharedMemoryObject_MOCK::createFct(); } TEST_F(MePooSegment_test, ADD_TEST_WITH_ADDITIONAL_USER(GetSharedMemoryObject)) { ::testing::Test::RecordProperty("TEST_ID", "e1c12dd0-fd7d-4be3-918b-08d16a68c8e0"); uint64_t memorySizeInBytes{0}; MePooSegment_test::SharedMemoryObject_MOCK::createVerificator = [&](const SharedMemory::Name_t, const uint64_t f_memorySizeInBytes, const iox::posix::AccessMode, const iox::posix::OpenMode, const void*, const iox::cxx::perms) { memorySizeInBytes = f_memorySizeInBytes; }; MePooSegment sut2{ mepooConfig, m_managementAllocator, PosixGroup{"iox_roudi_test1"}, PosixGroup{"iox_roudi_test2"}}; MePooSegment_test::SharedMemoryObject_MOCK::createVerificator = MePooSegment_test::SharedMemoryObject_MOCK::createFct(); EXPECT_THAT(sut2.getSharedMemoryObject().getSizeInBytes(), Eq(memorySizeInBytes)); } TEST_F(MePooSegment_test, ADD_TEST_WITH_ADDITIONAL_USER(GetReaderGroup)) { ::testing::Test::RecordProperty("TEST_ID", "ad3fd360-3765-45ae-8285-fe4ae60c91ae"); EXPECT_THAT(sut.getReaderGroup(), Eq(iox::posix::PosixGroup("iox_roudi_test1"))); } TEST_F(MePooSegment_test, ADD_TEST_WITH_ADDITIONAL_USER(GetWriterGroup)) { ::testing::Test::RecordProperty("TEST_ID", "3aa34489-bd46-4e77-89d6-20e82211e1a4"); EXPECT_THAT(sut.getWriterGroup(), Eq(iox::posix::PosixGroup("iox_roudi_test2"))); } TEST_F(MePooSegment_test, ADD_TEST_WITH_ADDITIONAL_USER(GetMemoryManager)) { ::testing::Test::RecordProperty("TEST_ID", "4bc4af78-4beb-42eb-aee4-0f7cffb66411"); ASSERT_THAT(sut.getMemoryManager().getNumberOfMemPools(), Eq(1U)); auto config = sut.getMemoryManager().getMemPoolInfo(0); ASSERT_THAT(config.m_numChunks, Eq(100U)); constexpr uint32_t USER_PAYLOAD_SIZE{128U}; auto chunkSettingsResult = ChunkSettings::create(USER_PAYLOAD_SIZE, iox::CHUNK_DEFAULT_USER_PAYLOAD_ALIGNMENT); ASSERT_FALSE(chunkSettingsResult.has_error()); auto& chunkSettings = chunkSettingsResult.value(); sut.getMemoryManager() .getChunk(chunkSettings) .and_then([&](auto& chunk) { EXPECT_THAT(chunk.getChunkHeader()->userPayloadSize(), Eq(USER_PAYLOAD_SIZE)); }) .or_else([](auto& error) { FAIL() << "getChunk failed with: " << error; }); } } // namespace