#include
#include
#include
#include
#include
#include
#ifndef XPLUGIN_NO_THREADS
#include
#endif
#include
using base_type = plugin::PluginBase;
using factory_base_type = xp::xfactory_base;
using plugin_registry_type = xp::xplugin_registry;
void test_xplugin_impl(plugin_registry_type& registry)
{
CHECK_EQ(registry.size(), 3);
auto factory_01 = registry["plugin_01"];
auto factory_02 = registry["plugin_02"];
auto factory_03 = registry["plugin_03"];
auto plugin_01 = factory_01->create(1, "a");
auto plugin_02 = factory_02->create(2, "b");
auto plugin_03 = factory_03->create(3, "c");
CHECK(plugin_01);
CHECK(plugin_02);
CHECK(plugin_03);
CHECK_EQ(plugin_01->name(), "Plugin01");
CHECK_EQ(plugin_02->name(), "Plugin02");
CHECK_EQ(plugin_03->name(), "Plugin03");
CHECK_EQ(plugin_01->greet(), "hello from Plugin01");
CHECK_EQ(plugin_02->greet(), "hello from Plugin02");
CHECK_EQ(plugin_03->greet(), "hello from Plugin03");
// // iterate over plugins
SUBCASE("begin_end")
{
std::cout greet();
plugin_names.insert(p.first);
}
CHECK_EQ(plugin_names.size(), 3);
CHECK(plugin_names.count("plugin_01"));
CHECK(plugin_names.count("plugin_02"));
CHECK(plugin_names.count("plugin_03"));
}
SUBCASE("iterator-values-ref")
{
std::set plugin_names;
for (auto &p : registry)
{
p.second->create(1, "a")->greet();
plugin_names.insert(p.first);
}
CHECK_EQ(plugin_names.size(), 3);
CHECK(plugin_names.count("plugin_01"));
CHECK(plugin_names.count("plugin_02"));
CHECK(plugin_names.count("plugin_03"));
}
SUBCASE("iterator-unpack")
{
std::set plugin_names;
for (auto [name, factory] : registry)
{
factory->create(1, "a")->greet();
plugin_names.insert(name);
}
CHECK_EQ(plugin_names.size(), 3);
CHECK(plugin_names.count("plugin_01"));
CHECK(plugin_names.count("plugin_02"));
CHECK(plugin_names.count("plugin_03"));
}
}
namespace
{
std::string get_default_extension()
{
#ifdef _WIN32
return ".dll";
#elif __APPLE__
return ".dylib";
#else
return ".so";
#endif
}
}
TEST_CASE("test_xplugin")
{
std::filesystem::path path("testplugin_a");
plugin_registry_type registry(path);
test_xplugin_impl(registry);
std::vector plugin_list;
for (const auto &entry : std::filesystem::directory_iterator(path))
{
if (entry.path().extension() == get_default_extension())
{
plugin_list.push_back(entry.path());
}
}
plugin_registry_type registry2(std::move(plugin_list));
test_xplugin_impl(registry2);
}
TEST_CASE("test_xregistry_getter")
{
using base_type = plugin::PluginBase;
using factory_base_type = xp::xfactory_base;
using plugin_registry_type = xp::xplugin_registry;
plugin_registry_type registry("testplugin_a");
CHECK_EQ(registry.size(), 3);
auto factory_01 = registry["plugin_01"];
auto factory_02 = registry["plugin_02"];
auto factory_03 = registry["plugin_03"];
auto plugin_01 = factory_01->create(1, "a");
auto plugin_02 = factory_02->create(2, "b");
auto plugin_03 = factory_03->create(3, "c");
CHECK(plugin_01);
CHECK(plugin_02);
CHECK(plugin_03);
CHECK_EQ(plugin_01->name(), "Plugin01");
CHECK_EQ(plugin_02->name(), "Plugin02");
CHECK_EQ(plugin_03->name(), "Plugin03");
CHECK_EQ(plugin_01->greet(), "hello from Plugin01");
CHECK_EQ(plugin_02->greet(), "hello from Plugin02");
CHECK_EQ(plugin_03->greet(), "hello from Plugin03");
}
TEST_CASE("test_xregistry_open_same_lib_multiple_times")
{
using base_type = plugin::PluginBase;
using factory_base_type = xp::xfactory_base;
using plugin_registry_type = xp::xplugin_registry;
std::vector registries(1000);
for (auto ®istry : registries)
{
registry = new plugin_registry_type("testplugin_a");
}
for (auto ®istry : registries)
{
CHECK_EQ(registry->size(), 3);
auto factory_01 = registry->operator[]("plugin_01");
auto factory_02 = registry->operator[]("plugin_02");
auto factory_03 = registry->operator[]("plugin_03");
auto plugin_01 = factory_01->create(1, "a");
auto plugin_02 = factory_02->create(2, "b");
auto plugin_03 = factory_03->create(3, "c");
CHECK(plugin_01);
CHECK(plugin_02);
CHECK(plugin_03);
CHECK_EQ(plugin_01->name(), "Plugin01");
CHECK_EQ(plugin_02->name(), "Plugin02");
CHECK_EQ(plugin_03->name(), "Plugin03");
}
for (auto ®istry : registries)
{
delete registry;
}
}
#ifndef XPLUGIN_NO_THREADS
TEST_CASE("parallel_access")
{
using base_type = plugin::PluginBase;
using factory_base_type = xp::xfactory_base;
using plugin_registry_type = xp::xthread_save_plugin_registry;
for (std::size_t i = 0; i < 1000; ++i)
{
plugin_registry_type registry("testplugin_a");
auto f = [&]() {
auto factory_01 = registry["plugin_01"];
auto factory_02 = registry["plugin_02"];
auto factory_03 = registry["plugin_03"];
auto plugin_01 = factory_01->create(1, "a");
auto plugin_02 = factory_02->create(2, "b");
auto plugin_03 = factory_03->create(3, "c");
CHECK(plugin_01);
CHECK(plugin_02);
CHECK(plugin_03);
CHECK_EQ(plugin_01->name(), "Plugin01");
CHECK_EQ(plugin_02->name(), "Plugin02");
CHECK_EQ(plugin_03->name(), "Plugin03");
};
std::thread thread1(f);
std::thread thread2(f);
thread1.join();
thread2.join();
}
}
#endif // XPLUGIN_NO_THREADS
#ifndef XPLUGIN_NO_THREADS
TEST_CASE("parallel_iterator_access")
{
using base_type = plugin::PluginBase;
using factory_base_type = xp::xfactory_base;
using plugin_registry_type = xp::xthread_save_plugin_registry;
for (std::size_t i = 0; i < 1000; ++i)
{
plugin_registry_type registry("testplugin_a");
auto f = [®istry]() {
for (auto name_factory : registry)
{
auto name = name_factory.first;
auto factory = name_factory.second;
CHECK(name[0] == 'p');
CHECK(factory);
auto plugin = factory->create(1, "a");
CHECK(plugin);
CHECK_EQ(plugin->name()[0], 'P');
}
};
std::thread thread1(f);
std::thread thread2(f);
thread1.join();
thread2.join();
}
}
#endif // XPLUGIN_NO_THREADS