Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add plugin name accessor #29

Merged
merged 3 commits into from
Oct 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions core/include/ignition/plugin/Plugin.hh
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,13 @@ namespace ignition
std::shared_ptr<const Interface> 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 <class Interface>
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,
Expand All @@ -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 -----------------------

Expand Down
9 changes: 9 additions & 0 deletions core/src/Plugin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion loader/src/Loader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
62 changes: 45 additions & 17 deletions test/integration/plugin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,32 +58,50 @@ TEST(Loader, LoadExistingLibrary)
// Make sure the expected plugins were loaded.
std::unordered_set<std::string> 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<bool>(firstPlugin));

EXPECT_EQ(std::string("test::util::DummySinglePlugin"), *firstPlugin->Name());

EXPECT_TRUE(firstPlugin->HasInterface<test::util::DummyNameBase>());
EXPECT_TRUE(firstPlugin->HasInterface("test::util::DummyNameBase"));

Expand All @@ -96,10 +114,13 @@ TEST(Loader, LoadExistingLibrary)
EXPECT_FALSE(firstPlugin->HasInterface<test::util::DummySetterBase>());
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<test::util::DummyNameBase>());
EXPECT_TRUE(secondPlugin->HasInterface("test::util::DummyNameBase"));

Expand All @@ -112,38 +133,42 @@ TEST(Loader, LoadExistingLibrary)
EXPECT_TRUE(secondPlugin->HasInterface<test::util::DummySetterBase>());
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<test::util::DummyNameBase>();
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<test::util::DummyDoubleBase>();
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<test::util::DummyNameBase>();
ASSERT_NE(nullptr, nameBase);
EXPECT_EQ(std::string("DummyMultiPlugin"), nameBase->MyNameIs());

// DummyDoubleBase interface by DummyMultiPlugin.
doubleBase = secondPlugin->QueryInterface<test::util::DummyDoubleBase>();
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<test::util::DummyNameBase>();
ASSERT_NE(nullptr, nameBase);
EXPECT_EQ(std::string("DummyMultiPlugin"), nameBase->MyNameIs());
// DummyIntBase interface by DummyMultiPlugin.
test::util::DummyIntBase* intBase =
secondPlugin->QueryInterface<test::util::DummyIntBase>();
EXPECT_EQ(5, intBase->MyIntegerValueIs());

// DummyGetObjectBase interface by DummyMultiPlugin.
test::util::DummyGetObjectBase *objectBase =
secondPlugin->QueryInterface<test::util::DummyGetObjectBase>();
secondPlugin->QueryInterface<test::util::DummyGetObjectBase>();
ASSERT_NE(nullptr, objectBase);

test::util::DummyObject object = objectBase->GetDummyObject();
EXPECT_EQ(secondPlugin->QueryInterface<test::util::DummyIntBase>()
->MyIntegerValueIs(), object.dummyInt);
EXPECT_NEAR(doubleBase->MyDoubleValueIs(), object.dummyDouble, 1e-8);
EXPECT_EQ(intBase->MyIntegerValueIs(), object.dummyInt);
}


Expand All @@ -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;
Expand Down Expand Up @@ -215,6 +242,7 @@ TEST(PluginPtr, Empty)
{
ignition::plugin::PluginPtr empty;
EXPECT_TRUE(empty.IsEmpty());
EXPECT_EQ(nullptr, empty->Name());
EXPECT_FALSE(empty->HasInterface<SomeInterface>());
EXPECT_FALSE(static_cast<bool>(empty));
EXPECT_EQ(nullptr, empty->QueryInterfaceSharedPtr<SomeInterface>());
Expand Down
2 changes: 2 additions & 0 deletions test/integration/templated_plugins.cc
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ void TestSetAndGet(const ignition::plugin::Loader &_pl,
const SetAndGetPluginPtr<T> plugin = _pl.Instantiate(pluginName);
ASSERT_TRUE(static_cast<bool>(plugin));

EXPECT_EQ(pluginName, *plugin->Name());

usedSpecializedInterfaceAccess = false;
ASSERT_TRUE(plugin->template HasInterface<SetInterface>());
EXPECT_TRUE(usedSpecializedInterfaceAccess);
Expand Down