// Copyright (c) 2020 - 2021 by Robert Bosch GmbH. All rights reserved. // Copyright (c) 2020 - 2021 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/convert.hpp" #include "iceoryx_hoofs/internal/units/duration.hpp" #include "iceoryx_posh/gateway/channel.hpp" #include "iceoryx_posh/gateway/gateway_config.hpp" #include "iceoryx_posh/iceoryx_posh_types.hpp" #include "test.hpp" #include "stubs/stub_gateway_generic.hpp" namespace { using namespace ::testing; using namespace iox::units::duration_literals; using ::testing::_; // ======================================== Helpers ======================================== // using iox::capro::IdString_t; // We do not need real channel terminals to test the base class. struct StubbedIceoryxTerminal { struct Options { }; StubbedIceoryxTerminal(const iox::capro::ServiceDescription&, const Options&){}; }; struct StubbedExternalTerminal { StubbedExternalTerminal(IdString_t, IdString_t, IdString_t){}; }; using TestChannel = iox::gw::Channel; using TestGatewayGeneric = iox::gw::StubbedGatewayGeneric; // ======================================== Fixture ======================================== // class GatewayGenericTest : public Test { public: void SetUp(){}; void TearDown(){}; std::unique_ptr sut{new TestGatewayGeneric{}}; }; // ======================================== Tests ======================================== // TEST_F(GatewayGenericTest, AddedChannelsAreStored) { ::testing::Test::RecordProperty("TEST_ID", "da5e4a66-4f88-48bb-a684-4d10a19684b5"); // ===== Setup auto testService = iox::capro::ServiceDescription("service", "instance", "event"); // ===== Test ASSERT_FALSE(sut->addChannel(testService, StubbedIceoryxTerminal::Options()).has_error()); EXPECT_EQ(1U, sut->getNumberOfChannels()); } TEST_F(GatewayGenericTest, DoesNotAddDuplicateChannels) { ::testing::Test::RecordProperty("TEST_ID", "fdd568b4-b377-48a3-8d2a-7f131bf1bba6"); // ===== Setup auto testService = iox::capro::ServiceDescription("service", "instance", "event"); // ===== Test ASSERT_FALSE(sut->addChannel(testService, StubbedIceoryxTerminal::Options()).has_error()); ASSERT_FALSE(sut->addChannel(testService, StubbedIceoryxTerminal::Options()).has_error()); EXPECT_EQ(1U, sut->getNumberOfChannels()); } TEST_F(GatewayGenericTest, IgnoresWildcardServices) { ::testing::Test::RecordProperty("TEST_ID", "27984b07-f100-4cc3-9092-7f8afb8adca0"); // ===== Setup auto completeWildcardService = iox::capro::ServiceDescription("*", "*", "*"); auto wildcardServiceService = iox::capro::ServiceDescription("*", "instance", "event"); auto wildcardInstanceService = iox::capro::ServiceDescription("service", "*", "event"); auto wildcardEventService = iox::capro::ServiceDescription("service", "instance", "*"); // ===== Test auto resultOne = sut->addChannel(completeWildcardService, StubbedIceoryxTerminal::Options()); auto resultTwo = sut->addChannel(wildcardServiceService, StubbedIceoryxTerminal::Options()); auto resultThree = sut->addChannel(wildcardInstanceService, StubbedIceoryxTerminal::Options()); auto resultFour = sut->addChannel(wildcardEventService, StubbedIceoryxTerminal::Options()); EXPECT_EQ(iox::gw::GatewayError::UNSUPPORTED_SERVICE_TYPE, resultOne.get_error()); EXPECT_EQ(iox::gw::GatewayError::UNSUPPORTED_SERVICE_TYPE, resultTwo.get_error()); EXPECT_EQ(iox::gw::GatewayError::UNSUPPORTED_SERVICE_TYPE, resultThree.get_error()); EXPECT_EQ(iox::gw::GatewayError::UNSUPPORTED_SERVICE_TYPE, resultFour.get_error()); EXPECT_EQ(0U, sut->getNumberOfChannels()); } TEST_F(GatewayGenericTest, ProperlyManagesMultipleChannels) { ::testing::Test::RecordProperty("TEST_ID", "d6126772-9069-47c4-b8b0-4325eecba208"); // ===== Setup auto serviceOne = iox::capro::ServiceDescription("serviceOne", "instanceOne", "eventOne"); auto serviceTwo = iox::capro::ServiceDescription("serviceTwo", "instanceTwo", "eventTwo"); auto serviceThree = iox::capro::ServiceDescription("serviceThree", "instanceThree", "eventThree"); auto serviceFour = iox::capro::ServiceDescription("serviceFour", "instanceFour", "eventFour"); // ===== Test ASSERT_FALSE(sut->addChannel(serviceOne, StubbedIceoryxTerminal::Options()).has_error()); ASSERT_FALSE(sut->addChannel(serviceTwo, StubbedIceoryxTerminal::Options()).has_error()); ASSERT_FALSE(sut->addChannel(serviceThree, StubbedIceoryxTerminal::Options()).has_error()); ASSERT_FALSE(sut->addChannel(serviceFour, StubbedIceoryxTerminal::Options()).has_error()); EXPECT_EQ(4U, sut->getNumberOfChannels()); EXPECT_EQ(true, sut->findChannel(serviceOne).has_value()); EXPECT_EQ(true, sut->findChannel(serviceTwo).has_value()); EXPECT_EQ(true, sut->findChannel(serviceThree).has_value()); EXPECT_EQ(true, sut->findChannel(serviceFour).has_value()); } TEST_F(GatewayGenericTest, HandlesMaxmimumChannelCapacity) { ::testing::Test::RecordProperty("TEST_ID", "5b4385e8-c717-4368-8121-b7d526fd22ac"); // ===== Setup // ===== Test for (auto i = 0U; i < iox::MAX_CHANNEL_NUMBER; i++) { auto result = sut->addChannel(iox::capro::ServiceDescription( iox::capro::IdString_t(iox::cxx::TruncateToCapacity, iox::cxx::convert::toString(i)), iox::capro::IdString_t(iox::cxx::TruncateToCapacity, iox::cxx::convert::toString(i)), iox::capro::IdString_t(iox::cxx::TruncateToCapacity, iox::cxx::convert::toString(i))), StubbedIceoryxTerminal::Options()); EXPECT_EQ(false, result.has_error()); } EXPECT_EQ(iox::MAX_CHANNEL_NUMBER, sut->getNumberOfChannels()); } TEST_F(GatewayGenericTest, ThrowsErrorWhenExceedingMaximumChannelCapaicity) { ::testing::Test::RecordProperty("TEST_ID", "f73c1fe0-d5d3-4527-9acb-29692c5fd19f"); // ===== Setup // ===== Test for (auto i = 0U; i < iox::MAX_CHANNEL_NUMBER; i++) { auto result = sut->addChannel(iox::capro::ServiceDescription( iox::capro::IdString_t(iox::cxx::TruncateToCapacity, iox::cxx::convert::toString(i)), iox::capro::IdString_t(iox::cxx::TruncateToCapacity, iox::cxx::convert::toString(i)), iox::capro::IdString_t(iox::cxx::TruncateToCapacity, iox::cxx::convert::toString(i))), StubbedIceoryxTerminal::Options()); EXPECT_EQ(false, result.has_error()); } auto result = sut->addChannel({"oneTooMany", "oneTooMany", "oneTooMany"}, StubbedIceoryxTerminal::Options()); EXPECT_EQ(true, result.has_error()); EXPECT_EQ(iox::gw::GatewayError::UNSUCCESSFUL_CHANNEL_CREATION, result.get_error()); } TEST_F(GatewayGenericTest, ThrowsErrorWhenAttemptingToRemoveNonexistantChannel) { ::testing::Test::RecordProperty("TEST_ID", "cd9f8279-5876-418a-9606-7413a9c2df35"); // ===== Setup auto testServiceA = iox::capro::ServiceDescription("serviceA", "instanceA", "eventA"); auto testServiceB = iox::capro::ServiceDescription("serviceB", "instanceB", "eventB"); auto testServiceC = iox::capro::ServiceDescription("serviceC", "instanceC", "eventC"); // ===== Test ASSERT_FALSE(sut->addChannel(testServiceA, StubbedIceoryxTerminal::Options()).has_error()); ASSERT_FALSE(sut->addChannel(testServiceB, StubbedIceoryxTerminal::Options()).has_error()); EXPECT_EQ(2U, sut->getNumberOfChannels()); auto result = sut->discardChannel(testServiceC); EXPECT_EQ(true, result.has_error()); EXPECT_EQ(2U, sut->getNumberOfChannels()); } TEST_F(GatewayGenericTest, DiscardedChannelsAreNotStored) { ::testing::Test::RecordProperty("TEST_ID", "b9f4cfcc-210d-4a61-83bf-d12da0ff7480"); // ===== Setup auto testService = iox::capro::ServiceDescription("service", "instance", "event"); // ===== Test ASSERT_FALSE(sut->addChannel(testService, StubbedIceoryxTerminal::Options()).has_error()); EXPECT_EQ(1U, sut->getNumberOfChannels()); auto result = sut->discardChannel(testService); EXPECT_EQ(false, result.has_error()); EXPECT_EQ(0U, sut->getNumberOfChannels()); } TEST_F(GatewayGenericTest, FindChannelReturnsCopyOfFoundChannel) { ::testing::Test::RecordProperty("TEST_ID", "3c97dd37-cdd4-4e93-b202-36cdcf3c1029"); // ===== Setup auto testService = iox::capro::ServiceDescription("service", "instance", "event"); // ===== Test ASSERT_FALSE(sut->addChannel(testService, StubbedIceoryxTerminal::Options()).has_error()); auto foundChannel = sut->findChannel(testService); EXPECT_EQ(true, foundChannel.has_value()); if (foundChannel.has_value()) { EXPECT_EQ(testService, foundChannel.value().getServiceDescription()); } } TEST_F(GatewayGenericTest, FindChannelGivesEmptyOptionalIfNoneFound) { ::testing::Test::RecordProperty("TEST_ID", "83cccfe0-68e6-4a35-b098-35c6c49c7743"); // ===== Setup auto storedChannelService = iox::capro::ServiceDescription("service", "instance", "event"); auto notStoredChannelService = iox::capro::ServiceDescription("otherService", "otherInstance", "otherEvent"); // ===== Test ASSERT_FALSE(sut->addChannel(storedChannelService, StubbedIceoryxTerminal::Options()).has_error()); auto foundChannel = sut->findChannel(notStoredChannelService); EXPECT_EQ(false, foundChannel.has_value()); } TEST_F(GatewayGenericTest, ForEachChannelExecutesGivenFunctionForAllStoredChannels) { ::testing::Test::RecordProperty("TEST_ID", "df23a642-f247-42c8-8df3-4daba32bc397"); // ===== Setup auto testServiceA = iox::capro::ServiceDescription("serviceA", "instanceA", "eventA"); auto testServiceB = iox::capro::ServiceDescription("serviceB", "instanceB", "eventB"); auto testServiceC = iox::capro::ServiceDescription("serviceC", "instanceC", "eventC"); auto count = 0U; auto f = [&count](TestChannel&) { count++; }; // ===== Test ASSERT_FALSE(sut->addChannel(testServiceA, StubbedIceoryxTerminal::Options()).has_error()); ASSERT_FALSE(sut->addChannel(testServiceB, StubbedIceoryxTerminal::Options()).has_error()); ASSERT_FALSE(sut->addChannel(testServiceC, StubbedIceoryxTerminal::Options()).has_error()); sut->forEachChannel(f); EXPECT_EQ(3U, count); } } // namespace