changeset 662:e9153b85b9bd

Tests: test irccdctl (plugin-* commands) #785 While here, fix many commands that were throwing invalid_message because of missing 'command' JSON property.
author David Demelier <markand@malikania.fr>
date Thu, 29 Mar 2018 09:13:51 +0200
parents cab5cfba4c3b
children 65a54b126c08
files cmake/function/IrccdDefineTest.cmake irccdctl/plugin_info_cli.cpp irccdctl/plugin_load_cli.cpp irccdctl/plugin_reload_cli.cpp irccdctl/plugin_unload_cli.cpp libirccd-test/CMakeLists.txt libirccd-test/irccd/test/cli_test.cpp libirccd-test/irccd/test/cli_test.hpp tests/CMakeLists.txt tests/data/bar.js tests/data/foo.js tests/data/irccd-plugins.conf tests/data/irccdctl.conf tests/src/irccdctl/CMakeLists.txt tests/src/irccdctl/cli-plugin-config/CMakeLists.txt tests/src/irccdctl/cli-plugin-config/main.cpp tests/src/irccdctl/cli-plugin-info/CMakeLists.txt tests/src/irccdctl/cli-plugin-info/main.cpp tests/src/irccdctl/cli-plugin-list/CMakeLists.txt tests/src/irccdctl/cli-plugin-list/main.cpp tests/src/irccdctl/cli-plugin-load/CMakeLists.txt tests/src/irccdctl/cli-plugin-load/main.cpp tests/src/irccdctl/cli-plugin-reload/CMakeLists.txt tests/src/irccdctl/cli-plugin-reload/main.cpp tests/src/irccdctl/cli-plugin-unload/CMakeLists.txt tests/src/irccdctl/cli-plugin-unload/main.cpp
diffstat 26 files changed, 722 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/cmake/function/IrccdDefineTest.cmake	Wed Mar 28 07:59:03 2018 +0200
+++ b/cmake/function/IrccdDefineTest.cmake	Thu Mar 29 09:13:51 2018 +0200
@@ -25,6 +25,7 @@
 #    SOURCES the sources files
 #    LIBRARIES (Optional) libraries to link
 #    FLAGS (Optional) compilation flags
+#    DEPENDS (Optional) list of dependencies
 # )
 #
 # Create a unit test named test-${NAME}
@@ -38,7 +39,7 @@
 
 function(irccd_define_test)
     set(oneValueArgs NAME)
-    set(multiValueArgs SOURCES LIBRARIES FLAGS)
+    set(multiValueArgs DEPENDS SOURCES LIBRARIES FLAGS)
 
     cmake_parse_arguments(TEST "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
 
@@ -56,8 +57,12 @@
             ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
     )
 
-    # Executable
     add_executable(test-${TEST_NAME} ${TEST_SOURCES})
+
+    if (TEST_DEPENDS)
+        add_dependencies(test-${TEST_NAME} ${TEST_DEPENDS})
+    endif ()
+
     target_link_libraries(test-${TEST_NAME} ${TEST_LIBRARIES})
 
     target_include_directories(
--- a/irccdctl/plugin_info_cli.cpp	Wed Mar 28 07:59:03 2018 +0200
+++ b/irccdctl/plugin_info_cli.cpp	Thu Mar 29 09:13:51 2018 +0200
@@ -34,7 +34,12 @@
     if (args.size() < 1)
         throw std::invalid_argument("plugin-info requires 1 argument");
 
-    request(ctl, {{ "plugin", args[0] }}, [] (auto result) {
+    const auto json = nlohmann::json::object({
+        { "command",    "plugin-info"   },
+        { "plugin",     args[0]         }
+    });
+
+    request(ctl, json, [] (auto result) {
         const json_util::parser parser(result);
 
         std::cout << std::boolalpha;
--- a/irccdctl/plugin_load_cli.cpp	Wed Mar 28 07:59:03 2018 +0200
+++ b/irccdctl/plugin_load_cli.cpp	Thu Mar 29 09:13:51 2018 +0200
@@ -32,7 +32,10 @@
     if (args.size() < 1)
         throw std::invalid_argument("plugin-load requires 1 argument");
 
-    request(ctl, {{ "plugin", args[0] }});
+    request(ctl, {
+        { "command",    "plugin-load"   },
+        { "plugin",     args[0]         }
+    });
 }
 
 } // !ctl
--- a/irccdctl/plugin_reload_cli.cpp	Wed Mar 28 07:59:03 2018 +0200
+++ b/irccdctl/plugin_reload_cli.cpp	Thu Mar 29 09:13:51 2018 +0200
@@ -32,7 +32,10 @@
     if (args.size() < 1)
         throw std::invalid_argument("plugin-reload requires 1 argument");
 
-    request(ctl, {{ "plugin", args[0] }});
+    request(ctl, {
+        { "command",    "plugin-reload" },
+        { "plugin",     args[0]         }
+    });
 }
 
 } // !ctl
--- a/irccdctl/plugin_unload_cli.cpp	Wed Mar 28 07:59:03 2018 +0200
+++ b/irccdctl/plugin_unload_cli.cpp	Thu Mar 29 09:13:51 2018 +0200
@@ -32,7 +32,10 @@
     if (args.size() < 1)
         throw std::invalid_argument("plugin-unload requires 1 argument");
 
-    request(ctl, {{ "plugin", args[0] }});
+    request(ctl, {
+        { "command",    "plugin-unload" },
+        { "plugin",     args[0]         }
+    });
 }
 
 } // !ctl
--- a/libirccd-test/CMakeLists.txt	Wed Mar 28 07:59:03 2018 +0200
+++ b/libirccd-test/CMakeLists.txt	Thu Mar 29 09:13:51 2018 +0200
@@ -21,6 +21,8 @@
 irccd_define_library(
     TARGET libirccd-test
     SOURCES
+        ${libirccd-test_SOURCE_DIR}/irccd/test/cli_test.cpp
+        ${libirccd-test_SOURCE_DIR}/irccd/test/cli_test.hpp
         ${libirccd-test_SOURCE_DIR}/irccd/test/command_test.hpp
         ${libirccd-test_SOURCE_DIR}/irccd/test/debug_server.cpp
         ${libirccd-test_SOURCE_DIR}/irccd/test/debug_server.hpp
@@ -35,4 +37,8 @@
         libirccdctl
     PUBLIC_INCLUDES
         $<BUILD_INTERFACE:${libirccd-test_SOURCE_DIR}>
+    FLAGS
+        IRCCD_EXECUTABLE="$<TARGET_FILE:irccd>"
+        IRCCDCTL_EXECUTABLE="$<TARGET_FILE:irccdctl>"
+        TESTS_BINARY_DIR="${tests_BINARY_DIR}"
 )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libirccd-test/irccd/test/cli_test.cpp	Thu Mar 29 09:13:51 2018 +0200
@@ -0,0 +1,85 @@
+/*
+ * cli_test.cpp -- test fixture for irccdctl frontend
+ *
+ * Copyright (c) 2013-2018 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 <chrono>
+#include <future>
+#include <sstream>
+#include <thread>
+
+#include <boost/asio.hpp>
+#include <boost/process.hpp>
+
+#include <irccd/string_util.hpp>
+
+#include "cli_test.hpp"
+
+namespace proc = boost::process;
+
+namespace irccd {
+
+void cli_test::run_irccd(const std::string& config)
+{
+    std::ostringstream oss;
+
+    oss << IRCCD_EXECUTABLE << " -fc " << TESTS_BINARY_DIR << "/" << config;
+
+    irccd_ = proc::child(oss.str());
+
+    // Let irccd bind correctly to the socket.
+    std::this_thread::sleep_for(std::chrono::milliseconds(250U));
+}
+
+cli_test::outputs cli_test::run_irccdctl(const std::vector<std::string>& args)
+{
+    std::ostringstream oss;
+    std::future<std::string> out;
+    std::future<std::string> err;
+
+    oss << IRCCDCTL_EXECUTABLE << " -c " << TESTS_BINARY_DIR << "/irccdctl.conf "
+        << string_util::join(args, " ");
+
+    boost::asio::io_service io;
+    proc::child irccdctl(
+        oss.str(),
+        proc::std_in.close(),
+        proc::std_out > out,
+        proc::std_err > err,
+        io
+    );
+
+    io.run();
+
+    auto result = std::make_pair(
+        string_util::split(out.get(), "\n"),
+        string_util::split(err.get(), "\n")
+    );
+
+    irccdctl.join();
+
+    return result;
+}
+
+cli_test::outputs cli_test::run(const std::string& config,
+                                const std::vector<std::string>& args)
+{
+    run_irccd(config);
+
+    return run_irccdctl(args);
+}
+
+} // !irccd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libirccd-test/irccd/test/cli_test.hpp	Thu Mar 29 09:13:51 2018 +0200
@@ -0,0 +1,77 @@
+/*
+ * cli_test.hpp -- test fixture for irccdctl frontend
+ *
+ * Copyright (c) 2013-2018 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_CLI_TEST_HPP
+#define IRCCD_TEST_CLI_TEST_HPP
+
+/**
+ * \file cli_test.hpp
+ * \brief Test fixture for irccdctl frontend.
+ */
+
+#include <utility>
+#include <vector>
+
+#include <boost/process.hpp>
+
+namespace irccd {
+
+/**
+ * \brief Test fixture for irccdctl frontend.
+ */
+class cli_test {
+private:
+    boost::process::child irccd_;
+
+public:
+    /**
+     * Type for all lines printed.
+     */
+    using output = std::vector<std::string>;
+
+    /**
+     * Collection of output from stdout/stderr respectively.
+     */
+    using outputs = std::pair<output, output>;
+
+    /**
+     * Start irccd daemon with the configuration file (relative to tests/data).
+     *
+     * \param config the path to the config
+     */
+    void run_irccd(const std::string& config);
+
+    /**
+     * Start irccdctl and returns its stdout/stderr.
+     *
+     * \param args the arguments to irccdctl
+     */
+    outputs run_irccdctl(const std::vector<std::string>& args);
+
+    /**
+     * Convenient function that starts irccd and irccdctl for oneshot tests.
+     *
+     * \param config the base configuration name for irccd
+     * \param args the arguments to irccdctl
+     */
+    outputs run(const std::string& config, const std::vector<std::string>& args);
+};
+
+} // !irccd
+
+#endif // !IRCCD_TEST_CLI_TEST_HPP
--- a/tests/CMakeLists.txt	Wed Mar 28 07:59:03 2018 +0200
+++ b/tests/CMakeLists.txt	Thu Mar 29 09:13:51 2018 +0200
@@ -19,9 +19,27 @@
 # Project
 project(tests)
 
+# Configuration files for irccd/irccdctl
+set(
+    CONFIGS
+    irccd-plugins.conf
+    irccdctl.conf
+)
+
+foreach (c ${CONFIGS})
+    configure_file(
+        ${tests_SOURCE_DIR}/data/${c}
+        ${tests_BINARY_DIR}/${c}
+        @ONLY
+    )
+endforeach ()
+
 # libirccd
 add_subdirectory(src/libirccd)
 
+# irccdctl
+add_subdirectory(src/irccdctl)
+
 # Javascript API and plugins.
 if (HAVE_JS)
     add_subdirectory(src/plugins)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/data/bar.js	Thu Mar 29 09:13:51 2018 +0200
@@ -0,0 +1,10 @@
+info = {
+    author: "David Demelier <markand@malikania.fr>",
+    license: "ISC",
+    summary: "bar",
+    version: "0.0"
+};
+
+function onLoad()
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/data/foo.js	Thu Mar 29 09:13:51 2018 +0200
@@ -0,0 +1,15 @@
+info = {
+    author: "David Demelier <markand@malikania.fr>",
+    license: "ISC",
+    summary: "foo",
+    version: "0.0"
+};
+
+function onLoad()
+{
+}
+
+function onReload()
+{
+    Irccd.Plugin.config["reloaded"] = "true";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/data/irccd-plugins.conf	Thu Mar 29 09:13:51 2018 +0200
@@ -0,0 +1,11 @@
+[transport]
+type = "unix"
+path = "@tests_BINARY_DIR@/irccd.sock"
+
+[plugins]
+foo = "@tests_SOURCE_DIR@/data/foo.js"
+bar = "@tests_SOURCE_DIR@/data/bar.js"
+
+[plugin.bar]
+v1 = "123"
+v2 = "456"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/data/irccdctl.conf	Thu Mar 29 09:13:51 2018 +0200
@@ -0,0 +1,3 @@
+[connect]
+type = "unix"
+path = "@tests_BINARY_DIR@/irccd.sock"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/irccdctl/CMakeLists.txt	Thu Mar 29 09:13:51 2018 +0200
@@ -0,0 +1,24 @@
+#
+# CMakeLists.txt -- CMake build system for irccd
+#
+# Copyright (c) 2013-2018 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.
+#
+
+add_subdirectory(cli-plugin-config)
+add_subdirectory(cli-plugin-info)
+add_subdirectory(cli-plugin-list)
+add_subdirectory(cli-plugin-load)
+add_subdirectory(cli-plugin-reload)
+add_subdirectory(cli-plugin-unload)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/irccdctl/cli-plugin-config/CMakeLists.txt	Thu Mar 29 09:13:51 2018 +0200
@@ -0,0 +1,24 @@
+#
+# CMakeLists.txt -- CMake build system for irccd
+#
+# Copyright (c) 2013-2018 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 cli-plugin-config
+    SOURCES main.cpp
+    LIBRARIES libcommon
+    DEPENDS irccd irccdctl
+)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/irccdctl/cli-plugin-config/main.cpp	Thu Mar 29 09:13:51 2018 +0200
@@ -0,0 +1,63 @@
+/*
+ * main.cpp -- test irccdctl plugin-config
+ *
+ * Copyright (c) 2013-2018 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.
+ */
+
+#define BOOST_TEST_MODULE "irccdctl plugin-config"
+#include <boost/test/unit_test.hpp>
+
+#include <irccd/test/cli_test.hpp>
+
+namespace irccd {
+
+BOOST_FIXTURE_TEST_SUITE(plugin_config_suite, cli_test)
+
+BOOST_AUTO_TEST_CASE(set_and_get)
+{
+    run_irccd("irccd-plugins.conf");
+
+    // First, configure. No output yet
+    {
+        const auto result = run_irccdctl({ "plugin-config", "foo", "verbose", "false" });
+
+        // no output yet.
+        BOOST_TEST(result.first.size() == 0U);
+        BOOST_TEST(result.second.size() == 0U);
+    }
+
+    // Get the newly created value.
+    {
+        const auto result = run_irccdctl({ "plugin-config", "foo", "verbose" });
+
+        BOOST_TEST(result.first.size() == 2U);
+        BOOST_TEST(result.second.size() == 0U);
+        BOOST_TEST(result.first[0] == "false");
+    }
+}
+
+BOOST_AUTO_TEST_CASE(getall)
+{
+    const auto result = run("irccd-plugins.conf", { "plugin-config", "bar" });
+
+    BOOST_TEST(result.first.size() == 3U);
+    BOOST_TEST(result.second.size() == 0U);
+    BOOST_TEST(result.first[0] == "v1               : 123");
+    BOOST_TEST(result.first[1] == "v2               : 456");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // !irccd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/irccdctl/cli-plugin-info/CMakeLists.txt	Thu Mar 29 09:13:51 2018 +0200
@@ -0,0 +1,24 @@
+#
+# CMakeLists.txt -- CMake build system for irccd
+#
+# Copyright (c) 2013-2018 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 cli-plugin-info
+    SOURCES main.cpp
+    LIBRARIES libcommon
+    DEPENDS irccd irccdctl
+)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/irccdctl/cli-plugin-info/main.cpp	Thu Mar 29 09:13:51 2018 +0200
@@ -0,0 +1,42 @@
+/*
+ * main.cpp -- test irccdctl plugin-info
+ *
+ * Copyright (c) 2013-2018 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.
+ */
+
+#define BOOST_TEST_MODULE "irccdctl plugin-info"
+#include <boost/test/unit_test.hpp>
+
+#include <irccd/test/cli_test.hpp>
+
+namespace irccd {
+
+BOOST_FIXTURE_TEST_SUITE(plugin_info_suite, cli_test)
+
+BOOST_AUTO_TEST_CASE(simple)
+{
+    const auto result = run("irccd-plugins.conf", { "plugin-info", "foo" });
+
+    BOOST_TEST(result.first.size() == 5U);
+    BOOST_TEST(result.second.size() == 0U);
+    BOOST_TEST(result.first[0] == "Author         : David Demelier <markand@malikania.fr>");
+    BOOST_TEST(result.first[1] == "License        : ISC");
+    BOOST_TEST(result.first[2] == "Summary        : foo");
+    BOOST_TEST(result.first[3] == "Version        : 0.0");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // !irccd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/irccdctl/cli-plugin-list/CMakeLists.txt	Thu Mar 29 09:13:51 2018 +0200
@@ -0,0 +1,24 @@
+#
+# CMakeLists.txt -- CMake build system for irccd
+#
+# Copyright (c) 2013-2018 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 cli-plugin-list
+    SOURCES main.cpp
+    LIBRARIES libcommon
+    DEPENDS irccd irccdctl
+)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/irccdctl/cli-plugin-list/main.cpp	Thu Mar 29 09:13:51 2018 +0200
@@ -0,0 +1,40 @@
+/*
+ * main.cpp -- test irccdctl plugin-list
+ *
+ * Copyright (c) 2013-2018 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.
+ */
+
+#define BOOST_TEST_MODULE "irccdctl plugin-list"
+#include <boost/test/unit_test.hpp>
+
+#include <irccd/test/cli_test.hpp>
+
+namespace irccd {
+
+BOOST_FIXTURE_TEST_SUITE(plugin_list_suite, cli_test)
+
+BOOST_AUTO_TEST_CASE(output)
+{
+    const auto result = run("irccd-plugins.conf", { "plugin-list" });
+
+    BOOST_TEST(result.first.size() == 3U);
+    BOOST_TEST(result.second.size() == 0U);
+    BOOST_TEST(result.first[0] == "foo");
+    BOOST_TEST(result.first[1] == "bar");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // !irccd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/irccdctl/cli-plugin-load/CMakeLists.txt	Thu Mar 29 09:13:51 2018 +0200
@@ -0,0 +1,28 @@
+#
+# CMakeLists.txt -- CMake build system for irccd
+#
+# Copyright (c) 2013-2018 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.
+#
+
+if (NOT IS_ABSOLUTE WITH_PLUGINDIR)
+    file(WRITE "${CMAKE_BINARY_DIR}/${WITH_PLUGINDIR}/test-cli-plugin-load.js" "")
+
+    irccd_define_test(
+        NAME cli-plugin-load
+        SOURCES main.cpp
+        LIBRARIES libcommon
+        DEPENDS irccd irccdctl
+    )
+endif ()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/irccdctl/cli-plugin-load/main.cpp	Thu Mar 29 09:13:51 2018 +0200
@@ -0,0 +1,54 @@
+/*
+ * main.cpp -- test irccdctl plugin-load
+ *
+ * Copyright (c) 2013-2018 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.
+ */
+
+#define BOOST_TEST_MODULE "irccdctl plugin-load"
+#include <boost/test/unit_test.hpp>
+
+#include <irccd/test/cli_test.hpp>
+
+namespace irccd {
+
+BOOST_FIXTURE_TEST_SUITE(plugin_load_suite, cli_test)
+
+BOOST_AUTO_TEST_CASE(simple)
+{
+    run_irccd("irccd-plugins.conf");
+
+    // Load a plugin first.
+    {
+        const auto result = run_irccdctl({ "plugin-load", "test-cli-plugin-load" });
+
+        BOOST_TEST(result.first.size() == 0U);
+        BOOST_TEST(result.second.size() == 0U);
+    }
+
+    // Get the new list of plugins.
+    {
+        const auto result = run_irccdctl({ "plugin-list" });
+
+    BOOST_TEST(result.first.size() == 4U);
+    BOOST_TEST(result.second.size() == 0U);
+    BOOST_TEST(result.first[0] == "foo");
+    BOOST_TEST(result.first[1] == "bar");
+    BOOST_TEST(result.first[2] == "test-cli-plugin-load");
+    }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // !irccd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/irccdctl/cli-plugin-reload/CMakeLists.txt	Thu Mar 29 09:13:51 2018 +0200
@@ -0,0 +1,24 @@
+#
+# CMakeLists.txt -- CMake build system for irccd
+#
+# Copyright (c) 2013-2018 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 cli-plugin-reload
+    SOURCES main.cpp
+    LIBRARIES libcommon
+    DEPENDS irccd irccdctl
+)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/irccdctl/cli-plugin-reload/main.cpp	Thu Mar 29 09:13:51 2018 +0200
@@ -0,0 +1,51 @@
+/*
+ * main.cpp -- test irccdctl plugin-reload
+ *
+ * Copyright (c) 2013-2018 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.
+ */
+
+#define BOOST_TEST_MODULE "irccdctl plugin-reload"
+#include <boost/test/unit_test.hpp>
+
+#include <irccd/test/cli_test.hpp>
+
+namespace irccd {
+
+BOOST_FIXTURE_TEST_SUITE(plugin_reload_suite, cli_test)
+
+BOOST_AUTO_TEST_CASE(simple)
+{
+    run_irccd("irccd-plugins.conf");
+
+    {
+        // onReload will update the config.
+        const auto result = run_irccdctl({ "plugin-reload", "foo" });
+
+        BOOST_TEST(result.first.size() == 0U);
+        BOOST_TEST(result.second.size() == 0U);
+    }
+
+    {
+        const auto result = run_irccdctl({ "plugin-config", "foo", "reloaded" });
+
+        BOOST_TEST(result.first.size() == 2U);
+        BOOST_TEST(result.second.size() == 0U);
+        BOOST_TEST(result.first[0] == "true");
+    }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // !irccd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/irccdctl/cli-plugin-unload/CMakeLists.txt	Thu Mar 29 09:13:51 2018 +0200
@@ -0,0 +1,24 @@
+#
+# CMakeLists.txt -- CMake build system for irccd
+#
+# Copyright (c) 2013-2018 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 cli-plugin-unload
+    SOURCES main.cpp
+    LIBRARIES libcommon
+    DEPENDS irccd irccdctl
+)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/irccdctl/cli-plugin-unload/main.cpp	Thu Mar 29 09:13:51 2018 +0200
@@ -0,0 +1,50 @@
+/*
+ * main.cpp -- test irccdctl plugin-unload
+ *
+ * Copyright (c) 2013-2018 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.
+ */
+
+#define BOOST_TEST_MODULE "irccdctl plugin-unload"
+#include <boost/test/unit_test.hpp>
+
+#include <irccd/test/cli_test.hpp>
+
+namespace irccd {
+
+BOOST_FIXTURE_TEST_SUITE(plugin_unload_suite, cli_test)
+
+BOOST_AUTO_TEST_CASE(simple)
+{
+    run_irccd("irccd-plugins.conf");
+
+    {
+        const auto result = run_irccdctl({ "plugin-unload", "foo" });
+
+        BOOST_TEST(result.first.size() == 0U);
+        BOOST_TEST(result.second.size() == 0U);
+    }
+
+    {
+        const auto result = run_irccdctl({ "plugin-list" });
+
+        BOOST_TEST(result.first.size() == 2U);
+        BOOST_TEST(result.second.size() == 0U);
+        BOOST_TEST(result.first[0] == "bar");
+    }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // !irccd