changeset 604:9d4da384f5d6

Tests: move libirccd-test to test/ folder, closes #750
author David Demelier <markand@malikania.fr>
date Fri, 08 Dec 2017 19:32:10 +0100
parents 986ed3a7575d
children 1cbdfc765d95
files libirccd-js/irccd/js/js_plugin.hpp libirccd-test/CMakeLists.txt libirccd-test/irccd/command_test.hpp libirccd-test/irccd/journal_server.cpp libirccd-test/irccd/journal_server.hpp libirccd-test/irccd/js_test.hpp libirccd-test/irccd/plugin_test.cpp libirccd-test/irccd/plugin_test.hpp libirccd-test/irccd/test/command_test.hpp libirccd-test/irccd/test/journal_server.cpp libirccd-test/irccd/test/journal_server.hpp libirccd-test/irccd/test/js_test.hpp libirccd-test/irccd/test/plugin_test.cpp libirccd-test/irccd/test/plugin_test.hpp libirccd/CMakeLists.txt tests/src/directory-jsapi/main.cpp tests/src/dynlib-plugin/main.cpp tests/src/dynlib-plugin/test_plugin.cpp tests/src/elapsedtimer-jsapi/main.cpp tests/src/file-jsapi/main.cpp tests/src/irccd-jsapi/main.cpp tests/src/logger-jsapi/main.cpp tests/src/plugin-ask/main.cpp tests/src/plugin-auth/main.cpp tests/src/plugin-config-command/main.cpp tests/src/plugin-hangman/main.cpp tests/src/plugin-history/main.cpp tests/src/plugin-info-command/main.cpp tests/src/plugin-list-command/main.cpp tests/src/plugin-load-command/main.cpp tests/src/plugin-logger/main.cpp tests/src/plugin-plugin/main.cpp tests/src/plugin-reload-command/main.cpp tests/src/plugin-unload-command/main.cpp tests/src/rule-add-command/main.cpp tests/src/rule-edit-command/main.cpp tests/src/rule-info-command/main.cpp tests/src/rule-list-command/main.cpp tests/src/rule-move-command/main.cpp tests/src/rule-remove-command/main.cpp tests/src/server-connect-command/main.cpp tests/src/server-disconnect-command/main.cpp tests/src/server-info-command/main.cpp tests/src/server-invite-command/main.cpp tests/src/server-join-command/main.cpp tests/src/server-kick-command/main.cpp tests/src/server-list-command/main.cpp tests/src/server-me-command/main.cpp tests/src/server-message-command/main.cpp tests/src/server-mode-command/main.cpp tests/src/server-nick-command/main.cpp tests/src/server-notice-command/main.cpp tests/src/server-part-command/main.cpp tests/src/server-reconnect-command/main.cpp tests/src/server-topic-command/main.cpp tests/src/system-jsapi/main.cpp tests/src/timer-jsapi/main.cpp tests/src/unicode-jsapi/main.cpp tests/src/util-jsapi/main.cpp
diffstat 59 files changed, 732 insertions(+), 730 deletions(-) [+]
line wrap: on
line diff
--- a/libirccd-js/irccd/js/js_plugin.hpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/libirccd-js/irccd/js/js_plugin.hpp	Fri Dec 08 19:32:10 2017 +0100
@@ -26,8 +26,9 @@
 
 #include <vector>
 
+#include <irccd/daemon/plugin.hpp>
+
 #include "duktape.hpp"
-#include "plugin.hpp"
 
 namespace irccd {
 
--- a/libirccd-test/CMakeLists.txt	Fri Dec 08 08:41:29 2017 +0100
+++ b/libirccd-test/CMakeLists.txt	Fri Dec 08 19:32:10 2017 +0100
@@ -21,19 +21,19 @@
 irccd_define_library(
     TARGET libirccd-test
     SOURCES
-        ${libirccd-test_SOURCE_DIR}/irccd/command_test.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_test.cpp>
-        $<$<BOOL:${HAVE_JS}>:${libirccd-test_SOURCE_DIR}/irccd/plugin_test.hpp>
-        $<$<BOOL:${HAVE_JS}>:${libirccd-test_SOURCE_DIR}/irccd/js_test.hpp>
+        ${libirccd-test_SOURCE_DIR}/irccd/test/command_test.hpp
+        ${libirccd-test_SOURCE_DIR}/irccd/test/journal_server.cpp
+        ${libirccd-test_SOURCE_DIR}/irccd/test/journal_server.hpp
+        $<$<BOOL:${HAVE_JS}>:${libirccd-test_SOURCE_DIR}/irccd/test/plugin_test.cpp>
+        $<$<BOOL:${HAVE_JS}>:${libirccd-test_SOURCE_DIR}/irccd/test/plugin_test.hpp>
+        $<$<BOOL:${HAVE_JS}>:${libirccd-test_SOURCE_DIR}/irccd/test/js_test.hpp>
         $<$<BOOL:${HAVE_JS}>:${libirccd-test_SOURCE_DIR}/irccd/plugin_test.js>
     LIBRARIES
         $<$<BOOL:${HAVE_JS}>:libirccd-js>
         libirccd
         libirccdctl
     PUBLIC_INCLUDES
-        $<BUILD_INTERFACE:${libirccd-test_SOURCE_DIR}/irccd>
+        $<BUILD_INTERFACE:${libirccd-test_SOURCE_DIR}>
     FLAGS
         $<BUILD_INTERFACE:IRCCD_PLUGIN_TEST="${libirccd-test_SOURCE_DIR}/irccd/plugin_test.js">
 )
--- a/libirccd-test/irccd/command_test.hpp	Fri Dec 08 08:41:29 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,121 +0,0 @@
-/*
- * command_test.hpp -- test fixture helper for transport commands
- *
- * 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_TEST_COMMAND_TEST_HPP
-#define IRCCD_TEST_COMMAND_TEST_HPP
-
-#include <memory>
-
-#include <irccd/daemon/command_service.hpp>
-#include <irccd/daemon/ip_transport_server.hpp>
-#include <irccd/daemon/irccd.hpp>
-#include <irccd/daemon/logger.hpp>
-#include <irccd/daemon/transport_service.hpp>
-
-#include <irccd/ctl/ip_connection.hpp>
-#include <irccd/ctl/controller.hpp>
-
-namespace irccd {
-
-template <typename... Commands>
-class command_test {
-private:
-    template <typename Command>
-    inline void add()
-    {
-        daemon_->commands().add(std::make_unique<Command>());
-    }
-
-    template <typename C1, typename C2, typename... Tail>
-    inline void add()
-    {
-        add<C1>();
-        add<C2, Tail...>();
-    }
-
-protected:
-    boost::asio::io_service service_;
-    boost::asio::deadline_timer timer_;
-
-    // daemon stuff.
-    std::unique_ptr<irccd> daemon_;
-
-    // controller stuff.
-    std::unique_ptr<ctl::connection> conn_;
-    std::unique_ptr<ctl::controller> ctl_;
-
-    command_test();
-
-    template <typename Condition>
-    void wait_for(Condition&& cond)
-    {
-        service_.reset();
-
-        while (!cond())
-            service_.poll();
-    }
-};
-
-template <typename... Commands>
-command_test<Commands...>::command_test()
-    : timer_(service_)
-    , daemon_(std::make_unique<irccd>(service_))
-{
-    using boost::asio::ip::tcp;
-
-    // Bind to a random port.
-    tcp::endpoint ep(tcp::v4(), 0);
-    tcp::acceptor acc(service_, ep);
-
-    // Connect to the local bound port.
-    conn_ = std::make_unique<ctl::ip_connection>(service_, "127.0.0.1", acc.local_endpoint().port());
-    ctl_ = std::make_unique<ctl::controller>(*conn_);
-
-    // Add the server and the command.
-    add<Commands...>();
-    daemon_->set_log(std::make_unique<silent_logger>());
-    daemon_->transports().add(std::make_unique<ip_transport_server>(std::move(acc)));
-
-    timer_.expires_from_now(boost::posix_time::seconds(10));
-    timer_.async_wait([] (auto code) {
-        if (!code)
-            throw make_error_code(boost::system::errc::timed_out);
-    });
-
-    bool connected = false;
-
-    ctl_->connect([&] (auto code, auto) {
-        if (code)
-            throw code;
-
-        connected = true;
-        timer_.cancel();
-    });
-
-    while (!connected)
-        service_.poll();
-
-    service_.reset();
-
-    if (!connected)
-        throw std::runtime_error("unable to connect");
-}
-
-} // !irccd
-
-#endif // !IRCCD_TEST_COMMAND_TEST_HPP
--- a/libirccd-test/irccd/journal_server.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +0,0 @@
-/*
- * journal_server.cpp -- journaled server that logs every command
- *
- * 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 "journal_server.hpp"
-
-namespace irccd {
-
-void journal_server::reconnect() noexcept
-{
-    cqueue_.push_back({
-        { "command",    "reconnect" }
-    });
-}
-
-void journal_server::invite(std::string target, std::string channel)
-{
-    cqueue_.push_back({
-        { "command",    "invite"    },
-        { "target",     target      },
-        { "channel",    channel     }
-    });
-}
-
-void journal_server::join(std::string channel, std::string password)
-{
-    cqueue_.push_back({
-        { "command",    "join"      },
-        { "channel",    channel     },
-        { "password",   password    }
-    });
-}
-
-void journal_server::kick(std::string target, std::string channel, std::string reason)
-{
-    cqueue_.push_back({
-        { "command",    "kick"      },
-        { "target",     target      },
-        { "channel",    channel     },
-        { "reason",     reason      }
-    });
-}
-
-void journal_server::me(std::string target, std::string message)
-{
-    cqueue_.push_back({
-        { "command",    "me"        },
-        { "target",     target      },
-        { "message",    message     }
-    });
-}
-
-void journal_server::message(std::string target, std::string message)
-{
-    cqueue_.push_back({
-        { "command",    "message"   },
-        { "target",     target      },
-        { "message",    message     }
-    });
-}
-
-void journal_server::mode(std::string channel,
-                          std::string mode,
-                          std::string limit,
-                          std::string user,
-                          std::string mask)
-{
-    cqueue_.push_back({
-        { "command",    "mode"      },
-        { "channel",    channel     },
-        { "mode",       mode        },
-        { "limit",      limit       },
-        { "user",       user        },
-        { "mask",       mask        }
-    });
-}
-
-void journal_server::names(std::string channel)
-{
-    cqueue_.push_back({
-        { "command",    "names"     },
-        { "channel",    channel     }
-    });
-}
-
-void journal_server::notice(std::string target, std::string message)
-{
-    cqueue_.push_back({
-        { "command",    "notice"    },
-        { "target",     target      },
-        { "message",    message     }
-    });
-}
-
-void journal_server::part(std::string channel, std::string reason)
-{
-    cqueue_.push_back({
-        { "command",    "part"      },
-        { "channel",    channel     },
-        { "reason",     reason      }
-    });
-}
-
-void journal_server::send(std::string raw)
-{
-    cqueue_.push_back({
-        { "command",    "send"      },
-        { "raw",        raw         }
-    });
-}
-
-void journal_server::topic(std::string channel, std::string topic)
-{
-    cqueue_.push_back({
-        { "command",    "topic"     },
-        { "channel",    channel     },
-        { "topic",      topic       }
-    });
-}
-
-void journal_server::whois(std::string target)
-{
-    cqueue_.push_back({
-        { "command",    "whois"     },
-        { "target",     target      }
-    });
-}
-
-} // !irccd
--- a/libirccd-test/irccd/journal_server.hpp	Fri Dec 08 08:41:29 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,175 +0,0 @@
-/*
- * journal_server.hpp -- journaled server that logs every command
- *
- * 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_TEST_JOURNAL_SERVER_HPP
-#define IRCCD_TEST_JOURNAL_SERVER_HPP
-
-#include <deque>
-
-#include <json.hpp>
-
-#include <server.hpp>
-
-/**
- * \file journal_server.hpp
- * \brief Journaled server that logs every command.
- */
-
-namespace irccd {
-
-/**
- * \brief Journaled server that logs every command.
- *
- * This class is used for unit testing, it logs every user command such as
- * message, invite.
- *
- * Each command store exactly the function name, parameter names in a json
- * object in a FIFO queue, don't forget to clear that queue when you don't need
- * it anymore.
- *
- * Example with message:
- *
- * ````json
- * {
- *     "command": "message",
- *     "target": "<argument value>",
- *     "message": "<argument value>"
- * }
- * ````
- *
- * \see cqueue()
- */
-class journal_server : public server {
-private:
-    std::deque<nlohmann::json> cqueue_;
-
-public:
-    /**
-     * Inherited constructors.
-     */
-    using server::server;
-
-    /**
-     * Access the command queue.
-     *
-     * \return the queue
-     */
-    inline const std::deque<nlohmann::json>& cqueue() const noexcept
-    {
-        return cqueue_;
-    }
-
-    /**
-     * Overloaded function.
-     *
-     * \return the queue
-     */
-    inline std::deque<nlohmann::json>& cqueue() noexcept
-    {
-        return cqueue_;
-    }
-
-    /**
-     * \copydoc server::connect
-     */
-    void connect() noexcept override
-    {
-        // avoid connecting.
-    }
-
-    /**
-     * \copydoc server::connect
-     */
-    void disconnect() noexcept override
-    {
-        // avoid disconnecting.
-    }
-
-    /**
-     * \copydoc server::reconnect
-     */
-    void reconnect() noexcept override;
-
-    /**
-     * \copydoc server::invite
-     */
-    void invite(std::string target, std::string channel) override;
-
-    /**
-     * \copydoc server::join
-     */
-    void join(std::string channel, std::string password = "") override;
-
-    /**
-     * \copydoc server::kick
-     */
-    void kick(std::string target, std::string channel, std::string reason = "") override;
-
-    /**
-     * \copydoc server::me
-     */
-    void me(std::string target, std::string message) override;
-
-    /**
-     * \copydoc server::message
-     */
-    void message(std::string target, std::string message) override;
-
-    /**
-     * \copydoc server::mode
-     */
-    void mode(std::string channel,
-              std::string mode,
-              std::string limit = "",
-              std::string user = "",
-              std::string mask = "") override;
-
-    /**
-     * \copydoc server::names
-     */
-    void names(std::string channel) override;
-
-    /**
-     * \copydoc server::notice
-     */
-    void notice(std::string target, std::string message) override;
-
-    /**
-     * \copydoc server::part
-     */
-    void part(std::string channel, std::string reason = "") override;
-
-    /**
-     * \copydoc server::send
-     */
-    void send(std::string raw) override;
-
-    /**
-     * \copydoc server::topic
-     */
-    void topic(std::string channel, std::string topic) override;
-
-    /**
-     * \copydoc server::whois
-     */
-    void whois(std::string target) override;
-};
-
-} // !irccd
-
-#endif // !IRCCD_TEST_JOURNAL_SERVER_HPP
--- a/libirccd-test/irccd/js_test.hpp	Fri Dec 08 08:41:29 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * js_test.hpp -- test fixture helper for Javascript modules
- *
- * 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_TEST_JS_TEST_HPP
-#define IRCCD_TEST_JS_TEST_HPP
-
-/**
- * \file js_test.hpp
- * \brief Test fixture helper for Javascript modules.
- */
-
-#include <boost/asio.hpp>
-
-#include <irccd/daemon/irccd.hpp>
-#include <irccd/daemon/logger.hpp>
-
-#include <irccd/js/js_plugin.hpp>
-#include <irccd/js/irccd_jsapi.hpp>
-
-#include "journal_server.hpp"
-
-namespace irccd {
-
-/**
- * \brief Test fixture helper for Javascript modules.
- */
-template <typename... Modules>
-class js_test {
-private:
-    template <typename Module>
-    inline void add()
-    {
-        Module().load(irccd_, plugin_);
-    }
-
-    template <typename M1, typename M2, typename... Tail>
-    inline void add()
-    {
-        add<M1>();
-        add<M2, Tail...>();
-    }
-
-public:
-    boost::asio::io_service service_;
-    irccd irccd_{service_};                     //!< Irccd instance.
-    std::shared_ptr<js_plugin> plugin_;         //!< Javascript plugin.
-    std::shared_ptr<journal_server> server_;    //!< A journal server.
-
-    /**
-     * Constructor.
-     *
-     * Create a server and a test plugin.
-     */
-    js_test(const std::string& plugin_path = IRCCD_PLUGIN_TEST)
-        : plugin_(new js_plugin("test", plugin_path))
-        , server_(new journal_server(service_, "test"))
-    {
-        irccd_.set_log(std::make_unique<silent_logger>());
-
-        // Irccd is mandatory at the moment.
-        add<irccd_jsapi>();
-        add<Modules...>();
-
-        // Add some CMake variables.
-        duk_push_string(plugin_->context(), CMAKE_BINARY_DIR);
-        duk_put_global_string(plugin_->context(), "CMAKE_BINARY_DIR");
-        duk_push_string(plugin_->context(), CMAKE_SOURCE_DIR);
-        duk_put_global_string(plugin_->context(), "CMAKE_SOURCE_DIR");
-        duk_push_string(plugin_->context(), CMAKE_CURRENT_BINARY_DIR);
-        duk_put_global_string(plugin_->context(), "CMAKE_CURRENT_BINARY_DIR");
-        duk_push_string(plugin_->context(), CMAKE_CURRENT_SOURCE_DIR);
-        duk_put_global_string(plugin_->context(), "CMAKE_CURRENT_SOURCE_DIR");
-    }
-};
-
-} // !irccd
-
-#endif // !IRCCD_TEST_JS_TEST_HPP
--- a/libirccd-test/irccd/plugin_test.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * plugin_test.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 <cassert>
-
-#include <irccd/daemon/logger.hpp>
-#include <irccd/daemon/plugin_service.hpp>
-#include <irccd/daemon/server_service.hpp>
-
-#include <irccd/js/directory_jsapi.hpp>
-#include <irccd/js/elapsed_timer_jsapi.hpp>
-#include <irccd/js/file_jsapi.hpp>
-#include <irccd/js/irccd_jsapi.hpp>
-#include <irccd/js/js_plugin.hpp>
-#include <irccd/js/logger_jsapi.hpp>
-#include <irccd/js/plugin_jsapi.hpp>
-#include <irccd/js/server_jsapi.hpp>
-#include <irccd/js/system_jsapi.hpp>
-#include <irccd/js/timer_jsapi.hpp>
-#include <irccd/js/unicode_jsapi.hpp>
-#include <irccd/js/util_jsapi.hpp>
-
-#include "plugin_test.hpp"
-
-namespace irccd {
-
-plugin_test::plugin_test(std::string name, std::string path)
-    : server_(std::make_shared<journal_server>(service_, "test"))
-{
-    server_->set_nickname("irccd");
-    plugin_ = std::make_unique<js_plugin>(std::move(name), std::move(path));
-
-    irccd_.log().set_verbose(false);
-    irccd_.set_log(std::make_unique<silent_logger>());
-    irccd_.plugins().add(plugin_);
-    irccd_.servers().add(server_);
-
-    irccd_jsapi().load(irccd_, plugin_);
-    directory_jsapi().load(irccd_, plugin_);
-    elapsed_timer_jsapi().load(irccd_, plugin_);
-    file_jsapi().load(irccd_, plugin_);
-    logger_jsapi().load(irccd_, plugin_);
-    plugin_jsapi().load(irccd_, plugin_);
-    server_jsapi().load(irccd_, plugin_);
-    system_jsapi().load(irccd_, plugin_);
-    timer_jsapi().load(irccd_, plugin_);
-    unicode_jsapi().load(irccd_, plugin_);
-    util_jsapi().load(irccd_, plugin_);
-
-    plugin_->open();
-}
-
-} // !irccd
--- a/libirccd-test/irccd/plugin_test.hpp	Fri Dec 08 08:41:29 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * plugin_test.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_TEST_PLUGIN_TEST_HPP
-#define IRCCD_TEST_PLUGIN_TEST_HPP
-
-/**
- * \file plugin_test.hpp
- * \brief test fixture helper for Javascript plugins.
- */
-
-#include <boost/asio/io_service.hpp>
-
-#include <js/js_plugin.hpp>
-
-#include "irccd.hpp"
-#include "journal_server.hpp"
-
-namespace irccd {
-
-/**
- * \brief test fixture helper for Javascript plugins.
- *
- * Holds a plugin that is opened (but not loaded).
- */
-class plugin_test {
-protected:
-    boost::asio::io_service service_;
-    irccd irccd_{service_};
-    std::shared_ptr<js_plugin> plugin_;
-    std::shared_ptr<journal_server> server_;
-
-public:
-    /**
-     * Construct the fixture test.
-     *
-     * \param name the plugin name (e.g. ask)
-     * \param path the full plugin path (e.g. /usr/libexec/irccd/plugins/ask.js)
-     */
-    plugin_test(std::string name, std::string path);
-};
-
-} // !irccd
-
-#endif // !IRCCD_TEST_PLUGIN_TESTER_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libirccd-test/irccd/test/command_test.hpp	Fri Dec 08 19:32:10 2017 +0100
@@ -0,0 +1,121 @@
+/*
+ * command_test.hpp -- test fixture helper for transport commands
+ *
+ * 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_TEST_COMMAND_TEST_HPP
+#define IRCCD_TEST_COMMAND_TEST_HPP
+
+#include <memory>
+
+#include <irccd/daemon/command_service.hpp>
+#include <irccd/daemon/ip_transport_server.hpp>
+#include <irccd/daemon/irccd.hpp>
+#include <irccd/daemon/logger.hpp>
+#include <irccd/daemon/transport_service.hpp>
+
+#include <irccd/ctl/ip_connection.hpp>
+#include <irccd/ctl/controller.hpp>
+
+namespace irccd {
+
+template <typename... Commands>
+class command_test {
+private:
+    template <typename Command>
+    inline void add()
+    {
+        daemon_->commands().add(std::make_unique<Command>());
+    }
+
+    template <typename C1, typename C2, typename... Tail>
+    inline void add()
+    {
+        add<C1>();
+        add<C2, Tail...>();
+    }
+
+protected:
+    boost::asio::io_service service_;
+    boost::asio::deadline_timer timer_;
+
+    // daemon stuff.
+    std::unique_ptr<irccd> daemon_;
+
+    // controller stuff.
+    std::unique_ptr<ctl::connection> conn_;
+    std::unique_ptr<ctl::controller> ctl_;
+
+    command_test();
+
+    template <typename Condition>
+    void wait_for(Condition&& cond)
+    {
+        service_.reset();
+
+        while (!cond())
+            service_.poll();
+    }
+};
+
+template <typename... Commands>
+command_test<Commands...>::command_test()
+    : timer_(service_)
+    , daemon_(std::make_unique<irccd>(service_))
+{
+    using boost::asio::ip::tcp;
+
+    // Bind to a random port.
+    tcp::endpoint ep(tcp::v4(), 0);
+    tcp::acceptor acc(service_, ep);
+
+    // Connect to the local bound port.
+    conn_ = std::make_unique<ctl::ip_connection>(service_, "127.0.0.1", acc.local_endpoint().port());
+    ctl_ = std::make_unique<ctl::controller>(*conn_);
+
+    // Add the server and the command.
+    add<Commands...>();
+    daemon_->set_log(std::make_unique<silent_logger>());
+    daemon_->transports().add(std::make_unique<ip_transport_server>(std::move(acc)));
+
+    timer_.expires_from_now(boost::posix_time::seconds(10));
+    timer_.async_wait([] (auto code) {
+        if (!code)
+            throw make_error_code(boost::system::errc::timed_out);
+    });
+
+    bool connected = false;
+
+    ctl_->connect([&] (auto code, auto) {
+        if (code)
+            throw code;
+
+        connected = true;
+        timer_.cancel();
+    });
+
+    while (!connected)
+        service_.poll();
+
+    service_.reset();
+
+    if (!connected)
+        throw std::runtime_error("unable to connect");
+}
+
+} // !irccd
+
+#endif // !IRCCD_TEST_COMMAND_TEST_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libirccd-test/irccd/test/journal_server.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -0,0 +1,143 @@
+/*
+ * journal_server.cpp -- journaled server that logs every command
+ *
+ * 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 "journal_server.hpp"
+
+namespace irccd {
+
+void journal_server::reconnect() noexcept
+{
+    cqueue_.push_back({
+        { "command",    "reconnect" }
+    });
+}
+
+void journal_server::invite(std::string target, std::string channel)
+{
+    cqueue_.push_back({
+        { "command",    "invite"    },
+        { "target",     target      },
+        { "channel",    channel     }
+    });
+}
+
+void journal_server::join(std::string channel, std::string password)
+{
+    cqueue_.push_back({
+        { "command",    "join"      },
+        { "channel",    channel     },
+        { "password",   password    }
+    });
+}
+
+void journal_server::kick(std::string target, std::string channel, std::string reason)
+{
+    cqueue_.push_back({
+        { "command",    "kick"      },
+        { "target",     target      },
+        { "channel",    channel     },
+        { "reason",     reason      }
+    });
+}
+
+void journal_server::me(std::string target, std::string message)
+{
+    cqueue_.push_back({
+        { "command",    "me"        },
+        { "target",     target      },
+        { "message",    message     }
+    });
+}
+
+void journal_server::message(std::string target, std::string message)
+{
+    cqueue_.push_back({
+        { "command",    "message"   },
+        { "target",     target      },
+        { "message",    message     }
+    });
+}
+
+void journal_server::mode(std::string channel,
+                          std::string mode,
+                          std::string limit,
+                          std::string user,
+                          std::string mask)
+{
+    cqueue_.push_back({
+        { "command",    "mode"      },
+        { "channel",    channel     },
+        { "mode",       mode        },
+        { "limit",      limit       },
+        { "user",       user        },
+        { "mask",       mask        }
+    });
+}
+
+void journal_server::names(std::string channel)
+{
+    cqueue_.push_back({
+        { "command",    "names"     },
+        { "channel",    channel     }
+    });
+}
+
+void journal_server::notice(std::string target, std::string message)
+{
+    cqueue_.push_back({
+        { "command",    "notice"    },
+        { "target",     target      },
+        { "message",    message     }
+    });
+}
+
+void journal_server::part(std::string channel, std::string reason)
+{
+    cqueue_.push_back({
+        { "command",    "part"      },
+        { "channel",    channel     },
+        { "reason",     reason      }
+    });
+}
+
+void journal_server::send(std::string raw)
+{
+    cqueue_.push_back({
+        { "command",    "send"      },
+        { "raw",        raw         }
+    });
+}
+
+void journal_server::topic(std::string channel, std::string topic)
+{
+    cqueue_.push_back({
+        { "command",    "topic"     },
+        { "channel",    channel     },
+        { "topic",      topic       }
+    });
+}
+
+void journal_server::whois(std::string target)
+{
+    cqueue_.push_back({
+        { "command",    "whois"     },
+        { "target",     target      }
+    });
+}
+
+} // !irccd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libirccd-test/irccd/test/journal_server.hpp	Fri Dec 08 19:32:10 2017 +0100
@@ -0,0 +1,175 @@
+/*
+ * journal_server.hpp -- journaled server that logs every command
+ *
+ * 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_TEST_JOURNAL_SERVER_HPP
+#define IRCCD_TEST_JOURNAL_SERVER_HPP
+
+#include <deque>
+
+#include <json.hpp>
+
+#include <irccd/daemon/server.hpp>
+
+/**
+ * \file journal_server.hpp
+ * \brief Journaled server that logs every command.
+ */
+
+namespace irccd {
+
+/**
+ * \brief Journaled server that logs every command.
+ *
+ * This class is used for unit testing, it logs every user command such as
+ * message, invite.
+ *
+ * Each command store exactly the function name, parameter names in a json
+ * object in a FIFO queue, don't forget to clear that queue when you don't need
+ * it anymore.
+ *
+ * Example with message:
+ *
+ * ````json
+ * {
+ *     "command": "message",
+ *     "target": "<argument value>",
+ *     "message": "<argument value>"
+ * }
+ * ````
+ *
+ * \see cqueue()
+ */
+class journal_server : public server {
+private:
+    std::deque<nlohmann::json> cqueue_;
+
+public:
+    /**
+     * Inherited constructors.
+     */
+    using server::server;
+
+    /**
+     * Access the command queue.
+     *
+     * \return the queue
+     */
+    inline const std::deque<nlohmann::json>& cqueue() const noexcept
+    {
+        return cqueue_;
+    }
+
+    /**
+     * Overloaded function.
+     *
+     * \return the queue
+     */
+    inline std::deque<nlohmann::json>& cqueue() noexcept
+    {
+        return cqueue_;
+    }
+
+    /**
+     * \copydoc server::connect
+     */
+    void connect() noexcept override
+    {
+        // avoid connecting.
+    }
+
+    /**
+     * \copydoc server::connect
+     */
+    void disconnect() noexcept override
+    {
+        // avoid disconnecting.
+    }
+
+    /**
+     * \copydoc server::reconnect
+     */
+    void reconnect() noexcept override;
+
+    /**
+     * \copydoc server::invite
+     */
+    void invite(std::string target, std::string channel) override;
+
+    /**
+     * \copydoc server::join
+     */
+    void join(std::string channel, std::string password = "") override;
+
+    /**
+     * \copydoc server::kick
+     */
+    void kick(std::string target, std::string channel, std::string reason = "") override;
+
+    /**
+     * \copydoc server::me
+     */
+    void me(std::string target, std::string message) override;
+
+    /**
+     * \copydoc server::message
+     */
+    void message(std::string target, std::string message) override;
+
+    /**
+     * \copydoc server::mode
+     */
+    void mode(std::string channel,
+              std::string mode,
+              std::string limit = "",
+              std::string user = "",
+              std::string mask = "") override;
+
+    /**
+     * \copydoc server::names
+     */
+    void names(std::string channel) override;
+
+    /**
+     * \copydoc server::notice
+     */
+    void notice(std::string target, std::string message) override;
+
+    /**
+     * \copydoc server::part
+     */
+    void part(std::string channel, std::string reason = "") override;
+
+    /**
+     * \copydoc server::send
+     */
+    void send(std::string raw) override;
+
+    /**
+     * \copydoc server::topic
+     */
+    void topic(std::string channel, std::string topic) override;
+
+    /**
+     * \copydoc server::whois
+     */
+    void whois(std::string target) override;
+};
+
+} // !irccd
+
+#endif // !IRCCD_TEST_JOURNAL_SERVER_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libirccd-test/irccd/test/js_test.hpp	Fri Dec 08 19:32:10 2017 +0100
@@ -0,0 +1,93 @@
+/*
+ * js_test.hpp -- test fixture helper for Javascript modules
+ *
+ * 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_TEST_JS_TEST_HPP
+#define IRCCD_TEST_JS_TEST_HPP
+
+/**
+ * \file js_test.hpp
+ * \brief Test fixture helper for Javascript modules.
+ */
+
+#include <boost/asio.hpp>
+
+#include <irccd/daemon/irccd.hpp>
+#include <irccd/daemon/logger.hpp>
+
+#include <irccd/js/js_plugin.hpp>
+#include <irccd/js/irccd_jsapi.hpp>
+
+#include "journal_server.hpp"
+
+namespace irccd {
+
+/**
+ * \brief Test fixture helper for Javascript modules.
+ */
+template <typename... Modules>
+class js_test {
+private:
+    template <typename Module>
+    inline void add()
+    {
+        Module().load(irccd_, plugin_);
+    }
+
+    template <typename M1, typename M2, typename... Tail>
+    inline void add()
+    {
+        add<M1>();
+        add<M2, Tail...>();
+    }
+
+public:
+    boost::asio::io_service service_;
+    irccd irccd_{service_};                     //!< Irccd instance.
+    std::shared_ptr<js_plugin> plugin_;         //!< Javascript plugin.
+    std::shared_ptr<journal_server> server_;    //!< A journal server.
+
+    /**
+     * Constructor.
+     *
+     * Create a server and a test plugin.
+     */
+    js_test(const std::string& plugin_path = IRCCD_PLUGIN_TEST)
+        : plugin_(new js_plugin("test", plugin_path))
+        , server_(new journal_server(service_, "test"))
+    {
+        irccd_.set_log(std::make_unique<silent_logger>());
+
+        // Irccd is mandatory at the moment.
+        add<irccd_jsapi>();
+        add<Modules...>();
+
+        // Add some CMake variables.
+        duk_push_string(plugin_->context(), CMAKE_BINARY_DIR);
+        duk_put_global_string(plugin_->context(), "CMAKE_BINARY_DIR");
+        duk_push_string(plugin_->context(), CMAKE_SOURCE_DIR);
+        duk_put_global_string(plugin_->context(), "CMAKE_SOURCE_DIR");
+        duk_push_string(plugin_->context(), CMAKE_CURRENT_BINARY_DIR);
+        duk_put_global_string(plugin_->context(), "CMAKE_CURRENT_BINARY_DIR");
+        duk_push_string(plugin_->context(), CMAKE_CURRENT_SOURCE_DIR);
+        duk_put_global_string(plugin_->context(), "CMAKE_CURRENT_SOURCE_DIR");
+    }
+};
+
+} // !irccd
+
+#endif // !IRCCD_TEST_JS_TEST_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libirccd-test/irccd/test/plugin_test.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -0,0 +1,68 @@
+/*
+ * plugin_test.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 <cassert>
+
+#include <irccd/daemon/logger.hpp>
+#include <irccd/daemon/plugin_service.hpp>
+#include <irccd/daemon/server_service.hpp>
+
+#include <irccd/js/directory_jsapi.hpp>
+#include <irccd/js/elapsed_timer_jsapi.hpp>
+#include <irccd/js/file_jsapi.hpp>
+#include <irccd/js/irccd_jsapi.hpp>
+#include <irccd/js/js_plugin.hpp>
+#include <irccd/js/logger_jsapi.hpp>
+#include <irccd/js/plugin_jsapi.hpp>
+#include <irccd/js/server_jsapi.hpp>
+#include <irccd/js/system_jsapi.hpp>
+#include <irccd/js/timer_jsapi.hpp>
+#include <irccd/js/unicode_jsapi.hpp>
+#include <irccd/js/util_jsapi.hpp>
+
+#include "plugin_test.hpp"
+
+namespace irccd {
+
+plugin_test::plugin_test(std::string name, std::string path)
+    : server_(std::make_shared<journal_server>(service_, "test"))
+{
+    server_->set_nickname("irccd");
+    plugin_ = std::make_unique<js_plugin>(std::move(name), std::move(path));
+
+    irccd_.log().set_verbose(false);
+    irccd_.set_log(std::make_unique<silent_logger>());
+    irccd_.plugins().add(plugin_);
+    irccd_.servers().add(server_);
+
+    irccd_jsapi().load(irccd_, plugin_);
+    directory_jsapi().load(irccd_, plugin_);
+    elapsed_timer_jsapi().load(irccd_, plugin_);
+    file_jsapi().load(irccd_, plugin_);
+    logger_jsapi().load(irccd_, plugin_);
+    plugin_jsapi().load(irccd_, plugin_);
+    server_jsapi().load(irccd_, plugin_);
+    system_jsapi().load(irccd_, plugin_);
+    timer_jsapi().load(irccd_, plugin_);
+    unicode_jsapi().load(irccd_, plugin_);
+    util_jsapi().load(irccd_, plugin_);
+
+    plugin_->open();
+}
+
+} // !irccd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libirccd-test/irccd/test/plugin_test.hpp	Fri Dec 08 19:32:10 2017 +0100
@@ -0,0 +1,61 @@
+/*
+ * plugin_test.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_TEST_PLUGIN_TEST_HPP
+#define IRCCD_TEST_PLUGIN_TEST_HPP
+
+/**
+ * \file plugin_test.hpp
+ * \brief test fixture helper for Javascript plugins.
+ */
+
+#include <boost/asio/io_service.hpp>
+
+#include <irccd/daemon/irccd.hpp>
+
+#include <js/js_plugin.hpp>
+
+#include "journal_server.hpp"
+
+namespace irccd {
+
+/**
+ * \brief test fixture helper for Javascript plugins.
+ *
+ * Holds a plugin that is opened (but not loaded).
+ */
+class plugin_test {
+protected:
+    boost::asio::io_service service_;
+    irccd irccd_{service_};
+    std::shared_ptr<js_plugin> plugin_;
+    std::shared_ptr<journal_server> server_;
+
+public:
+    /**
+     * Construct the fixture test.
+     *
+     * \param name the plugin name (e.g. ask)
+     * \param path the full plugin path (e.g. /usr/libexec/irccd/plugins/ask.js)
+     */
+    plugin_test(std::string name, std::string path);
+};
+
+} // !irccd
+
+#endif // !IRCCD_TEST_PLUGIN_TESTER_HPP
--- a/libirccd/CMakeLists.txt	Fri Dec 08 08:41:29 2017 +0100
+++ b/libirccd/CMakeLists.txt	Fri Dec 08 19:32:10 2017 +0100
@@ -77,7 +77,6 @@
         $<$<BOOL:${IRCCD_SYSTEM_MAC}>:resolv>
         libcommon
     PUBLIC_INCLUDES
-        $<BUILD_INTERFACE:${libirccd_SOURCE_DIR}/irccd/daemon>
         $<BUILD_INTERFACE:${libirccd_SOURCE_DIR}>
         $<INSTALL_INTERFACE:${WITH_INCLUDEDIR}>
 )
--- a/tests/src/directory-jsapi/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/directory-jsapi/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -21,7 +21,7 @@
 
 #include <irccd/js/directory_jsapi.hpp>
 
-#include <js_test.hpp>
+#include <irccd/test/js_test.hpp>
 
 namespace irccd {
 
--- a/tests/src/dynlib-plugin/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/dynlib-plugin/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -28,9 +28,10 @@
  * Functions load, unload and reload can not be tested though.
  */
 
-#include <irccd.hpp>
-#include <dynlib_plugin.hpp>
-#include <journal_server.hpp>
+#include <irccd/daemon/dynlib_plugin.hpp>
+#include <irccd/daemon/irccd.hpp>
+
+#include <irccd/test/journal_server.hpp>
 
 namespace irccd {
 
--- a/tests/src/dynlib-plugin/test_plugin.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/dynlib-plugin/test_plugin.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -18,7 +18,7 @@
 
 #include <boost/dll.hpp>
 
-#include <plugin.hpp>
+#include <irccd/daemon/plugin.hpp>
 
 namespace irccd {
 
--- a/tests/src/elapsedtimer-jsapi/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/elapsedtimer-jsapi/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -23,7 +23,7 @@
 
 #include <irccd/js/elapsed_timer_jsapi.hpp>
 
-#include <js_test.hpp>
+#include <irccd/test/js_test.hpp>
 
 using namespace std::chrono_literals;
 
--- a/tests/src/file-jsapi/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/file-jsapi/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -24,7 +24,7 @@
 #include <irccd/js/duktape_vector.hpp>
 #include <irccd/js/file_jsapi.hpp>
 
-#include <js_test.hpp>
+#include <irccd/test/js_test.hpp>
 
 namespace irccd {
 
--- a/tests/src/irccd-jsapi/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/irccd-jsapi/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -19,7 +19,7 @@
 #define BOOST_TEST_MODULE "Irccd Javascript API"
 #include <boost/test/unit_test.hpp>
 
-#include <js_test.hpp>
+#include <irccd/test/js_test.hpp>
 
 namespace irccd {
 
--- a/tests/src/logger-jsapi/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/logger-jsapi/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -24,7 +24,7 @@
 #include <irccd/js/logger_jsapi.hpp>
 #include <irccd/js/plugin_jsapi.hpp>
 
-#include <js_test.hpp>
+#include <irccd/test/js_test.hpp>
 
 namespace irccd {
 
--- a/tests/src/plugin-ask/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/plugin-ask/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -22,7 +22,7 @@
 #include <irccd/daemon/irccd.hpp>
 #include <irccd/daemon/server.hpp>
 
-#include "plugin_test.hpp"
+#include <irccd/test/plugin_test.hpp>
 
 namespace irccd {
 
--- a/tests/src/plugin-auth/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/plugin-auth/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -22,7 +22,7 @@
 #include <irccd/daemon/irccd.hpp>
 #include <irccd/daemon/server.hpp>
 
-#include "plugin_test.hpp"
+#include <irccd/test/plugin_test.hpp>
 
 namespace irccd {
 
--- a/tests/src/plugin-config-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/plugin-config-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -22,7 +22,7 @@
 #include <irccd/daemon/command.hpp>
 #include <irccd/daemon/plugin_service.hpp>
 
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
 
 namespace irccd {
 
--- a/tests/src/plugin-hangman/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/plugin-hangman/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -25,7 +25,7 @@
 #include <irccd/daemon/irccd.hpp>
 #include <irccd/daemon/server.hpp>
 
-#include "plugin_test.hpp"
+#include <irccd/test/plugin_test.hpp>
 
 namespace irccd {
 
--- a/tests/src/plugin-history/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/plugin-history/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -24,7 +24,7 @@
 #include <irccd/daemon/irccd.hpp>
 #include <irccd/daemon/server.hpp>
 
-#include "plugin_test.hpp"
+#include <irccd/test/plugin_test.hpp>
 
 namespace irccd {
 
--- a/tests/src/plugin-info-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/plugin-info-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -22,7 +22,7 @@
 #include <irccd/daemon/command.hpp>
 #include <irccd/daemon/plugin_service.hpp>
 
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
 
 namespace irccd {
 
--- a/tests/src/plugin-list-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/plugin-list-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -22,7 +22,7 @@
 #include <irccd/daemon/command.hpp>
 #include <irccd/daemon/plugin_service.hpp>
 
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
 
 namespace irccd {
 
--- a/tests/src/plugin-load-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/plugin-load-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -22,7 +22,7 @@
 #include <irccd/daemon/command.hpp>
 #include <irccd/daemon/plugin_service.hpp>
 
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
 
 namespace irccd {
 
--- a/tests/src/plugin-logger/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/plugin-logger/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -25,7 +25,7 @@
 #include <irccd/daemon/irccd.hpp>
 #include <irccd/daemon/server.hpp>
 
-#include "plugin_test.hpp"
+#include <irccd/test/plugin_test.hpp>
 
 namespace irccd {
 
--- a/tests/src/plugin-plugin/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/plugin-plugin/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -25,7 +25,7 @@
 #include <irccd/daemon/plugin_service.hpp>
 #include <irccd/daemon/server.hpp>
 
-#include "plugin_test.hpp"
+#include <irccd/test/plugin_test.hpp>
 
 namespace irccd {
 
--- a/tests/src/plugin-reload-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/plugin-reload-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -22,7 +22,7 @@
 #include <irccd/daemon/command.hpp>
 #include <irccd/daemon/plugin_service.hpp>
 
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
 
 namespace irccd {
 
--- a/tests/src/plugin-unload-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/plugin-unload-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -22,7 +22,7 @@
 #include <irccd/daemon/command.hpp>
 #include <irccd/daemon/plugin_service.hpp>
 
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
 
 namespace irccd {
 
--- a/tests/src/rule-add-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/rule-add-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -24,7 +24,7 @@
 #include <irccd/daemon/command.hpp>
 #include <irccd/daemon/rule_service.hpp>
 
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
 
 namespace irccd {
 
--- a/tests/src/rule-edit-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/rule-edit-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -24,7 +24,7 @@
 #include <irccd/daemon/command.hpp>
 #include <irccd/daemon/rule_service.hpp>
 
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
 
 namespace irccd {
 
--- a/tests/src/rule-info-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/rule-info-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -24,7 +24,7 @@
 #include <irccd/daemon/command.hpp>
 #include <irccd/daemon/rule_service.hpp>
 
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
 
 namespace irccd {
 
--- a/tests/src/rule-list-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/rule-list-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -24,7 +24,7 @@
 #include <irccd/daemon/command.hpp>
 #include <irccd/daemon/rule_service.hpp>
 
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
 
 namespace irccd {
 
--- a/tests/src/rule-move-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/rule-move-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -24,7 +24,7 @@
 #include <irccd/daemon/command.hpp>
 #include <irccd/daemon/rule_service.hpp>
 
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
 
 namespace irccd {
 
--- a/tests/src/rule-remove-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/rule-remove-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -24,7 +24,7 @@
 #include <irccd/daemon/command.hpp>
 #include <irccd/daemon/rule_service.hpp>
 
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
 
 namespace irccd {
 
--- a/tests/src/server-connect-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/server-connect-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -21,8 +21,8 @@
 
 #include <irccd/daemon/server_service.hpp>
 
-#include <journal_server.hpp>
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
+#include <irccd/test/journal_server.hpp>
 
 namespace irccd {
 
--- a/tests/src/server-disconnect-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/server-disconnect-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -21,8 +21,8 @@
 
 #include <irccd/daemon/server_service.hpp>
 
-#include <journal_server.hpp>
-#include <command_test.hpp>
+#include <irccd/test/journal_server.hpp>
+#include <irccd/test/command_test.hpp>
 
 namespace irccd {
 
--- a/tests/src/server-info-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/server-info-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -21,8 +21,8 @@
 
 #include <irccd/daemon/server_service.hpp>
 
-#include <journal_server.hpp>
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
+#include <irccd/test/journal_server.hpp>
 
 namespace irccd {
 
--- a/tests/src/server-invite-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/server-invite-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -21,8 +21,8 @@
 
 #include <irccd/daemon/server_service.hpp>
 
-#include <journal_server.hpp>
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
+#include <irccd/test/journal_server.hpp>
 
 namespace irccd {
 
--- a/tests/src/server-join-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/server-join-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -21,8 +21,8 @@
 
 #include <irccd/daemon/server_service.hpp>
 
-#include <journal_server.hpp>
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
+#include <irccd/test/journal_server.hpp>
 
 namespace irccd {
 
--- a/tests/src/server-kick-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/server-kick-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -21,8 +21,8 @@
 
 #include <irccd/daemon/server_service.hpp>
 
-#include <journal_server.hpp>
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
+#include <irccd/test/journal_server.hpp>
 
 namespace irccd {
 
--- a/tests/src/server-list-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/server-list-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -21,8 +21,8 @@
 
 #include <irccd/daemon/server_service.hpp>
 
-#include <journal_server.hpp>
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
+#include <irccd/test/journal_server.hpp>
 
 namespace irccd {
 
--- a/tests/src/server-me-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/server-me-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -21,8 +21,8 @@
 
 #include <irccd/daemon/server_service.hpp>
 
-#include <journal_server.hpp>
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
+#include <irccd/test/journal_server.hpp>
 
 namespace irccd {
 
--- a/tests/src/server-message-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/server-message-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -21,8 +21,8 @@
 
 #include <irccd/daemon/server_service.hpp>
 
-#include <journal_server.hpp>
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
+#include <irccd/test/journal_server.hpp>
 
 namespace irccd {
 
--- a/tests/src/server-mode-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/server-mode-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -21,8 +21,8 @@
 
 #include <irccd/daemon/server_service.hpp>
 
-#include <journal_server.hpp>
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
+#include <irccd/test/journal_server.hpp>
 
 namespace irccd {
 
--- a/tests/src/server-nick-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/server-nick-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -21,8 +21,8 @@
 
 #include <irccd/daemon/server_service.hpp>
 
-#include <journal_server.hpp>
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
+#include <irccd/test/journal_server.hpp>
 
 namespace irccd {
 
--- a/tests/src/server-notice-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/server-notice-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -21,8 +21,8 @@
 
 #include <irccd/daemon/server_service.hpp>
 
-#include <journal_server.hpp>
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
+#include <irccd/test/journal_server.hpp>
 
 namespace irccd {
 
--- a/tests/src/server-part-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/server-part-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -21,8 +21,8 @@
 
 #include <irccd/daemon/server_service.hpp>
 
-#include <journal_server.hpp>
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
+#include <irccd/test/journal_server.hpp>
 
 namespace irccd {
 
--- a/tests/src/server-reconnect-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/server-reconnect-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -21,8 +21,8 @@
 
 #include <irccd/daemon/server_service.hpp>
 
-#include <journal_server.hpp>
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
+#include <irccd/test/journal_server.hpp>
 
 namespace irccd {
 
--- a/tests/src/server-topic-command/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/server-topic-command/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -21,8 +21,8 @@
 
 #include <irccd/daemon/server_service.hpp>
 
-#include <journal_server.hpp>
-#include <command_test.hpp>
+#include <irccd/test/command_test.hpp>
+#include <irccd/test/journal_server.hpp>
 
 namespace irccd {
 
--- a/tests/src/system-jsapi/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/system-jsapi/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -26,7 +26,7 @@
 #include <irccd/js/file_jsapi.hpp>
 #include <irccd/js/system_jsapi.hpp>
 
-#include <js_test.hpp>
+#include <irccd/test/js_test.hpp>
 
 namespace irccd {
 
--- a/tests/src/timer-jsapi/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/timer-jsapi/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -23,7 +23,7 @@
 #include <irccd/js/plugin_jsapi.hpp>
 #include <irccd/js/timer_jsapi.hpp>
 
-#include <js_test.hpp>
+#include <irccd/test/js_test.hpp>
 
 #include <irccd/js/logger_jsapi.hpp>
 
--- a/tests/src/unicode-jsapi/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/unicode-jsapi/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -25,7 +25,7 @@
 
 #include <irccd/js/unicode_jsapi.hpp>
 
-#include <js_test.hpp>
+#include <irccd/test/js_test.hpp>
 
 namespace irccd {
 
--- a/tests/src/util-jsapi/main.cpp	Fri Dec 08 08:41:29 2017 +0100
+++ b/tests/src/util-jsapi/main.cpp	Fri Dec 08 19:32:10 2017 +0100
@@ -21,7 +21,7 @@
 
 #include <irccd/js/util_jsapi.hpp>
 
-#include <js_test.hpp>
+#include <irccd/test/js_test.hpp>
 
 namespace irccd {