changeset 684:8d93e415c3b4

Irccd: load directly native plugin instead of wrapping it, closes #790 @1h The boost::dll::import function support importing variables as boost::shared_ptr, instead of wrapping all individual function, just load the plugin from the shared object and return it as a std::shared_ptr.
author David Demelier <markand@malikania.fr>
date Fri, 13 Apr 2018 07:32:10 +0200
parents d30793525261
children e81c6badede3
files libirccd/irccd/daemon/dynlib_plugin.cpp libirccd/irccd/daemon/dynlib_plugin.hpp tests/src/libirccd/dynlib-plugin/CMakeLists.txt tests/src/libirccd/dynlib-plugin/main.cpp tests/src/libirccd/dynlib-plugin/test_plugin.cpp
diffstat 5 files changed, 135 insertions(+), 343 deletions(-) [+]
line wrap: on
line diff
--- a/libirccd/irccd/daemon/dynlib_plugin.cpp	Thu Apr 12 19:30:43 2018 +0200
+++ b/libirccd/irccd/daemon/dynlib_plugin.cpp	Fri Apr 13 07:32:10 2018 +0200
@@ -19,7 +19,7 @@
 #include <cctype>
 #include <algorithm>
 
-#include <boost/filesystem.hpp>
+#include <boost/dll.hpp>
 
 #include <irccd/string_util.hpp>
 
@@ -35,126 +35,23 @@
 
 namespace irccd {
 
-dynlib_plugin::dynlib_plugin(std::string name, std::string path)
-    : plugin(name, path)
-    , dso_(path)
-{
-    using load_t = std::unique_ptr<plugin>(std::string, std::string);
-
-    /*
-     * Function name is determined from the plugin filename where all non
-     * alphabetic characters are removed.
-     *
-     * Example: foo_bar-baz___.so becomes irccd_foobarbaz_load.
-     */
-    auto base = boost::filesystem::path(path).stem().string();
-    auto need_remove = [] (auto c) {
-        return !std::isalnum(c);
-    };
-
-    base.erase(std::remove_if(base.begin(), base.end(), need_remove), base.end());
-
-    auto fname = string_util::sprintf("irccd_%s_load", base);
-    auto load = dso_.get<load_t>(fname);
-
-    if (!load)
-        throw std::runtime_error(string_util::sprintf("missing plugin entry function '%s'", fname));
-
-    plugin_ = load(name, path);
+namespace {
 
-    if (!plugin_)
-        throw std::runtime_error("plugin returned null");
-}
-
-void dynlib_plugin::handle_command(irccd& irccd, const message_event& ev)
+std::string symbol(std::string id) noexcept
 {
-    plugin_->handle_command(irccd, ev);
-}
-
-void dynlib_plugin::handle_connect(irccd& irccd, const connect_event& ev)
-{
-    plugin_->handle_connect(irccd, ev);
-}
+    std::transform(id.begin(), id.end(), id.begin(), [] (auto c) {
+        return c == '-' ? '_' : c;
+    });
 
-void dynlib_plugin::handle_disconnect(irccd& irccd, const disconnect_event& ev)
-{
-    plugin_->handle_disconnect(irccd, ev);
-}
-
-void dynlib_plugin::handle_invite(irccd& irccd, const invite_event& ev)
-{
-    plugin_->handle_invite(irccd, ev);
-}
-
-void dynlib_plugin::handle_join(irccd& irccd, const join_event& ev)
-{
-    plugin_->handle_join(irccd, ev);
+    return string_util::sprintf("irccd_plugin_%s", id);
 }
 
-void dynlib_plugin::handle_kick(irccd& irccd, const kick_event& ev)
-{
-    plugin_->handle_kick(irccd, ev);
-}
-
-void dynlib_plugin::handle_load(irccd& irccd)
-{
-    plugin_->handle_load(irccd);
-}
-
-void dynlib_plugin::handle_message(irccd& irccd, const message_event& ev)
+std::shared_ptr<plugin> wrap(boost::shared_ptr<plugin> ptr) noexcept
 {
-    plugin_->handle_message(irccd, ev);
-}
-
-void dynlib_plugin::handle_me(irccd& irccd, const me_event& ev)
-{
-    plugin_->handle_me(irccd, ev);
-}
-
-void dynlib_plugin::handle_mode(irccd& irccd, const mode_event& ev)
-{
-    plugin_->handle_mode(irccd, ev);
-}
-
-void dynlib_plugin::handle_names(irccd& irccd, const names_event& ev)
-{
-    plugin_->handle_names(irccd, ev);
+    return std::shared_ptr<plugin>(ptr.get(), [ptr] (auto) mutable { ptr.reset(); });
 }
 
-void dynlib_plugin::handle_nick(irccd& irccd, const nick_event& ev)
-{
-    plugin_->handle_nick(irccd, ev);
-}
-
-void dynlib_plugin::handle_notice(irccd& irccd, const notice_event& ev)
-{
-    plugin_->handle_notice(irccd, ev);
-}
-
-void dynlib_plugin::handle_part(irccd& irccd, const part_event& ev)
-{
-    plugin_->handle_part(irccd, ev);
-}
-
-void dynlib_plugin::handle_reload(irccd& irccd)
-{
-    plugin_->handle_reload(irccd);
-}
-
-void dynlib_plugin::handle_topic(irccd& irccd, const topic_event& ev)
-{
-    plugin_->handle_topic(irccd, ev);
-}
-
-void dynlib_plugin::handle_unload(irccd& irccd)
-{
-    plugin_->handle_unload(irccd);
-}
-
-void dynlib_plugin::handle_whois(irccd& irccd, const whois_event& ev)
-{
-    plugin_->handle_whois(irccd, ev);
-}
+} // !namespace
 
 dynlib_plugin_loader::dynlib_plugin_loader(std::vector<std::string> directories) noexcept
     : plugin_loader(std::move(directories), { DYNLIB_EXTENSION })
@@ -164,7 +61,7 @@
 std::shared_ptr<plugin> dynlib_plugin_loader::open(const std::string& id,
                                                    const std::string& path) noexcept
 {
-    return std::make_unique<dynlib_plugin>(id, path);
+    return wrap(boost::dll::import<plugin>(path, symbol(id)));
 }
 
 } // !irccd
--- a/libirccd/irccd/daemon/dynlib_plugin.hpp	Thu Apr 12 19:30:43 2018 +0200
+++ b/libirccd/irccd/daemon/dynlib_plugin.hpp	Fri Apr 13 07:32:10 2018 +0200
@@ -31,116 +31,6 @@
 namespace irccd {
 
 /**
- * \brief Dynlib based plugin.
- * \ingroup plugins
- */
-class dynlib_plugin : public plugin {
-private:
-    boost::dll::shared_library dso_;
-    std::unique_ptr<plugin> plugin_;
-
-public:
-    /**
-     * Construct the plugin.
-     *
-     * \param name the name
-     * \param path the fully resolved path (must be absolute)
-     * \throw std::exception on failures
-     */
-    dynlib_plugin(std::string name, std::string path);
-
-    /**
-     * \copydoc plugin::handle_command
-     */
-    void handle_command(irccd& irccd, const message_event& event) override;
-
-    /**
-     * \copydoc plugin::handle_connect
-     */
-    void handle_connect(irccd& irccd, const connect_event& event) override;
-
-    /**
-     * \copydoc plugin::handle_disconnect
-     */
-    void handle_disconnect(irccd& irccd, const disconnect_event& event) override;
-
-    /**
-     * \copydoc plugin::handle_invite
-     */
-    void handle_invite(irccd& irccd, const invite_event& event) override;
-
-    /**
-     * \copydoc plugin::handle_join
-     */
-    void handle_join(irccd& irccd, const join_event& event) override;
-
-    /**
-     * \copydoc plugin::handle_kick
-     */
-    void handle_kick(irccd& irccd, const kick_event& event) override;
-
-    /**
-     * \copydoc plugin::handle_load
-     */
-    void handle_load(irccd& irccd) override;
-
-    /**
-     * \copydoc plugin::handle_message
-     */
-    void handle_message(irccd& irccd, const message_event& event) override;
-
-    /**
-     * \copydoc plugin::handle_me
-     */
-    void handle_me(irccd& irccd, const me_event& event) override;
-
-    /**
-     * \copydoc plugin::handle_mode
-     */
-    void handle_mode(irccd& irccd, const mode_event& event) override;
-
-    /**
-     * \copydoc plugin::handle_names
-     */
-    void handle_names(irccd& irccd, const names_event& event) override;
-
-    /**
-     * \copydoc plugin::handle_nick
-     */
-    void handle_nick(irccd& irccd, const nick_event& event) override;
-
-    /**
-     * \copydoc plugin::handle_notice
-     */
-    void handle_notice(irccd& irccd, const notice_event& event) override;
-
-    /**
-     * \copydoc plugin::handle_part
-     */
-    void handle_part(irccd& irccd, const part_event& event) override;
-
-    /**
-     * \copydoc plugin::handle_reload
-     */
-    void handle_reload(irccd& irccd) override;
-
-    /**
-     * \copydoc plugin::handle_topic
-     */
-    void handle_topic(irccd& irccd, const topic_event& event) override;
-
-    /**
-     * \copydoc plugin::handle_unload
-     */
-    void handle_unload(irccd& irccd) override;
-
-    /**
-     * \copydoc plugin::handle_whois
-     */
-    void handle_whois(irccd& irccd, const whois_event& event) override;
-};
-
-/**
  * \brief Implementation for searching native plugins.
  */
 class dynlib_plugin_loader : public plugin_loader {
--- a/tests/src/libirccd/dynlib-plugin/CMakeLists.txt	Thu Apr 12 19:30:43 2018 +0200
+++ b/tests/src/libirccd/dynlib-plugin/CMakeLists.txt	Fri Apr 13 07:32:10 2018 +0200
@@ -40,4 +40,5 @@
     NAME dynlib-plugin
     SOURCES main.cpp
     LIBRARIES libirccd libirccd-test
+    DEPENDS test-plugin
 )
--- a/tests/src/libirccd/dynlib-plugin/main.cpp	Thu Apr 12 19:30:43 2018 +0200
+++ b/tests/src/libirccd/dynlib-plugin/main.cpp	Fri Apr 13 07:32:10 2018 +0200
@@ -20,31 +20,22 @@
 #include <boost/test/unit_test.hpp>
 
 /*
- * For this test, we open a plugin written in C++ and pass a journal_server
- * class for each of the plugin function.
- *
- * Then we verify that the appropriate function has been called correctly.
- *
- * Functions load, unload and reload can not be tested though.
+ * For this test, we update internal plugin configuration each time a function
+ * is called and check if it has been called correctly using get_config.
  */
 
 #include <irccd/daemon/dynlib_plugin.hpp>
 #include <irccd/daemon/irccd.hpp>
 
-#include <irccd/test/journal_server.hpp>
-
 namespace irccd {
 
 class fixture {
 protected:
     boost::asio::io_service service_;
-    std::shared_ptr<journal_server> server_;
     std::shared_ptr<plugin> plugin_;
-    irccd irccd_;
+    irccd irccd_{service_};
 
     inline fixture()
-        : server_(std::make_shared<journal_server>(service_, "test"))
-        , irccd_(service_)
     {
         plugin_ = dynlib_plugin_loader({CMAKE_CURRENT_BINARY_DIR}).find("test-plugin");
 
@@ -57,142 +48,138 @@
 
 BOOST_AUTO_TEST_CASE(handle_command)
 {
-    plugin_->handle_command(irccd_, {server_, "", "", ""});
+    plugin_->handle_command(irccd_, {});
 
-    BOOST_TEST(server_->cqueue().size() == 1U);
-    BOOST_TEST(server_->cqueue()[0]["command"].get<std::string>() == "message");
-    BOOST_TEST(server_->cqueue()[0]["message"].get<std::string>() == "handle_command");
-    BOOST_TEST(server_->cqueue()[0]["target"].get<std::string>() == "test");
+    BOOST_TEST(plugin_->get_config().size() == 1U);
+    BOOST_TEST(plugin_->get_config()["command"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_connect)
 {
-    plugin_->handle_connect(irccd_, {server_});
+    plugin_->handle_connect(irccd_, {});
 
-    BOOST_TEST(server_->cqueue().size() == 1U);
-    BOOST_TEST(server_->cqueue()[0]["command"].get<std::string>() == "message");
-    BOOST_TEST(server_->cqueue()[0]["message"].get<std::string>() == "handle_connect");
-    BOOST_TEST(server_->cqueue()[0]["target"].get<std::string>() == "test");
+    BOOST_TEST(plugin_->get_config().size() == 1U);
+    BOOST_TEST(plugin_->get_config()["connect"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_invite)
 {
-    plugin_->handle_invite(irccd_, {server_, "", "", ""});
+    plugin_->handle_invite(irccd_, {});
 
-    BOOST_TEST(server_->cqueue().size() == 1U);
-    BOOST_TEST(server_->cqueue()[0]["command"].get<std::string>() == "message");
-    BOOST_TEST(server_->cqueue()[0]["message"].get<std::string>() == "handle_invite");
-    BOOST_TEST(server_->cqueue()[0]["target"].get<std::string>() == "test");
+    BOOST_TEST(plugin_->get_config().size() == 1U);
+    BOOST_TEST(plugin_->get_config()["invite"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_join)
 {
-    plugin_->handle_join(irccd_, {server_, "", ""});
+    plugin_->handle_join(irccd_, {});
 
-    BOOST_TEST(server_->cqueue().size() == 1U);
-    BOOST_TEST(server_->cqueue()[0]["command"].get<std::string>() == "message");
-    BOOST_TEST(server_->cqueue()[0]["message"].get<std::string>() == "handle_join");
-    BOOST_TEST(server_->cqueue()[0]["target"].get<std::string>() == "test");
+    BOOST_TEST(plugin_->get_config().size() == 1U);
+    BOOST_TEST(plugin_->get_config()["join"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_kick)
 {
-    plugin_->handle_kick(irccd_, {server_, "", "", "", ""});
+    plugin_->handle_kick(irccd_, {});
+
+    BOOST_TEST(plugin_->get_config().size() == 1U);
+    BOOST_TEST(plugin_->get_config()["kick"] == "true");
+}
 
-    BOOST_TEST(server_->cqueue().size() == 1U);
-    BOOST_TEST(server_->cqueue()[0]["command"].get<std::string>() == "message");
-    BOOST_TEST(server_->cqueue()[0]["message"].get<std::string>() == "handle_kick");
-    BOOST_TEST(server_->cqueue()[0]["target"].get<std::string>() == "test");
+BOOST_AUTO_TEST_CASE(handle_load)
+{
+    plugin_->handle_load(irccd_);
+
+    BOOST_TEST(plugin_->get_config().size() == 1U);
+    BOOST_TEST(plugin_->get_config()["load"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_message)
 {
-    plugin_->handle_message(irccd_, {server_, "", "", ""});
+    plugin_->handle_message(irccd_, {});
 
-    BOOST_TEST(server_->cqueue().size() == 1U);
-    BOOST_TEST(server_->cqueue()[0]["command"].get<std::string>() == "message");
-    BOOST_TEST(server_->cqueue()[0]["message"].get<std::string>() == "handle_message");
-    BOOST_TEST(server_->cqueue()[0]["target"].get<std::string>() == "test");
+    BOOST_TEST(plugin_->get_config().size() == 1U);
+    BOOST_TEST(plugin_->get_config()["message"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_me)
 {
-    plugin_->handle_me(irccd_, {server_, "", "", ""});
+    plugin_->handle_me(irccd_, {});
 
-    BOOST_TEST(server_->cqueue().size() == 1U);
-    BOOST_TEST(server_->cqueue()[0]["command"].get<std::string>() == "message");
-    BOOST_TEST(server_->cqueue()[0]["message"].get<std::string>() == "handle_me");
-    BOOST_TEST(server_->cqueue()[0]["target"].get<std::string>() == "test");
+    BOOST_TEST(plugin_->get_config().size() == 1U);
+    BOOST_TEST(plugin_->get_config()["me"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_mode)
 {
-    plugin_->handle_mode(irccd_, {server_, "", "", "", "", "", ""});
+    plugin_->handle_mode(irccd_, {});
 
-    BOOST_TEST(server_->cqueue().size() == 1U);
-    BOOST_TEST(server_->cqueue()[0]["command"].get<std::string>() == "message");
-    BOOST_TEST(server_->cqueue()[0]["message"].get<std::string>() == "handle_mode");
-    BOOST_TEST(server_->cqueue()[0]["target"].get<std::string>() == "test");
+    BOOST_TEST(plugin_->get_config().size() == 1U);
+    BOOST_TEST(plugin_->get_config()["mode"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_names)
 {
-    plugin_->handle_names(irccd_, {server_, "", {}});
+    plugin_->handle_names(irccd_, {});
 
-    BOOST_TEST(server_->cqueue().size() == 1U);
-    BOOST_TEST(server_->cqueue()[0]["command"].get<std::string>() == "message");
-    BOOST_TEST(server_->cqueue()[0]["message"].get<std::string>() == "handle_names");
-    BOOST_TEST(server_->cqueue()[0]["target"].get<std::string>() == "test");
+    BOOST_TEST(plugin_->get_config().size() == 1U);
+    BOOST_TEST(plugin_->get_config()["names"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_nick)
 {
-    plugin_->handle_nick(irccd_, {server_, "", ""});
+    plugin_->handle_nick(irccd_, {});
 
-    BOOST_TEST(server_->cqueue().size() == 1U);
-    BOOST_TEST(server_->cqueue()[0]["command"].get<std::string>() == "message");
-    BOOST_TEST(server_->cqueue()[0]["message"].get<std::string>() == "handle_nick");
-    BOOST_TEST(server_->cqueue()[0]["target"].get<std::string>() == "test");
+    BOOST_TEST(plugin_->get_config().size() == 1U);
+    BOOST_TEST(plugin_->get_config()["nick"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_notice)
 {
-    plugin_->handle_notice(irccd_, {server_, "", "", ""});
+    plugin_->handle_notice(irccd_, {});
 
-    BOOST_TEST(server_->cqueue().size() == 1U);
-    BOOST_TEST(server_->cqueue()[0]["command"].get<std::string>() == "message");
-    BOOST_TEST(server_->cqueue()[0]["message"].get<std::string>() == "handle_notice");
-    BOOST_TEST(server_->cqueue()[0]["target"].get<std::string>() == "test");
+    BOOST_TEST(plugin_->get_config().size() == 1U);
+    BOOST_TEST(plugin_->get_config()["notice"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_part)
 {
-    plugin_->handle_part(irccd_, {server_, "", "", ""});
+    plugin_->handle_part(irccd_, {});
+
+    BOOST_TEST(plugin_->get_config().size() == 1U);
+    BOOST_TEST(plugin_->get_config()["part"] == "true");
+}
 
-    BOOST_TEST(server_->cqueue().size() == 1U);
-    BOOST_TEST(server_->cqueue()[0]["command"].get<std::string>() == "message");
-    BOOST_TEST(server_->cqueue()[0]["message"].get<std::string>() == "handle_part");
-    BOOST_TEST(server_->cqueue()[0]["target"].get<std::string>() == "test");
+BOOST_AUTO_TEST_CASE(handle_reload)
+{
+    plugin_->handle_reload(irccd_);
+
+    BOOST_TEST(plugin_->get_config().size() == 1U);
+    BOOST_TEST(plugin_->get_config()["reload"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_topic)
 {
-    plugin_->handle_topic(irccd_, {server_, "", "", ""});
+    plugin_->handle_topic(irccd_, {});
+
+    BOOST_TEST(plugin_->get_config().size() == 1U);
+    BOOST_TEST(plugin_->get_config()["topic"] == "true");
+}
 
-    BOOST_TEST(server_->cqueue().size() == 1U);
-    BOOST_TEST(server_->cqueue()[0]["command"].get<std::string>() == "message");
-    BOOST_TEST(server_->cqueue()[0]["message"].get<std::string>() == "handle_topic");
-    BOOST_TEST(server_->cqueue()[0]["target"].get<std::string>() == "test");
+BOOST_AUTO_TEST_CASE(handle_unload)
+{
+    plugin_->handle_unload(irccd_);
+
+    BOOST_TEST(plugin_->get_config().size() == 1U);
+    BOOST_TEST(plugin_->get_config()["unload"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_whois)
 {
-    plugin_->handle_whois(irccd_, {server_, {"", "", "", "", {}}});
+    plugin_->handle_whois(irccd_, {});
 
-    BOOST_TEST(server_->cqueue().size() == 1U);
-    BOOST_TEST(server_->cqueue()[0]["command"].get<std::string>() == "message");
-    BOOST_TEST(server_->cqueue()[0]["message"].get<std::string>() == "handle_whois");
-    BOOST_TEST(server_->cqueue()[0]["target"].get<std::string>() == "test");
+    BOOST_TEST(plugin_->get_config().size() == 1U);
+    BOOST_TEST(plugin_->get_config()["whois"] == "true");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/dynlib-plugin/test_plugin.cpp	Thu Apr 12 19:30:43 2018 +0200
+++ b/tests/src/libirccd/dynlib-plugin/test_plugin.cpp	Fri Apr 13 07:32:10 2018 +0200
@@ -23,88 +23,105 @@
 namespace irccd {
 
 class test_plugin : public plugin {
+private:
+    plugin_config config_;
+
 public:
     using plugin::plugin;
 
-    void handle_command(irccd&, const message_event& event) override
+    plugin_config get_config() override
     {
-        event.server->message("test", "handle_command");
+        return config_;
     }
 
-    void handle_connect(irccd&, const connect_event& event) override
+    void handle_command(irccd&, const message_event&) override
     {
-        event.server->message("test", "handle_connect");
+        config_["command"] = "true";
+    }
+
+    void handle_connect(irccd&, const connect_event&) override
+    {
+        config_["connect"] = "true";
     }
 
-    void handle_invite(irccd&, const invite_event& event) override
+    void handle_invite(irccd&, const invite_event&) override
     {
-        event.server->message("test", "handle_invite");
+        config_["invite"] = "true";
+    }
+
+    void handle_join(irccd&, const join_event&) override
+    {
+        config_["join"] = "true";
     }
 
-    void handle_join(irccd&, const join_event& event) override
+    void handle_kick(irccd&, const kick_event&) override
     {
-        event.server->message("test", "handle_join");
+        config_["kick"] = "true";
     }
 
-    void handle_kick(irccd&, const kick_event& event) override
+    void handle_load(irccd&) override
     {
-        event.server->message("test", "handle_kick");
+        config_["load"] = "true";
     }
 
-    void handle_message(irccd&, const message_event& event) override
+    void handle_message(irccd&, const message_event&) override
     {
-        event.server->message("test", "handle_message");
+        config_["message"] = "true";
     }
 
-    void handle_me(irccd&, const me_event& event) override
+    void handle_me(irccd&, const me_event&) override
     {
-        event.server->message("test", "handle_me");
+        config_["me"] = "true";
     }
 
-    void handle_mode(irccd&, const mode_event& event) override
+    void handle_mode(irccd&, const mode_event&) override
     {
-        event.server->message("test", "handle_mode");
+        config_["mode"] = "true";
     }
 
-    void handle_names(irccd&, const names_event& event) override
+    void handle_names(irccd&, const names_event&) override
     {
-        event.server->message("test", "handle_names");
+        config_["names"] = "true";
+    }
+
+    void handle_nick(irccd&, const nick_event&) override
+    {
+        config_["nick"] = "true";
     }
 
-    void handle_nick(irccd&, const nick_event& event) override
+    void handle_notice(irccd&, const notice_event&) override
     {
-        event.server->message("test", "handle_nick");
+        config_["notice"] = "true";
     }
 
-    void handle_notice(irccd&, const notice_event& event) override
+    void handle_part(irccd&, const part_event&) override
     {
-        event.server->message("test", "handle_notice");
+        config_["part"] = "true";
     }
 
-    void handle_part(irccd&, const part_event& event) override
+    void handle_reload(irccd&) override
     {
-        event.server->message("test", "handle_part");
+        config_["reload"] = "true";
     }
 
-    void handle_topic(irccd&, const topic_event& event) override
+    void handle_topic(irccd&, const topic_event&) override
     {
-        event.server->message("test", "handle_topic");
+        config_["topic"] = "true";
     }
 
-    void handle_whois(irccd&, const whois_event& event) override
+    void handle_unload(irccd&) override
     {
-        event.server->message("test", "handle_whois");
+        config_["unload"] = "true";
+    }
+
+    void handle_whois(irccd&, const whois_event&) override
+    {
+        config_["whois"] = "true";
     }
 };
 
-} // !irccd
-
-extern "C" {
+extern "C" BOOST_SYMBOL_EXPORT test_plugin irccd_plugin_test_plugin;
 
-BOOST_SYMBOL_EXPORT
-std::unique_ptr<irccd::plugin> irccd_testplugin_load(std::string name, std::string path)
-{
-    return std::make_unique<irccd::test_plugin>(name, path);
-}
+test_plugin irccd_plugin_test_plugin("test", "");
 
-} // !C
+} // !irccd