changeset 525:d070d33bf4a0

Plugin hangman: finally switch to boost
author David Demelier <markand@malikania.fr>
date Tue, 14 Nov 2017 20:13:56 +0100
parents ba81aeb514b8
children 5df38b4fbc55
files libirccd-js/irccd/js_plugin.hpp libirccd-test/CMakeLists.txt libirccd-test/irccd/plugin-tester.cpp libirccd-test/irccd/plugin-tester.hpp libirccd-test/irccd/plugin_test.cpp libirccd-test/irccd/plugin_test.hpp libirccd/irccd/config.hpp libirccd/irccd/irccd.hpp libirccd/irccd/service.cpp plugins/hangman/hangman.js tests/CMakeLists.txt tests/js-plugin/main.cpp tests/plugin-hangman/CMakeLists.txt tests/plugin-hangman/main.cpp tests/plugin-history/main.cpp tests/service-plugin/CMakeLists.txt tests/service-plugin/main.cpp
diffstat 17 files changed, 293 insertions(+), 460 deletions(-) [+]
line wrap: on
line diff
--- a/libirccd-js/irccd/js_plugin.hpp	Tue Nov 14 19:54:32 2017 +0100
+++ b/libirccd-js/irccd/js_plugin.hpp	Tue Nov 14 20:13:56 2017 +0100
@@ -250,9 +250,12 @@
  * \brief Implementation for searching Javascript plugins.
  */
 class js_plugin_loader : public plugin_loader {
+public:
+    using modules_t = std::vector<std::unique_ptr<module>>;
+
 private:
     irccd& irccd_;
-    std::vector<std::unique_ptr<module>> modules_;
+    modules_t modules_;
 
 public:
     /**
@@ -268,8 +271,29 @@
     ~js_plugin_loader() noexcept;
 
     /**
+     * Get the list of modules.
+     *
+     * \return the modules
+     */
+    inline const modules_t& modules() const noexcept
+    {
+        return modules_;
+    }
+
+    /**
+     * Overloaded function.
+     *
+     * \return the modules
+     */
+    inline modules_t& modules() noexcept
+    {
+        return modules_;
+    }
+
+    /**
      * Register a new module for loading new plugins.
      *
+     * \deprecated use modules() instead
      * \param module the module to add
      */
     void add_module(std::unique_ptr<module> module);
--- a/libirccd-test/CMakeLists.txt	Tue Nov 14 19:54:32 2017 +0100
+++ b/libirccd-test/CMakeLists.txt	Tue Nov 14 20:13:56 2017 +0100
@@ -25,8 +25,6 @@
         ${libirccd-test_SOURCE_DIR}/irccd/command-tester.hpp
         ${libirccd-test_SOURCE_DIR}/irccd/journal_server.cpp
         ${libirccd-test_SOURCE_DIR}/irccd/journal_server.hpp
-        $<$<BOOL:${HAVE_JS}>:${libirccd-test_SOURCE_DIR}/irccd/plugin-tester.cpp>
-        $<$<BOOL:${HAVE_JS}>:${libirccd-test_SOURCE_DIR}/irccd/plugin-tester.hpp>
         $<$<BOOL:${HAVE_JS}>:${libirccd-test_SOURCE_DIR}/irccd/plugin_test.cpp>
         $<$<BOOL:${HAVE_JS}>:${libirccd-test_SOURCE_DIR}/irccd/plugin_test.hpp>
         $<$<BOOL:${HAVE_JS}>:${libirccd-test_SOURCE_DIR}/irccd/js_test.hpp>
--- a/libirccd-test/irccd/plugin-tester.cpp	Tue Nov 14 19:54:32 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * plugin-tester.cpp -- test fixture helper for javascript plugins
- *
- * Copyright (c) 2013-2017 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "js_directory_module.hpp"
-#include "js_elapsed_timer_module.hpp"
-#include "js_file_module.hpp"
-#include "js_irccd_module.hpp"
-#include "js_logger_module.hpp"
-#include "js_plugin_module.hpp"
-#include "js_server_module.hpp"
-#include "js_system_module.hpp"
-#include "js_timer_module.hpp"
-#include "js_unicode_module.hpp"
-#include "js_util_module.hpp"
-#include "js_plugin.hpp"
-#include "plugin-tester.hpp"
-#include "service.hpp"
-
-namespace irccd {
-
-PluginTester::PluginTester()
-{
-    auto loader = std::make_unique<js_plugin_loader>(m_irccd);
-
-    loader->add_module(std::make_unique<js_irccd_module>());
-    loader->add_module(std::make_unique<js_directory_module>());
-    loader->add_module(std::make_unique<js_elapsed_timer_module>());
-    loader->add_module(std::make_unique<js_file_module>());
-    loader->add_module(std::make_unique<js_logger_module>());
-    loader->add_module(std::make_unique<js_plugin_module>());
-    loader->add_module(std::make_unique<js_server_module>());
-    loader->add_module(std::make_unique<js_system_module>());
-    loader->add_module(std::make_unique<js_timer_module>());
-    loader->add_module(std::make_unique<js_unicode_module>());
-    loader->add_module(std::make_unique<js_util_module>());
-
-    m_irccd.plugins().add_loader(std::move(loader));
-}
-
-} // !irccd
--- a/libirccd-test/irccd/plugin-tester.hpp	Tue Nov 14 19:54:32 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * plugin-tester.hpp -- test fixture helper for javascript plugins
- *
- * Copyright (c) 2013-2017 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IRCCD_PLUGIN_TESTER_HPP
-#define IRCCD_PLUGIN_TESTER_HPP
-
-#include <gtest/gtest.h>
-
-#include "irccd.hpp"
-
-namespace irccd {
-
-class PluginTester : public testing::Test {
-protected:
-    irccd m_irccd;
-
-public:
-    PluginTester();
-};
-
-} // !irccd
-
-#endif // !IRCCD_PLUGIN_TESTER_HPP
--- a/libirccd-test/irccd/plugin_test.cpp	Tue Nov 14 19:54:32 2017 +0100
+++ b/libirccd-test/irccd/plugin_test.cpp	Tue Nov 14 20:13:56 2017 +0100
@@ -16,6 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <cassert>
+
 #include <irccd/js_directory_module.hpp>
 #include <irccd/js_elapsed_timer_module.hpp>
 #include <irccd/js_file_module.hpp>
@@ -41,23 +43,24 @@
     log::set_verbose(false);
     log::set_logger(std::make_unique<log::silent_logger>());
 
-    js_plugin_loader loader(irccd_);
+    plugin_ = std::make_unique<js_plugin>(std::move(name), std::move(path));
 
-    loader.add_module(std::make_unique<js_irccd_module>());
-    loader.add_module(std::make_unique<js_directory_module>());
-    loader.add_module(std::make_unique<js_elapsed_timer_module>());
-    loader.add_module(std::make_unique<js_file_module>());
-    loader.add_module(std::make_unique<js_logger_module>());
-    loader.add_module(std::make_unique<js_plugin_module>());
-    loader.add_module(std::make_unique<js_server_module>());
-    loader.add_module(std::make_unique<js_system_module>());
-    loader.add_module(std::make_unique<js_timer_module>());
-    loader.add_module(std::make_unique<js_unicode_module>());
-    loader.add_module(std::make_unique<js_util_module>());
-
-    plugin_ = loader.open(name, path);
     irccd_.plugins().add(plugin_);
     irccd_.servers().add(server_);
+
+    js_irccd_module().load(irccd_, plugin_);
+    js_directory_module().load(irccd_, plugin_);
+    js_elapsed_timer_module().load(irccd_, plugin_);
+    js_file_module().load(irccd_, plugin_);
+    js_logger_module().load(irccd_, plugin_);
+    js_plugin_module().load(irccd_, plugin_);
+    js_server_module().load(irccd_, plugin_);
+    js_system_module().load(irccd_, plugin_);
+    js_timer_module().load(irccd_, plugin_);
+    js_unicode_module().load(irccd_, plugin_);
+    js_util_module().load(irccd_, plugin_);
+
+    plugin_->open();
 }
 
 } // !irccd
--- a/libirccd-test/irccd/plugin_test.hpp	Tue Nov 14 19:54:32 2017 +0100
+++ b/libirccd-test/irccd/plugin_test.hpp	Tue Nov 14 20:13:56 2017 +0100
@@ -25,7 +25,7 @@
  */
 
 #include "irccd.hpp"
-#include "plugin.hpp"
+#include "js_plugin.hpp"
 #include "journal_server.hpp"
 
 namespace irccd {
@@ -38,7 +38,7 @@
 class plugin_test {
 protected:
     irccd irccd_;
-    std::shared_ptr<plugin> plugin_;
+    std::shared_ptr<js_plugin> plugin_;
     std::shared_ptr<journal_server> server_;
 
 public:
--- a/libirccd/irccd/config.hpp	Tue Nov 14 19:54:32 2017 +0100
+++ b/libirccd/irccd/config.hpp	Tue Nov 14 20:13:56 2017 +0100
@@ -61,10 +61,11 @@
      *
      * \param path the path
      */
-    inline config(std::string path)
+    inline config(std::string path = "")
         : path_(std::move(path))
-        , document_(ini::read_file(path_))
     {
+        if (!path_.empty())
+            document_ = ini::read_file(path_);
     }
 
     /**
--- a/libirccd/irccd/irccd.hpp	Tue Nov 14 19:54:32 2017 +0100
+++ b/libirccd/irccd/irccd.hpp	Tue Nov 14 20:13:56 2017 +0100
@@ -30,6 +30,7 @@
 #include <mutex>
 #include <vector>
 
+#include "config.hpp"
 #include "net.hpp"
 #include "sysconfig.hpp"
 
@@ -50,14 +51,14 @@
  */
 class irccd {
 private:
+    // Configurations.
+    class config config_;
+
     // Main loop stuff.
     std::atomic<bool> running_{true};
     std::mutex mutex_;
     std::vector<std::function<void (irccd&)>> events_;
 
-    // Path to config.
-    std::string config_;
-
     // Services.
     std::shared_ptr<command_service> command_service_;
     std::shared_ptr<interrupt_service> itr_service_;
@@ -87,23 +88,23 @@
     ~irccd();
 
     /**
-     * Get the current configuration path.
+     * Get the current configuration.
      *
-     * \return the path
+     * \return the configuration
      */
-    inline const std::string& config() const noexcept
+    inline const class config& config() const noexcept
     {
         return config_;
     }
 
     /**
-     * Set the configuration path.
+     * Set the configuration.
      *
-     * \param path the new path
+     * \param cfg the new config
      */
-    inline void set_config(std::string path) noexcept
+    inline void set_config(class config cfg) noexcept
     {
-        config_ = std::move(path);
+        config_ = std::move(cfg);
     }
 
     /**
--- a/libirccd/irccd/service.cpp	Tue Nov 14 19:54:32 2017 +0100
+++ b/libirccd/irccd/service.cpp	Tue Nov 14 20:13:56 2017 +0100
@@ -200,10 +200,8 @@
 
 plugin_paths plugin_service::paths(const std::string& id)
 {
-    class config cfg(irccd_.config());
-
-    auto defaults = to_map<plugin_paths>(cfg, "paths");
-    auto paths = to_map<plugin_paths>(cfg, string_util::sprintf("paths.%s", id));
+    auto defaults = to_map<plugin_paths>(irccd_.config(), "paths");
+    auto paths = to_map<plugin_paths>(irccd_.config(), string_util::sprintf("paths.%s", id));
 
     // Fill defaults paths.
     if (!defaults.count("cache"))
--- a/plugins/hangman/hangman.js	Tue Nov 14 19:54:32 2017 +0100
+++ b/plugins/hangman/hangman.js	Tue Nov 14 20:13:56 2017 +0100
@@ -289,7 +289,6 @@
 
 function onLoad()
 {
-    Logger.warning("TAMERE");
     Hangman.loadFormats();
     Hangman.loadWords();
 }
--- a/tests/CMakeLists.txt	Tue Nov 14 19:54:32 2017 +0100
+++ b/tests/CMakeLists.txt	Tue Nov 14 20:13:56 2017 +0100
@@ -63,9 +63,6 @@
     add_subdirectory(rules)
     add_subdirectory(util)
 
-    # Services
-    #add_subdirectory(service-plugin)
-
     # JS API
     if (HAVE_JS)
         # Javascript plugin object.
@@ -83,7 +80,7 @@
         add_subdirectory(js-util)
         add_subdirectory(plugin-ask)
         add_subdirectory(plugin-auth)
-        #add_subdirectory(plugin-hangman)
+        add_subdirectory(plugin-hangman)
         add_subdirectory(plugin-history)
         add_subdirectory(plugin-logger)
         add_subdirectory(plugin-plugin)
--- a/tests/js-plugin/main.cpp	Tue Nov 14 19:54:32 2017 +0100
+++ b/tests/js-plugin/main.cpp	Tue Nov 14 20:13:56 2017 +0100
@@ -99,7 +99,7 @@
 
     js_plugin_loader_test()
     {
-        irccd_.set_config(CMAKE_CURRENT_SOURCE_DIR "/irccd.conf");
+        irccd_.set_config(config(CMAKE_CURRENT_SOURCE_DIR "/irccd.conf"));
 
         auto loader = std::make_unique<js_plugin_loader>(irccd_);
 
--- a/tests/plugin-hangman/CMakeLists.txt	Tue Nov 14 19:54:32 2017 +0100
+++ b/tests/plugin-hangman/CMakeLists.txt	Tue Nov 14 20:13:56 2017 +0100
@@ -18,7 +18,12 @@
 
 irccd_define_test(
     NAME plugin-hangman
-    SOURCES main.cpp words.conf wordlist_fix_644.conf
+    SOURCES
+        main.cpp
+        words.conf
+        wordlist_fix_644.conf
     LIBRARIES libirccd
-    FLAGS PLUGINDIR=\"${IRCCD_FAKEROOTDIR}/${WITH_PLUGINDIR}\"
+    FLAGS
+        PLUGIN_NAME="hangman"
+        PLUGIN_PATH="${CMAKE_SOURCE_DIR}/plugins/hangman/hangman.js"
 )
--- a/tests/plugin-hangman/main.cpp	Tue Nov 14 19:54:32 2017 +0100
+++ b/tests/plugin-hangman/main.cpp	Tue Nov 14 20:13:56 2017 +0100
@@ -19,52 +19,23 @@
 #include <unordered_map>
 #include <unordered_set>
 
-#include <gtest/gtest.h>
+#define BOOST_TEST_MODULE "Hangman plugin"
+#include <boost/test/unit_test.hpp>
 
 #include <irccd/irccd.hpp>
 #include <irccd/server.hpp>
 #include <irccd/service.hpp>
-#include <irccd/string_util.hpp>
-
-#include "plugin-tester.hpp"
-
-int main() { }
-
-#if 0
-
-using namespace irccd;
 
-class ServerTest : public server {
-private:
-    std::string m_last;
+#include "plugin_test.hpp"
 
-public:
-    inline ServerTest()
-        : server("test")
-    {
-    }
+namespace irccd {
 
-    inline const std::string &last() const noexcept
-    {
-        return m_last;
-    }
-
-    void message(std::string target, std::string message) override
+class hangman_test : public plugin_test {
+public:
+    hangman_test()
+        : plugin_test(PLUGIN_NAME, PLUGIN_PATH)
     {
-        m_last = string_util::join({target, message});
-    }
-};
-
-class HangmanTest : public PluginTester {
-protected:
-    std::shared_ptr<ServerTest> m_server;
-    std::shared_ptr<plugin> m_plugin;
-
-public:
-    HangmanTest()
-        : m_server(std::make_shared<ServerTest>())
-    {
-        m_irccd.plugins().set_formats("hangman", {
+        plugin_->set_formats({
             { "asked", "asked=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{letter}" },
             { "dead", "dead=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{word}" },
             { "found", "found=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{word}" },
@@ -81,170 +52,281 @@
     {
         // Add file if not there.
         if (config.count("file") == 0)
-            config.emplace("file", SOURCEDIR "/words.conf");
+            config.emplace("file", CMAKE_CURRENT_SOURCE_DIR "/words.conf");
 
-        m_irccd.plugins().set_config("hangman", config);
-        m_irccd.plugins().load("hangman", CMAKE_SOURCE_DIR "/plugins/hangman/hangman.js");
-        m_plugin = m_irccd.plugins().require("hangman");
+        plugin_->set_config(config);
+        plugin_->on_load(irccd_);
     }
 };
 
-TEST_F(HangmanTest, asked)
+BOOST_FIXTURE_TEST_SUITE(hangman_test_suite, hangman_test)
+
+BOOST_AUTO_TEST_CASE(asked)
 {
     load({{ "collaborative", "false" }});
 
-    m_plugin->on_command(m_irccd, {m_server, "jean!jean@localhost", "#hangman", ""});
-    m_plugin->on_message(m_irccd, {m_server, "jean!jean@localhost", "#hangman", "s"});
-    m_plugin->on_message(m_irccd, {m_server, "jean!jean@localhost", "#hangman", "s"});
+    plugin_->on_command(irccd_, {server_, "jean!jean@localhost", "#hangman", ""});
+
+    auto cmd = server_->cqueue().back();
+
+    BOOST_TEST(cmd["command"].get<std::string>() == "message");
+    BOOST_TEST(cmd["target"].get<std::string>() == "#hangman");
+    BOOST_TEST(cmd["message"].get<std::string>() == "start=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:_ _ _");
+
+    plugin_->on_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "s"});
+    cmd = server_->cqueue().back();
 
-    ASSERT_EQ("#hangman:asked=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s", m_server->last());
+    BOOST_TEST(cmd["command"].get<std::string>() == "message");
+    BOOST_TEST(cmd["target"].get<std::string>() == "#hangman");
+    BOOST_TEST(cmd["message"].get<std::string>() == "found=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s _ _");
+
+    plugin_->on_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "s"});
+    cmd = server_->cqueue().back();
+
+    BOOST_TEST(cmd["command"].get<std::string>() == "message");
+    BOOST_TEST(cmd["target"].get<std::string>() == "#hangman");
+    BOOST_TEST(cmd["message"].get<std::string>() == "asked=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s");
 }
 
-TEST_F(HangmanTest, dead)
+BOOST_AUTO_TEST_CASE(dead)
 {
     load({{ "collaborative", "false" }});
 
-    m_plugin->on_command(m_irccd, {m_server, "jean!jean@localhost", "#hangman", ""});
-    m_plugin->on_message(m_irccd, {m_server, "jean!jean@localhost", "#hangman", "a"});
-    m_plugin->on_message(m_irccd, {m_server, "jean!jean@localhost", "#hangman", "b"});
-    m_plugin->on_message(m_irccd, {m_server, "jean!jean@localhost", "#hangman", "c"});
-    m_plugin->on_message(m_irccd, {m_server, "jean!jean@localhost", "#hangman", "d"});
-    m_plugin->on_message(m_irccd, {m_server, "jean!jean@localhost", "#hangman", "e"});
-    m_plugin->on_message(m_irccd, {m_server, "jean!jean@localhost", "#hangman", "f"});
-    m_plugin->on_message(m_irccd, {m_server, "jean!jean@localhost", "#hangman", "g"});
-    m_plugin->on_message(m_irccd, {m_server, "jean!jean@localhost", "#hangman", "h"});
-    m_plugin->on_message(m_irccd, {m_server, "jean!jean@localhost", "#hangman", "i"});
-    m_plugin->on_message(m_irccd, {m_server, "jean!jean@localhost", "#hangman", "j"});
+    plugin_->on_command(irccd_, {server_, "jean!jean@localhost", "#hangman", ""});
+    plugin_->on_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "a"});
+    plugin_->on_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "b"});
+    plugin_->on_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "c"});
+    plugin_->on_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "d"});
+    plugin_->on_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "e"});
+    plugin_->on_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "f"});
+    plugin_->on_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "g"});
+    plugin_->on_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "h"});
+    plugin_->on_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "i"});
+    plugin_->on_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "j"});
 
-    ASSERT_EQ("#hangman:dead=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:sky", m_server->last());
+    auto cmd = server_->cqueue().back();
+
+    BOOST_TEST(cmd["command"].get<std::string>() == "message");
+    BOOST_TEST(cmd["target"].get<std::string>() == "#hangman");
+    BOOST_TEST(cmd["message"].get<std::string>() == "dead=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:sky");
 }
 
-TEST_F(HangmanTest, found)
+
+BOOST_AUTO_TEST_CASE(found)
 {
     load({{ "collaborative", "false" }});
 
-    m_plugin->on_command(m_irccd, {m_server, "jean!jean@localhost", "#hangman", ""});
-    m_plugin->on_message(m_irccd, {m_server, "jean!jean@localhost", "#hangman", "s"});
+    plugin_->on_command(irccd_, {server_, "jean!jean@localhost", "#hangman", ""});
+    plugin_->on_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "s"});
 
-    ASSERT_EQ("#hangman:found=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s _ _", m_server->last());
+    auto cmd = server_->cqueue().back();
+
+    BOOST_TEST(cmd["command"].get<std::string>() == "message");
+    BOOST_TEST(cmd["target"].get<std::string>() == "#hangman");
+    BOOST_TEST(cmd["message"].get<std::string>() == "found=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s _ _");
 }
 
-TEST_F(HangmanTest, start)
+BOOST_AUTO_TEST_CASE(start)
 {
     load();
 
-    m_plugin->on_command(m_irccd, {m_server, "jean!jean@localhost", "#hangman", ""});
+    plugin_->on_command(irccd_, {server_, "jean!jean@localhost", "#hangman", ""});
+
+    auto cmd = server_->cqueue().back();
 
-    ASSERT_EQ("#hangman:start=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:_ _ _", m_server->last());
+    BOOST_TEST(cmd["command"].get<std::string>() == "message");
+    BOOST_TEST(cmd["target"].get<std::string>() == "#hangman");
+    BOOST_TEST(cmd["message"].get<std::string>() == "start=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:_ _ _");
 }
 
-TEST_F(HangmanTest, win1)
+BOOST_AUTO_TEST_CASE(win1)
 {
     load({{ "collaborative", "false" }});
 
-    m_plugin->on_command(m_irccd, {m_server, "jean!jean@localhost", "#hangman", ""});
-    m_plugin->on_message(m_irccd, {m_server, "jean!jean@localhost", "#hangman", "s"});
-    m_plugin->on_message(m_irccd, {m_server, "jean!jean@localhost", "#hangman", "k"});
-    m_plugin->on_message(m_irccd, {m_server, "jean!jean@localhost", "#hangman", "y"});
+    plugin_->on_command(irccd_, {server_, "jean!jean@localhost", "#hangman", ""});
+    plugin_->on_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "s"});
+    plugin_->on_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "k"});
+    plugin_->on_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "y"});
 
-    ASSERT_EQ("#hangman:win=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:sky", m_server->last());
+    auto cmd = server_->cqueue().back();
+
+    BOOST_TEST(cmd["command"].get<std::string>() == "message");
+    BOOST_TEST(cmd["target"].get<std::string>() == "#hangman");
+    BOOST_TEST(cmd["message"].get<std::string>() == "win=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:sky");
 }
 
-TEST_F(HangmanTest, win2)
+BOOST_AUTO_TEST_CASE(win2)
 {
     load({{ "collaborative", "false" }});
 
-    m_plugin->on_command(m_irccd, {m_server, "jean!jean@localhost", "#hangman", ""});
-    m_plugin->on_command(m_irccd, {m_server, "jean!jean@localhost", "#hangman", "sky"});
+    plugin_->on_command(irccd_, {server_, "jean!jean@localhost", "#hangman", ""});
+    plugin_->on_command(irccd_, {server_, "jean!jean@localhost", "#hangman", "sky"});
 
-    ASSERT_EQ("#hangman:win=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:sky", m_server->last());
+    auto cmd = server_->cqueue().back();
+
+    BOOST_TEST(cmd["command"].get<std::string>() == "message");
+    BOOST_TEST(cmd["target"].get<std::string>() == "#hangman");
+    BOOST_TEST(cmd["message"].get<std::string>() == "win=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:sky");
 }
 
-TEST_F(HangmanTest, wrongLetter)
+BOOST_AUTO_TEST_CASE(wrong_letter)
 {
     load();
 
-    m_plugin->on_command(m_irccd, {m_server, "jean!jean@localhost", "#hangman", ""});
-    m_plugin->on_message(m_irccd, {m_server, "jean!jean@localhost", "#hangman", "x"});
+    plugin_->on_command(irccd_, {server_, "jean!jean@localhost", "#hangman", ""});
+    plugin_->on_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "x"});
 
-    ASSERT_EQ("#hangman:wrong-letter=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:x", m_server->last());
+    auto cmd = server_->cqueue().back();
+
+    BOOST_TEST(cmd["command"].get<std::string>() == "message");
+    BOOST_TEST(cmd["target"].get<std::string>() == "#hangman");
+    BOOST_TEST(cmd["message"].get<std::string>() == "wrong-letter=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:x");
 }
 
-TEST_F(HangmanTest, wrongWord)
+BOOST_AUTO_TEST_CASE(wrongWord)
 {
     load();
 
-    m_plugin->on_command(m_irccd, {m_server, "jean!jean@localhost", "#hangman", ""});
-    m_plugin->on_command(m_irccd, {m_server, "jean!jean@localhost", "#hangman", "cheese"});
+    plugin_->on_command(irccd_, {server_, "jean!jean@localhost", "#hangman", ""});
+    plugin_->on_command(irccd_, {server_, "jean!jean@localhost", "#hangman", "cheese"});
 
-    ASSERT_EQ("#hangman:wrong-word=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:cheese", m_server->last());
+    auto cmd = server_->cqueue().back();
+
+    BOOST_TEST(cmd["command"].get<std::string>() == "message");
+    BOOST_TEST(cmd["target"].get<std::string>() == "#hangman");
+    BOOST_TEST(cmd["message"].get<std::string>() == "wrong-word=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:cheese");
 }
 
-TEST_F(HangmanTest, collaborativeDisabled)
+BOOST_AUTO_TEST_CASE(collaborative_disabled)
 {
     // Disable collaborative mode.
     load({{ "collaborative", "false" }});
 
-    m_plugin->on_command(m_irccd, {m_server, "jean!jean@localhost", "#hangman", ""});
-    m_plugin->on_message(m_irccd, {m_server, "jean!jean@localhost", "#hangman", "s"});
-    ASSERT_EQ("#hangman:found=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s _ _", m_server->last());
-    m_plugin->on_message(m_irccd, {m_server, "jean!jean@localhost", "#hangman", "k"});
-    ASSERT_EQ("#hangman:found=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s k _", m_server->last());
+    plugin_->on_command(irccd_, {server_, "jean!jean@localhost", "#hangman", ""});
+    plugin_->on_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "s"});
+
+    auto cmd = server_->cqueue().back();
+
+    BOOST_TEST(cmd["command"].get<std::string>() == "message");
+    BOOST_TEST(cmd["target"].get<std::string>() == "#hangman");
+    BOOST_TEST(cmd["message"].get<std::string>() == "found=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s _ _");
+
+    plugin_->on_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "k"});
+    cmd = server_->cqueue().back();
+
+    BOOST_TEST(cmd["command"].get<std::string>() == "message");
+    BOOST_TEST(cmd["target"].get<std::string>() == "#hangman");
+    BOOST_TEST(cmd["message"].get<std::string>() == "found=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s k _");
 }
 
-TEST_F(HangmanTest, collaborativeEnabled)
+BOOST_AUTO_TEST_CASE(collaborative_enabled)
 {
     // Enable collaborative mode.
     load({{ "collaborative", "true" }});
 
-    m_plugin->on_command(m_irccd, {m_server, "jean!jean@localhost", "#hangman", ""});
-    m_plugin->on_message(m_irccd, {m_server, "jean!jean@localhost", "#hangman", "s"});
-    ASSERT_EQ("#hangman:found=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s _ _", m_server->last());
-    m_plugin->on_message(m_irccd, {m_server, "jean!jean@localhost", "#hangman", "k"});
-    ASSERT_EQ("#hangman:wrong-player=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:k", m_server->last());
-    m_plugin->on_message(m_irccd, {m_server, "francis!francis@localhost", "#hangman", "k"});
-    ASSERT_EQ("#hangman:found=hangman:!hangman:test:#hangman:francis!francis@localhost:francis:s k _", m_server->last());
+    plugin_->on_command(irccd_, {server_, "jean!jean@localhost", "#hangman", ""});
+    plugin_->on_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "s"});
+
+    auto cmd = server_->cqueue().back();
+
+    BOOST_TEST(cmd["command"].get<std::string>() == "message");
+    BOOST_TEST(cmd["target"].get<std::string>() == "#hangman");
+    BOOST_TEST(cmd["message"].get<std::string>() == "found=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s _ _");
+
+    plugin_->on_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "k"});
+    cmd = server_->cqueue().back();
+
+    BOOST_TEST(cmd["command"].get<std::string>() == "message");
+    BOOST_TEST(cmd["target"].get<std::string>() == "#hangman");
+    BOOST_TEST(cmd["message"].get<std::string>() == "wrong-player=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:k");
+
+    plugin_->on_message(irccd_, {server_, "francis!francis@localhost", "#hangman", "k"});
+    cmd = server_->cqueue().back();
+
+    BOOST_TEST(cmd["command"].get<std::string>() == "message");
+    BOOST_TEST(cmd["target"].get<std::string>() == "#hangman");
+    BOOST_TEST(cmd["message"].get<std::string>() == "found=hangman:!hangman:test:#hangman:francis!francis@localhost:francis:s k _");
 }
 
-TEST_F(HangmanTest, case_fix_642)
+BOOST_AUTO_TEST_CASE(case_fix_642)
 {
     load();
 
-    m_plugin->on_command(m_irccd, {m_server, "jean!jean@localhost", "#hangman", ""});
-    m_plugin->on_message(m_irccd, {m_server, "jean!jean@localhost", "#HANGMAN", "s"});
-    ASSERT_EQ("#hangman:found=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s _ _", m_server->last());
-    m_plugin->on_message(m_irccd, {m_server, "jean!jean@localhost", "#HaNGMaN", "k"});
-    ASSERT_EQ("#hangman:wrong-player=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:k", m_server->last());
-    m_plugin->on_message(m_irccd, {m_server, "francis!francis@localhost", "#hAngmAn", "k"});
-    ASSERT_EQ("#hangman:found=hangman:!hangman:test:#hangman:francis!francis@localhost:francis:s k _", m_server->last());
+    plugin_->on_command(irccd_, {server_, "jean!jean@localhost", "#hangman", ""});
+    plugin_->on_message(irccd_, {server_, "jean!jean@localhost", "#HANGMAN", "s"});
+
+    auto cmd = server_->cqueue().back();
+
+    BOOST_TEST(cmd["command"].get<std::string>() == "message");
+    BOOST_TEST(cmd["target"].get<std::string>() == "#hangman");
+    BOOST_TEST(cmd["message"].get<std::string>() == "found=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s _ _");
+
+    plugin_->on_message(irccd_, {server_, "jean!jean@localhost", "#HaNGMaN", "k"});
+    cmd = server_->cqueue().back();
+
+    BOOST_TEST(cmd["command"].get<std::string>() == "message");
+    BOOST_TEST(cmd["target"].get<std::string>() == "#hangman");
+    BOOST_TEST(cmd["message"].get<std::string>() == "wrong-player=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:k");
+
+    plugin_->on_message(irccd_, {server_, "francis!francis@localhost", "#hAngmAn", "k"});
+    cmd = server_->cqueue().back();
+
+    BOOST_TEST(cmd["command"].get<std::string>() == "message");
+    BOOST_TEST(cmd["target"].get<std::string>() == "#hangman");
+    BOOST_TEST(cmd["message"].get<std::string>() == "found=hangman:!hangman:test:#hangman:francis!francis@localhost:francis:s k _");
 }
 
-TEST_F(HangmanTest, query)
+BOOST_AUTO_TEST_CASE(query)
 {
     load();
 
     // Query mode is never collaborative.
-    m_plugin->on_query_command(m_irccd, {m_server, "jean!jean@localhost", ""});
-    ASSERT_EQ("jean:start=hangman:!hangman:test:jean:jean!jean@localhost:jean:_ _ _", m_server->last());
-    m_plugin->on_query(m_irccd, {m_server, "jean!jean@localhost", "s"});
-    ASSERT_EQ("jean:found=hangman:!hangman:test:jean:jean!jean@localhost:jean:s _ _", m_server->last());
-    m_plugin->on_query(m_irccd, {m_server, "jean!jean@localhost", "k"});
-    ASSERT_EQ("jean:found=hangman:!hangman:test:jean:jean!jean@localhost:jean:s k _", m_server->last());
-    m_plugin->on_query_command(m_irccd, {m_server, "jean!jean@localhost", "sky"});
-    ASSERT_EQ("jean:win=hangman:!hangman:test:jean:jean!jean@localhost:jean:sky", m_server->last());
+    plugin_->on_query_command(irccd_, {server_, "jean!jean@localhost", ""});
+
+    auto cmd = server_->cqueue().back();
+
+    BOOST_TEST(cmd["command"].get<std::string>() == "message");
+    BOOST_TEST(cmd["target"].get<std::string>() == "jean");
+    BOOST_TEST(cmd["message"].get<std::string>() == "start=hangman:!hangman:test:jean:jean!jean@localhost:jean:_ _ _");
+
+    plugin_->on_query(irccd_, {server_, "jean!jean@localhost", "s"});
+    cmd = server_->cqueue().back();
+
+    BOOST_TEST(cmd["command"].get<std::string>() == "message");
+    BOOST_TEST(cmd["target"].get<std::string>() == "jean");
+    BOOST_TEST(cmd["message"].get<std::string>() == "found=hangman:!hangman:test:jean:jean!jean@localhost:jean:s _ _");
+
+    plugin_->on_query(irccd_, {server_, "jean!jean@localhost", "k"});
+    cmd = server_->cqueue().back();
+
+    BOOST_TEST(cmd["command"].get<std::string>() == "message");
+    BOOST_TEST(cmd["target"].get<std::string>() == "jean");
+    BOOST_TEST(cmd["message"].get<std::string>() == "found=hangman:!hangman:test:jean:jean!jean@localhost:jean:s k _");
+
+    plugin_->on_query_command(irccd_, {server_, "jean!jean@localhost", "sky"});
+    cmd = server_->cqueue().back();
+
+    BOOST_TEST(cmd["command"].get<std::string>() == "message");
+    BOOST_TEST(cmd["target"].get<std::string>() == "jean");
+    BOOST_TEST(cmd["message"].get<std::string>() == "win=hangman:!hangman:test:jean:jean!jean@localhost:jean:sky");
 }
 
-TEST_F(HangmanTest, running)
+BOOST_AUTO_TEST_CASE(running)
 {
     load();
 
-    m_plugin->on_command(m_irccd, {m_server, "jean!jean@localhost", "#hangman", ""});
-    m_plugin->on_message(m_irccd, {m_server, "jean!jean@localhost", "#hangman", "y"});
-    m_plugin->on_command(m_irccd, {m_server, "jean!jean@localhost", "#hangman", ""});
-    ASSERT_EQ("#hangman:running=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:_ _ y", m_server->last());
+    plugin_->on_command(irccd_, {server_, "jean!jean@localhost", "#hangman", ""});
+    plugin_->on_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "y"});
+    plugin_->on_command(irccd_, {server_, "jean!jean@localhost", "#hangman", ""});
+
+    auto cmd = server_->cqueue().back();
+
+    BOOST_TEST(cmd["command"].get<std::string>() == "message");
+    BOOST_TEST(cmd["target"].get<std::string>() == "#hangman");
+    BOOST_TEST(cmd["message"].get<std::string>() == "running=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:_ _ y");
 }
 
-TEST_F(HangmanTest, wordlist_fix_644)
+BOOST_AUTO_TEST_CASE(wordlist_fix_644)
 {
     /*
      * To be sure that the selection use the same list, we create a list of
@@ -255,51 +337,46 @@
      *
      * This is not very accurate but it's better than nothing.
      */
-    load({{ "file", SOURCEDIR "/wordlist_fix_644.conf" }});
+    load({{ "file", CMAKE_CURRENT_SOURCE_DIR "/wordlist_fix_644.conf" }});
 
     std::unordered_map<unsigned, std::string> words{
-        { 14, "abc"     },
-        { 16, "abcd"    },
-        { 18, "abcde"   }
+        { 5, "abc"     },
+        { 7, "abcd"    },
+        { 9, "abcde"   }
     };
     std::unordered_set<unsigned> found;
 
-    m_plugin->set_formats({
+    plugin_->set_formats({
         { "start", "#{word}" }
     });
 
     unsigned last, current;
 
     // 1. Initial game + finish.
-    m_plugin->on_command(m_irccd, {m_server, "jean!jean@localhost", "#hangman", ""});
-    last = m_server->last().length();
+    plugin_->on_command(irccd_, {server_, "jean!jean@localhost", "#hangman", ""});
+    last = server_->cqueue().back()["message"].get<std::string>().length();
     found.insert(last);
-    m_plugin->on_command(m_irccd, {m_server, "jean!jean@localhost", "#hangman", words[last]});
+    plugin_->on_command(irccd_, {server_, "jean!jean@localhost", "#hangman", words[last]});
 
     // 2. Current must not be the last one.
-    m_plugin->on_command(m_irccd, {m_server, "jean!jean@localhost", "#hangman", ""});
-    current = m_server->last().length();
+    plugin_->on_command(irccd_, {server_, "jean!jean@localhost", "#hangman", ""});
+    current = server_->cqueue().back()["message"].get<std::string>().length();
 
-    ASSERT_NE(last, current);
-    ASSERT_EQ(0U, found.count(current));
+    BOOST_TEST(last != current);
+    BOOST_TEST(0U == found.count(current));
 
     found.insert(current);
     last = current;
-    m_plugin->on_command(m_irccd, {m_server, "jean!jean@localhost", "#hangman", words[current]});
+    plugin_->on_command(irccd_, {server_, "jean!jean@localhost", "#hangman", words[current]});
 
     // 3. Last word must be the one that is kept into the map.
-    m_plugin->on_command(m_irccd, {m_server, "jean!jean@localhost", "#hangman", ""});
-    current = m_server->last().length();
+    plugin_->on_command(irccd_, {server_, "jean!jean@localhost", "#hangman", ""});
+    current = server_->cqueue().back()["message"].get<std::string>().length();
 
-    ASSERT_NE(last, current);
-    ASSERT_EQ(0U, found.count(current));
+    BOOST_TEST(last != current);
+    BOOST_TEST(0U == found.count(current));
 }
 
-int main(int argc, char **argv)
-{
-    testing::InitGoogleTest(&argc, argv);
+BOOST_AUTO_TEST_SUITE_END()
 
-    return RUN_ALL_TESTS();
-}
-
-#endif
+} // !irccd
--- a/tests/plugin-history/main.cpp	Tue Nov 14 19:54:32 2017 +0100
+++ b/tests/plugin-history/main.cpp	Tue Nov 14 20:13:56 2017 +0100
@@ -138,7 +138,7 @@
     // Random caps.
     plugin_->on_command(irccd_, {server_, "destructor!dst@localhost", "#HiSToRy", "said JeaN"});
 
-    cmd = server_->cqueue().front();
+    cmd = server_->cqueue().back();
 
     BOOST_REQUIRE_EQUAL(cmd["command"].get<std::string>(), "message");
     BOOST_REQUIRE_EQUAL(cmd["target"].get<std::string>(), "#history");
--- a/tests/service-plugin/CMakeLists.txt	Tue Nov 14 19:54:32 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-#
-# CMakeLists.txt -- CMake build system for irccd
-#
-# Copyright (c) 2013-2017 David Demelier <markand@malikania.fr>
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-
-irccd_define_test(
-    NAME service-plugin
-    SOURCES main.cpp
-    LIBRARIES libirccd
-)
-
--- a/tests/service-plugin/main.cpp	Tue Nov 14 19:54:32 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,153 +0,0 @@
-/*
- * main.cpp -- test irccd rules
- *
- * Copyright (c) 2013-2017 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <gtest/gtest.h>
-
-#include <irccd/irccd.hpp>
-#include <irccd/service.hpp>
-
-namespace irccd {
-
-TEST(service_plugin, default_paths)
-{
-    irccd irccd;
-
-    irccd.plugins().set_paths({
-        { "cache",  "/var/cache/irccd"          },
-        { "config", "/etc/irccd"                },
-        { "data",   "/usr/local/share/irccd"    }
-    });
-
-    auto paths = irccd.plugins().paths("ask");
-
-    ASSERT_EQ("/var/cache/irccd/plugin/ask", paths["cache"]);
-    ASSERT_EQ("/etc/irccd/plugin/ask", paths["config"]);
-    ASSERT_EQ("/usr/local/share/irccd/plugin/ask", paths["data"]);
-}
-
-TEST(service_plugin, override_cache)
-{
-    irccd irccd;
-
-    irccd.plugins().set_paths({
-        { "cache",  "/var/cache/irccd"          },
-        { "config", "/etc/irccd"                },
-        { "data",   "/usr/local/share/irccd"    }
-    });
-    irccd.plugins().set_paths("ask", {
-        { "cache",  "/opt/cache/ask"            }
-    });
-
-    auto paths = irccd.plugins().paths("ask");
-
-    ASSERT_EQ("/opt/cache/ask", paths["cache"]);
-    ASSERT_EQ("/etc/irccd/plugin/ask", paths["config"]);
-    ASSERT_EQ("/usr/local/share/irccd/plugin/ask", paths["data"]);
-}
-
-TEST(service_plugin, override_config)
-{
-    irccd irccd;
-
-    irccd.plugins().set_paths({
-        { "cache",  "/var/cache/irccd"          },
-        { "config", "/etc/irccd"                },
-        { "data",   "/usr/local/share/irccd"    }
-    });
-    irccd.plugins().set_paths("ask", {
-        { "config", "/opt/config/ask"           }
-    });
-
-    auto paths = irccd.plugins().paths("ask");
-
-    ASSERT_EQ("/var/cache/irccd/plugin/ask", paths["cache"]);
-    ASSERT_EQ("/opt/config/ask", paths["config"]);
-    ASSERT_EQ("/usr/local/share/irccd/plugin/ask", paths["data"]);
-}
-
-TEST(service_plugin, override_data)
-{
-    irccd irccd;
-
-    irccd.plugins().set_paths({
-        { "cache",  "/var/cache/irccd"          },
-        { "config", "/etc/irccd"                },
-        { "data",   "/usr/local/share/irccd"    }
-    });
-    irccd.plugins().set_paths("ask", {
-        { "data",   "/opt/data/ask"             }
-    });
-
-    auto paths = irccd.plugins().paths("ask");
-
-    ASSERT_EQ("/var/cache/irccd/plugin/ask", paths["cache"]);
-    ASSERT_EQ("/etc/irccd/plugin/ask", paths["config"]);
-    ASSERT_EQ("/opt/data/ask", paths["data"]);
-}
-
-TEST(service_plugin, override_all)
-{
-    irccd irccd;
-
-    irccd.plugins().set_paths({
-        { "cache",  "/var/cache/irccd"          },
-        { "config", "/etc/irccd"                },
-        { "data",   "/usr/local/share/irccd"    }
-    });
-    irccd.plugins().set_paths("ask", {
-        { "cache",  "/opt/cache/ask"            },
-        { "config", "/opt/config/ask"           },
-        { "data",   "/opt/data/ask"             }
-    });
-
-    auto paths = irccd.plugins().paths("ask");
-
-    ASSERT_EQ("/opt/cache/ask", paths["cache"]);
-    ASSERT_EQ("/opt/config/ask", paths["config"]);
-    ASSERT_EQ("/opt/data/ask", paths["data"]);
-}
-
-TEST(service_plugin, extra_paths)
-{
-    irccd irccd;
-
-    irccd.plugins().set_paths({
-        { "cache",  "/var/cache/irccd"          },
-        { "config", "/etc/irccd"                },
-        { "data",   "/usr/local/share/irccd"    }
-    });
-    irccd.plugins().set_paths("ask", {
-        { "extra",  "/opt/magic"                }
-    });
-
-    auto paths = irccd.plugins().paths("ask");
-
-    ASSERT_EQ("/var/cache/irccd/plugin/ask", paths["cache"]);
-    ASSERT_EQ("/etc/irccd/plugin/ask", paths["config"]);
-    ASSERT_EQ("/usr/local/share/irccd/plugin/ask", paths["data"]);
-    ASSERT_EQ("/opt/magic", paths["extra"]);
-}
-
-} // !irccd
-
-int main(int argc, char **argv)
-{
-    testing::InitGoogleTest(&argc, argv);
-
-    return RUN_ALL_TESTS();
-}