From 4a87904ac0b70385d8e5bb520e84ab11aa2eaba5 Mon Sep 17 00:00:00 2001 From: Nick Lamprianidis Date: Thu, 29 Oct 2020 09:43:54 +0100 Subject: [PATCH] Add plugin name accessor (#29) Closes #5 * Update plugin tests * Fix indentation in PrettyStr Signed-off-by: Nick Lamprianidis --- core/include/ignition/plugin/Plugin.hh | 14 ++++-- core/src/Plugin.cc | 9 ++++ loader/src/Loader.cc | 2 +- test/integration/plugin.cc | 62 +++++++++++++++++++------- test/integration/templated_plugins.cc | 2 + 5 files changed, 67 insertions(+), 22 deletions(-) diff --git a/core/include/ignition/plugin/Plugin.hh b/core/include/ignition/plugin/Plugin.hh index ac884d3c..d94fc95d 100644 --- a/core/include/ignition/plugin/Plugin.hh +++ b/core/include/ignition/plugin/Plugin.hh @@ -120,13 +120,13 @@ namespace ignition std::shared_ptr QueryInterfaceSharedPtr( const std::string &/*_interfaceName*/) const; - /// \brief Returns true if this Plugin has the specified type of - /// interface. + /// \brief Checks if this Plugin has the specified type of interface. + /// \return Returns true if this Plugin has the specified type of + /// interface, and false otherwise. public: template bool HasInterface() const; - /// \brief Returns true if this Plugin has the specified type of - /// interface, otherwise returns false. + /// \brief Checks if this Plugin has the specified type of interface. /// /// By default, we expect you to pass in a demangled version of the /// interface name. If you want to use a mangled version of the name, @@ -137,9 +137,15 @@ namespace ignition /// \param[in] _demangled If _interfaceName is demangled, set this to /// true. If you are instead using the raw mangled name that gets provided /// by typeid(T).name(), then set _demangled to false. + /// \return Returns true if this Plugin has the specified type of + /// interface, and false otherwise. public: bool HasInterface(const std::string &_interfaceName, const bool _demangled = true) const; + /// \brief Gets the name of this Plugin. + /// \return A pointer to the name of this Plugin, or nullptr if this + /// Plugin is not instantiated. + public: const std::string *Name() const; // -------------------- Private API ----------------------- diff --git a/core/src/Plugin.cc b/core/src/Plugin.cc index 77283d38..e56ac091 100644 --- a/core/src/Plugin.cc +++ b/core/src/Plugin.cc @@ -310,6 +310,15 @@ namespace ignition return (this->dataPtr->interfaces.count(_interfaceName) != 0); } + ////////////////////////////////////////////////// + const std::string *Plugin::Name() const + { + if (!this->dataPtr->info) + return nullptr; + + return &this->dataPtr->info->name; + } + ////////////////////////////////////////////////// Plugin::Plugin() : dataPtr(new Implementation) diff --git a/loader/src/Loader.cc b/loader/src/Loader.cc index 801c5aa4..4b6362f1 100644 --- a/loader/src/Loader.cc +++ b/loader/src/Loader.cc @@ -150,7 +150,7 @@ namespace ignition } else { - pretty << "has no aliases\n"; + pretty << "\t\t\thas no aliases\n"; } const std::size_t iSize = plugin->interfaces.size(); diff --git a/test/integration/plugin.cc b/test/integration/plugin.cc index 484df8ee..e372f8bf 100644 --- a/test/integration/plugin.cc +++ b/test/integration/plugin.cc @@ -58,32 +58,50 @@ TEST(Loader, LoadExistingLibrary) // Make sure the expected plugins were loaded. std::unordered_set pluginNames = pl.LoadLib(IGNDummyPlugins_LIB); + ASSERT_EQ(3u, pluginNames.size()); ASSERT_EQ(1u, pluginNames.count("test::util::DummySinglePlugin")); ASSERT_EQ(1u, pluginNames.count("test::util::DummyMultiPlugin")); + ASSERT_EQ(1u, pluginNames.count("test::util::DummyNoAliasPlugin")); std::cout << pl.PrettyStr(); // Make sure the expected interfaces were loaded. EXPECT_EQ(7u, pl.InterfacesImplemented().size()); + EXPECT_EQ(1u, pl.InterfacesImplemented().count( + "test::util::DummyDoubleBase")); + EXPECT_EQ(1u, pl.InterfacesImplemented().count( + "test::util::DummyGetObjectBase")); + EXPECT_EQ(1u, pl.InterfacesImplemented().count("test::util::DummyIntBase")); + EXPECT_EQ(1u, pl.InterfacesImplemented().count( + "test::util::DummySetterBase")); + EXPECT_EQ(1u, pl.InterfacesImplemented().count( + "ignition::plugin::EnablePluginFromThis")); + EXPECT_EQ(1u, pl.InterfacesImplemented().count( + "test::util::DummyGetPluginInstancePtr")); EXPECT_EQ(1u, pl.InterfacesImplemented().count("test::util::DummyNameBase")); + // Make sure the expected number of plugins implements each interface. + EXPECT_EQ(3u, pl.PluginsImplementing<::test::util::DummyNameBase>().size()); EXPECT_EQ(3u, pl.PluginsImplementing("test::util::DummyNameBase").size()); EXPECT_EQ(3u, pl.PluginsImplementing( - typeid(test::util::DummyNameBase).name(), false).size()); + typeid(test::util::DummyNameBase).name(), false).size()); EXPECT_EQ(1u, pl.PluginsImplementing<::test::util::DummyDoubleBase>().size()); EXPECT_EQ(1u, pl.PluginsImplementing("test::util::DummyDoubleBase").size()); EXPECT_EQ(1u, pl.PluginsImplementing( - typeid(test::util::DummyDoubleBase).name(), false).size()); + typeid(test::util::DummyDoubleBase).name(), false).size()); EXPECT_EQ(3u, pl.AllPlugins().size()); + // Check DummySinglePlugin. ignition::plugin::PluginPtr firstPlugin = pl.Instantiate("test::util::DummySinglePlugin"); EXPECT_FALSE(firstPlugin.IsEmpty()); EXPECT_TRUE(static_cast(firstPlugin)); + EXPECT_EQ(std::string("test::util::DummySinglePlugin"), *firstPlugin->Name()); + EXPECT_TRUE(firstPlugin->HasInterface()); EXPECT_TRUE(firstPlugin->HasInterface("test::util::DummyNameBase")); @@ -96,10 +114,13 @@ TEST(Loader, LoadExistingLibrary) EXPECT_FALSE(firstPlugin->HasInterface()); EXPECT_FALSE(firstPlugin->HasInterface("test::util::DummySetterBase")); + // Check DummyMultiPlugin. ignition::plugin::PluginPtr secondPlugin = pl.Instantiate("test::util::DummyMultiPlugin"); EXPECT_FALSE(secondPlugin.IsEmpty()); + EXPECT_EQ(std::string("test::util::DummyMultiPlugin"), *secondPlugin->Name()); + EXPECT_TRUE(secondPlugin->HasInterface()); EXPECT_TRUE(secondPlugin->HasInterface("test::util::DummyNameBase")); @@ -112,38 +133,42 @@ TEST(Loader, LoadExistingLibrary) EXPECT_TRUE(secondPlugin->HasInterface()); EXPECT_TRUE(secondPlugin->HasInterface("test::util::DummySetterBase")); - // Check that the DummyNameBase interface exists and that it returns the - // correct value. + // Check that the right interfaces for each plugin exist (or don't exist) and + // that they return the correct values. + + // DummyNameBase interface by DummySinglePlugin. test::util::DummyNameBase* nameBase = firstPlugin->QueryInterface(); ASSERT_NE(nullptr, nameBase); EXPECT_EQ(std::string("DummySinglePlugin"), nameBase->MyNameIs()); - // Check that DummyDoubleBase does not exist for this plugin + // No DummyDoubleBase interface by DummySinglePlugin. test::util::DummyDoubleBase* doubleBase = firstPlugin->QueryInterface(); EXPECT_EQ(nullptr, doubleBase); - // Check that DummyDoubleBase does exist for this function and that it returns - // the correct value. + // DummyNameBase interface by DummyMultiPlugin. + nameBase = secondPlugin->QueryInterface(); + ASSERT_NE(nullptr, nameBase); + EXPECT_EQ(std::string("DummyMultiPlugin"), nameBase->MyNameIs()); + + // DummyDoubleBase interface by DummyMultiPlugin. doubleBase = secondPlugin->QueryInterface(); ASSERT_NE(nullptr, doubleBase); EXPECT_NEAR(3.14159, doubleBase->MyDoubleValueIs(), 1e-8); - // Check that the DummyNameBase interface exists for this plugin and that it - // returns the correct value. - nameBase = secondPlugin->QueryInterface(); - ASSERT_NE(nullptr, nameBase); - EXPECT_EQ(std::string("DummyMultiPlugin"), nameBase->MyNameIs()); + // DummyIntBase interface by DummyMultiPlugin. + test::util::DummyIntBase* intBase = + secondPlugin->QueryInterface(); + EXPECT_EQ(5, intBase->MyIntegerValueIs()); + // DummyGetObjectBase interface by DummyMultiPlugin. test::util::DummyGetObjectBase *objectBase = - secondPlugin->QueryInterface(); + secondPlugin->QueryInterface(); ASSERT_NE(nullptr, objectBase); - test::util::DummyObject object = objectBase->GetDummyObject(); - EXPECT_EQ(secondPlugin->QueryInterface() - ->MyIntegerValueIs(), object.dummyInt); EXPECT_NEAR(doubleBase->MyDoubleValueIs(), object.dummyDouble, 1e-8); + EXPECT_EQ(intBase->MyIntegerValueIs(), object.dummyInt); } @@ -163,9 +188,11 @@ TEST(SpecializedPluginPtr, Construction) pl.LoadLib(IGNDummyPlugins_LIB); SomeSpecializedPluginPtr plugin( - pl.Instantiate("test::util::DummyMultiPlugin")); + pl.Instantiate("test::util::DummyMultiPlugin")); EXPECT_FALSE(plugin.IsEmpty()); + EXPECT_EQ(std::string("test::util::DummyMultiPlugin"), *plugin->Name()); + // Make sure the specialized interface is available, that it is accessed using // the specialized access, and that it returns the expected value. usedSpecializedInterfaceAccess = false; @@ -215,6 +242,7 @@ TEST(PluginPtr, Empty) { ignition::plugin::PluginPtr empty; EXPECT_TRUE(empty.IsEmpty()); + EXPECT_EQ(nullptr, empty->Name()); EXPECT_FALSE(empty->HasInterface()); EXPECT_FALSE(static_cast(empty)); EXPECT_EQ(nullptr, empty->QueryInterfaceSharedPtr()); diff --git a/test/integration/templated_plugins.cc b/test/integration/templated_plugins.cc index b5a26d7f..0ded41b9 100644 --- a/test/integration/templated_plugins.cc +++ b/test/integration/templated_plugins.cc @@ -79,6 +79,8 @@ void TestSetAndGet(const ignition::plugin::Loader &_pl, const SetAndGetPluginPtr plugin = _pl.Instantiate(pluginName); ASSERT_TRUE(static_cast(plugin)); + EXPECT_EQ(pluginName, *plugin->Name()); + usedSpecializedInterfaceAccess = false; ASSERT_TRUE(plugin->template HasInterface()); EXPECT_TRUE(usedSpecializedInterfaceAccess);