Mercurial > irccd
changeset 453:acb2d4990249
Irccdctl: implement rule-edit
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 20 Jul 2017 22:55:02 +0200 |
parents | 2170aa0e38aa |
children | 9bb6bf1cb50b |
files | doc/html/CMakeLists.txt doc/html/irccdctl/command/index.md doc/html/irccdctl/command/rule-edit.md irccd/main.cpp irccdctl/cli.cpp irccdctl/cli.hpp irccdctl/main.cpp libirccd/irccd/command.cpp libirccd/irccd/command.hpp libirccd/irccd/rule.cpp libirccd/irccd/rule.hpp libirccd/irccd/service.cpp libirccd/irccd/service.hpp tests/CMakeLists.txt tests/cmd-rule-edit/CMakeLists.txt tests/cmd-rule-edit/main.cpp |
diffstat | 16 files changed, 853 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/html/CMakeLists.txt Thu Jul 20 22:56:34 2017 +0200 +++ b/doc/html/CMakeLists.txt Thu Jul 20 22:55:02 2017 +0200 @@ -153,6 +153,7 @@ ${html_SOURCE_DIR}/irccdctl/command/plugin-reload.md ${html_SOURCE_DIR}/irccdctl/command/plugin-unload.md ${html_SOURCE_DIR}/irccdctl/command/rule-add.md + ${html_SOURCE_DIR}/irccdctl/command/rule-edit.md ${html_SOURCE_DIR}/irccdctl/command/rule-info.md ${html_SOURCE_DIR}/irccdctl/command/rule-list.md ${html_SOURCE_DIR}/irccdctl/command/rule-move.md
--- a/doc/html/irccdctl/command/index.md Thu Jul 20 22:56:34 2017 +0200 +++ b/doc/html/irccdctl/command/index.md Thu Jul 20 22:55:02 2017 +0200 @@ -13,6 +13,7 @@ - [plugin-reload](plugin-reload.html) - [plugin-unload](plugin-unload.html) - [rule-add](rule-add.html) + - [rule-edit](rule-edit.html) - [rule-info](rule-info.html) - [rule-list](rule-list.html) - [rule-move](rule-move.html)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/html/irccdctl/command/rule-edit.md Thu Jul 20 22:55:02 2017 +0200 @@ -0,0 +1,35 @@ +--- +title: rule-edit +guide: yes +--- + +# rule-edit + +Edit an existing rule in irccd. + +All options can be specified multiple times. + +Available options: + + - **a, --action**: set action + - **c, --add-channel**: match a channel + - **C, --remove-channel**: remove a channel + - **e, --add-event**: match an event + - **E, --remove-event**: remove an event + - **p, --add-plugin**: match a plugin + - **P, --add-plugin**: remove a plugin + - **s, --add-server**: match a server + - **S, --remove-server**: remove a server + +## Usage + +````nohighlight +usage: irccdctl rule-edit [options] index +```` + +## Example + +````nohighlight +$ irccdctl rule-edit -p hangman 0 +$ irccdctl rule-edit -S localhost -c #games -p hangman 1 +````
--- a/irccd/main.cpp Thu Jul 20 22:56:34 2017 +0200 +++ b/irccd/main.cpp Thu Jul 20 22:55:02 2017 +0200 @@ -321,6 +321,7 @@ instance->commands().add(std::make_unique<command::ServerReconnectCommand>()); instance->commands().add(std::make_unique<command::ServerTopicCommand>()); instance->commands().add(std::make_unique<command::RuleAddCommand>()); + instance->commands().add(std::make_unique<command::RuleEditCommand>()); instance->commands().add(std::make_unique<command::RuleInfoCommand>()); instance->commands().add(std::make_unique<command::RuleListCommand>()); instance->commands().add(std::make_unique<command::RuleMoveCommand>());
--- a/irccdctl/cli.cpp Thu Jul 20 22:56:34 2017 +0200 +++ b/irccdctl/cli.cpp Thu Jul 20 22:55:02 2017 +0200 @@ -923,6 +923,102 @@ } /* + * RuleEditCli. + * ------------------------------------------------------------------ + */ + +RuleEditCli::RuleEditCli() + : Cli("rule-edit", + "edit an existing rule", + "rule-edit [options] index", + "Edit an existing rule in irccd.\n\n" + "All options can be specified multiple times.\n\n" + "Available options:\n" + " -a, --action\t\t\tset action\n" + " -c, --add-channel\t\tmatch a channel\n" + " -C, --remove-channel\t\tremove a channel\n" + " -e, --add-event\t\tmatch an event\n" + " -E, --remove-event\t\tremove an event\n" + " -p, --add-plugin\t\tmatch a plugin\n" + " -P, --add-plugin\t\tremove a plugin\n" + " -s, --add-server\t\tmatch a server\n" + " -S, --remove-server\t\tremove a server\n\n" + "Example:\n" + "\tirccdctl rule-edit -p hangman 0\n" + "\tirccdctl rule-edit -S localhost -c #games -p hangman 1") +{ +} + +void RuleEditCli::exec(Irccdctl &irccdctl, const std::vector<std::string> &args) +{ + static const option::Options options{ + { "-a", true }, + { "--action", true }, + { "-c", true }, + { "--add-channel", true }, + { "-C", true }, + { "--remove-channel", true }, + { "-e", true }, + { "--add-event", true }, + { "-E", true }, + { "--remove-event", true }, + { "-p", true }, + { "--add-plugin", true }, + { "-P", true }, + { "--remove-plugin", true }, + { "-s", true }, + { "--add-server", true }, + { "-S", true }, + { "--remove-server", true }, + }; + + auto copy = args; + auto result = option::read(copy, options); + + if (copy.size() < 1) + throw std::invalid_argument("rule-edit requires at least 1 argument"); + + auto json = nlohmann::json::object({ + { "command", "rule-edit" }, + { "channels", nlohmann::json::array() }, + { "events", nlohmann::json::array() }, + { "plugins", nlohmann::json::array() }, + { "servers", nlohmann::json::array() } + }); + + for (const auto& pair : result) { + // Action. + if (pair.first == "-a" || pair.first == "--action") + json["action"] = pair.second; + + // Additions. + if (pair.first == "-c" || pair.first == "--add-channel") + json["add-channels"].push_back(pair.second); + if (pair.first == "-e" || pair.first == "--add-event") + json["add-events"].push_back(pair.second); + if (pair.first == "-p" || pair.first == "--add-plugin") + json["add-plugins"].push_back(pair.second); + if (pair.first == "-s" || pair.first == "--add-server") + json["add-servers"].push_back(pair.second); + + // Removals. + if (pair.first == "-C" || pair.first == "--remove-channel") + json["remove-channels"].push_back(pair.second); + if (pair.first == "-E" || pair.first == "--remove-event") + json["remove-events"].push_back(pair.second); + if (pair.first == "-P" || pair.first == "--remove-plugin") + json["remove-plugins"].push_back(pair.second); + if (pair.first == "-S" || pair.first == "--remove-server") + json["remove-servers"].push_back(pair.second); + } + + // Index. + json["index"] = util::toNumber<unsigned>(copy[0]); + + check(request(irccdctl, json)); +} + +/* * RuleListCli. * ------------------------------------------------------------------ */
--- a/irccdctl/cli.hpp Thu Jul 20 22:56:34 2017 +0200 +++ b/irccdctl/cli.hpp Thu Jul 20 22:55:02 2017 +0200 @@ -607,6 +607,27 @@ }; /* + * RuleEditCli. + * ------------------------------------------------------------------ + */ + +/** + * \brief Implementation of irccdctl rule-edit. + */ +class RuleEditCli : public Cli { +public: + /** + * Default constructor. + */ + RuleEditCli(); + + /** + * \copydoc Cli::exec + */ + void exec(Irccdctl &client, const std::vector<std::string> &args) override; +}; + +/* * RuleListCli. * ------------------------------------------------------------------ */
--- a/irccdctl/main.cpp Thu Jul 20 22:56:34 2017 +0200 +++ b/irccdctl/main.cpp Thu Jul 20 22:55:02 2017 +0200 @@ -523,6 +523,7 @@ commands.push_back(std::make_unique<cli::ServerReconnectCli>()); commands.push_back(std::make_unique<cli::ServerTopicCli>()); commands.push_back(std::make_unique<cli::RuleAddCli>()); + commands.push_back(std::make_unique<cli::RuleEditCli>()); commands.push_back(std::make_unique<cli::RuleListCli>()); commands.push_back(std::make_unique<cli::RuleInfoCli>()); commands.push_back(std::make_unique<cli::RuleMoveCli>());
--- a/libirccd/irccd/command.cpp Thu Jul 20 22:56:34 2017 +0200 +++ b/libirccd/irccd/command.cpp Thu Jul 20 22:55:02 2017 +0200 @@ -487,6 +487,56 @@ client.success("server-topic"); } +RuleEditCommand::RuleEditCommand() + : Command("rule-edit") +{ +} + +void RuleEditCommand::exec(Irccd &irccd, TransportClient &client, const nlohmann::json &args) +{ + static const auto updateset = [] (auto &set, auto args, const auto &key) { + for (const auto &v : args["remove-"s + key]) { + if (v.is_string()) + set.erase(v.template get<std::string>()); + } + for (const auto &v : args["add-"s + key]) { + if (v.is_string()) + set.insert(v.template get<std::string>()); + } + }; + + // Create a copy to avoid incomplete edition in case of errors. + auto index = util::json::requireUint(args, "index"); + auto rule = irccd.rules().require(index); + + updateset(rule.channels(), args, "channels"); + updateset(rule.events(), args, "events"); + updateset(rule.plugins(), args, "plugins"); + updateset(rule.servers(), args, "servers"); + + auto action = args.find("action"); + + if (action != args.end()) { + if (!action->is_string()) { + client.error("rule-edit", "action must be \"accept\" or \"drop\""); + return; + } + + if (action->get<std::string>() == "accept") + rule.setAction(RuleAction::Accept); + else if (action->get<std::string>() == "drop") + rule.setAction(RuleAction::Drop); + else { + client.error("rule-edit", "invalid action '"s + action->get<std::string>() + "'"); + return; + } + } + + // All done, sync the rule. + irccd.rules().require(index) = rule; + client.success("rule-edit"); +} + RuleListCommand::RuleListCommand() : Command("rule-list") {
--- a/libirccd/irccd/command.hpp Thu Jul 20 22:56:34 2017 +0200 +++ b/libirccd/irccd/command.hpp Thu Jul 20 22:55:02 2017 +0200 @@ -458,6 +458,19 @@ void exec(Irccd &irccd, TransportClient &client, const nlohmann::json &args) override; }; +class IRCCD_EXPORT RuleEditCommand : public Command { +public: + /** + * Constructor. + */ + RuleEditCommand(); + + /** + * \copydoc Command::exec + */ + void exec(Irccd &irccd, TransportClient &client, const nlohmann::json &args) override; +}; + /** * \brief Implementation of rule-list transport command. */
--- a/libirccd/irccd/rule.cpp Thu Jul 20 22:56:34 2017 +0200 +++ b/libirccd/irccd/rule.cpp Thu Jul 20 22:55:02 2017 +0200 @@ -16,6 +16,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <cassert> #include <stdexcept> #include "logger.hpp" @@ -86,6 +87,13 @@ return m_action; } +void Rule::setAction(RuleAction action) noexcept +{ + assert(action == RuleAction::Accept || action == RuleAction::Drop); + + m_action = action; +} + const RuleSet &Rule::servers() const noexcept { return m_servers;
--- a/libirccd/irccd/rule.hpp Thu Jul 20 22:56:34 2017 +0200 +++ b/libirccd/irccd/rule.hpp Thu Jul 20 22:55:02 2017 +0200 @@ -109,6 +109,13 @@ IRCCD_EXPORT RuleAction action() const noexcept; /** + * Set the action. + * + * \pre action must be valid + */ + IRCCD_EXPORT void setAction(RuleAction action) noexcept; + + /** * Get the servers. * * \return the servers @@ -116,12 +123,33 @@ IRCCD_EXPORT const RuleSet &servers() const noexcept; /** + * Overloaded function. + * + * \return the servers + */ + inline RuleSet &servers() noexcept + { + return m_servers; + } + + /** * Get the channels. * * \return the channels */ IRCCD_EXPORT const RuleSet &channels() const noexcept; + + /** + * Overloaded function. + * + * \return the channels + */ + inline RuleSet &channels() noexcept + { + return m_channels; + } + /** * Get the origins. * @@ -136,12 +164,34 @@ */ IRCCD_EXPORT const RuleSet &plugins() const noexcept; + + /** + * Overloaded function. + * + * \return the plugins + */ + inline RuleSet &plugins() noexcept + { + return m_plugins; + } + /** * Get the events. * * \return the events */ IRCCD_EXPORT const RuleSet &events() const noexcept; + + + /** + * Overloaded function. + * + * \return the events + */ + inline RuleSet& events() noexcept + { + return m_events; + } }; } // !irccd
--- a/libirccd/irccd/service.cpp Thu Jul 20 22:56:34 2017 +0200 +++ b/libirccd/irccd/service.cpp Thu Jul 20 22:55:02 2017 +0200 @@ -304,6 +304,14 @@ return m_rules[position]; } +Rule &RuleService::require(unsigned position) +{ + if (position >= m_rules.size()) + throw std::out_of_range("rule " + std::to_string(position) + " does not exist"); + + return m_rules[position]; +} + bool RuleService::solve(const std::string &server, const std::string &channel, const std::string &origin,
--- a/libirccd/irccd/service.hpp Thu Jul 20 22:56:34 2017 +0200 +++ b/libirccd/irccd/service.hpp Thu Jul 20 22:55:02 2017 +0200 @@ -356,6 +356,13 @@ IRCCD_EXPORT const Rule &require(unsigned position) const; /** + * Overloaded function. + * + * \copydoc require + */ + IRCCD_EXPORT Rule& require(unsigned position); + + /** * Resolve the action to execute with the specified list of rules. * * \param server the server name
--- a/tests/CMakeLists.txt Thu Jul 20 22:56:34 2017 +0200 +++ b/tests/CMakeLists.txt Thu Jul 20 22:55:02 2017 +0200 @@ -27,6 +27,7 @@ add_subdirectory(cmd-plugin-reload) add_subdirectory(cmd-plugin-unload) add_subdirectory(cmd-rule-add) + add_subdirectory(cmd-rule-edit) add_subdirectory(cmd-rule-info) add_subdirectory(cmd-rule-list) add_subdirectory(cmd-rule-move)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/cmd-rule-edit/CMakeLists.txt Thu Jul 20 22:55:02 2017 +0200 @@ -0,0 +1,23 @@ +# +# 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 cmd-rule-edit + SOURCES main.cpp + LIBRARIES libirccd libirccdctl +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/cmd-rule-edit/main.cpp Thu Jul 20 22:55:02 2017 +0200 @@ -0,0 +1,537 @@ +/* + * main.cpp -- test rule-info remote 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 <command.hpp> +#include <command-tester.hpp> +#include <service.hpp> + +using namespace irccd; +using namespace irccd::command; + +class RuleEditCommandTest : public CommandTester { +protected: + nlohmann::json m_result; + + /* + * Rule sets are unordered so use this function to search a string in + * the JSON array. + */ + inline bool contains(const nlohmann::json &array, const std::string &str) + { + for (const auto &v : array) + if (v.is_string() && v == str) + return true; + + return false; + } + +public: + RuleEditCommandTest() + : CommandTester(std::make_unique<RuleEditCommand>()) + { + m_irccd.commands().add(std::make_unique<RuleInfoCommand>()); + m_irccd.rules().add(Rule( + { "s1", "s2" }, + { "c1", "c2" }, + { "o1", "o2" }, + { "p1", "p2" }, + { "onMessage", "onCommand" }, + RuleAction::Drop + )); + m_irccdctl.client().onMessage.connect([&] (auto result) { + m_result = result; + }); + } +}; + +TEST_F(RuleEditCommandTest, addServer) +{ + try { + m_irccdctl.client().request({ + { "command", "rule-edit" }, + { "add-servers", { "new-s3" } }, + { "index", 0 } + }); + + poll([&] () { + return m_result.is_object(); + }); + + ASSERT_TRUE(m_result.is_object()); + ASSERT_TRUE(m_result["status"].get<bool>()); + + m_result = nullptr; + m_irccdctl.client().request({ + { "command", "rule-info" }, + { "index", 0 } + }); + + poll([&] () { + return m_result.is_object(); + }); + + ASSERT_TRUE(m_result.is_object()); + ASSERT_TRUE(m_result["status"].get<bool>()); + ASSERT_TRUE(contains(m_result["servers"], "s1")); + ASSERT_TRUE(contains(m_result["servers"], "s2")); + ASSERT_TRUE(contains(m_result["servers"], "new-s3")); + ASSERT_TRUE(contains(m_result["channels"], "c1")); + ASSERT_TRUE(contains(m_result["channels"], "c2")); + ASSERT_TRUE(contains(m_result["plugins"], "p1")); + ASSERT_TRUE(contains(m_result["plugins"], "p2")); + ASSERT_TRUE(contains(m_result["events"], "onMessage")); + ASSERT_TRUE(contains(m_result["events"], "onCommand")); + ASSERT_EQ(m_result["action"].get<std::string>(), "drop"); + } catch (const std::exception &ex) { + FAIL() << ex.what(); + } +} + +TEST_F(RuleEditCommandTest, addChannel) +{ + try { + m_irccdctl.client().request({ + { "command", "rule-edit" }, + { "add-channels", { "new-c3" } }, + { "index", 0 } + }); + + poll([&] () { + return m_result.is_object(); + }); + + ASSERT_TRUE(m_result.is_object()); + ASSERT_TRUE(m_result["status"].get<bool>()); + + m_result = nullptr; + m_irccdctl.client().request({ + { "command", "rule-info" }, + { "index", 0 } + }); + + poll([&] () { + return m_result.is_object(); + }); + + ASSERT_TRUE(m_result.is_object()); + ASSERT_TRUE(m_result["status"].get<bool>()); + ASSERT_TRUE(contains(m_result["servers"], "s1")); + ASSERT_TRUE(contains(m_result["servers"], "s2")); + ASSERT_TRUE(contains(m_result["channels"], "c1")); + ASSERT_TRUE(contains(m_result["channels"], "c2")); + ASSERT_TRUE(contains(m_result["channels"], "new-c3")); + ASSERT_TRUE(contains(m_result["plugins"], "p1")); + ASSERT_TRUE(contains(m_result["plugins"], "p2")); + ASSERT_TRUE(contains(m_result["events"], "onMessage")); + ASSERT_TRUE(contains(m_result["events"], "onCommand")); + ASSERT_EQ(m_result["action"].get<std::string>(), "drop"); + } catch (const std::exception &ex) { + FAIL() << ex.what(); + } +} + +TEST_F(RuleEditCommandTest, addPlugin) +{ + try { + m_irccdctl.client().request({ + { "command", "rule-edit" }, + { "add-plugins", { "new-p3" } }, + { "index", 0 } + }); + + poll([&] () { + return m_result.is_object(); + }); + + ASSERT_TRUE(m_result.is_object()); + ASSERT_TRUE(m_result["status"].get<bool>()); + + m_result = nullptr; + m_irccdctl.client().request({ + { "command", "rule-info" }, + { "index", 0 } + }); + + poll([&] () { + return m_result.is_object(); + }); + + ASSERT_TRUE(m_result.is_object()); + ASSERT_TRUE(m_result["status"].get<bool>()); + ASSERT_TRUE(contains(m_result["servers"], "s1")); + ASSERT_TRUE(contains(m_result["servers"], "s2")); + ASSERT_TRUE(contains(m_result["channels"], "c1")); + ASSERT_TRUE(contains(m_result["channels"], "c2")); + ASSERT_TRUE(contains(m_result["plugins"], "p1")); + ASSERT_TRUE(contains(m_result["plugins"], "p2")); + ASSERT_TRUE(contains(m_result["plugins"], "new-p3")); + ASSERT_TRUE(contains(m_result["events"], "onMessage")); + ASSERT_TRUE(contains(m_result["events"], "onCommand")); + ASSERT_EQ(m_result["action"].get<std::string>(), "drop"); + } catch (const std::exception &ex) { + FAIL() << ex.what(); + } +} + +TEST_F(RuleEditCommandTest, addEvent) +{ + try { + m_irccdctl.client().request({ + { "command", "rule-edit" }, + { "add-events", { "onQuery" } }, + { "index", 0 } + }); + + poll([&] () { + return m_result.is_object(); + }); + + ASSERT_TRUE(m_result.is_object()); + ASSERT_TRUE(m_result["status"].get<bool>()); + + m_result = nullptr; + m_irccdctl.client().request({ + { "command", "rule-info" }, + { "index", 0 } + }); + + poll([&] () { + return m_result.is_object(); + }); + + ASSERT_TRUE(m_result.is_object()); + ASSERT_TRUE(m_result["status"].get<bool>()); + ASSERT_TRUE(contains(m_result["servers"], "s1")); + ASSERT_TRUE(contains(m_result["servers"], "s2")); + ASSERT_TRUE(contains(m_result["channels"], "c1")); + ASSERT_TRUE(contains(m_result["channels"], "c2")); + ASSERT_TRUE(contains(m_result["plugins"], "p1")); + ASSERT_TRUE(contains(m_result["plugins"], "p2")); + ASSERT_TRUE(contains(m_result["events"], "onMessage")); + ASSERT_TRUE(contains(m_result["events"], "onCommand")); + ASSERT_TRUE(contains(m_result["events"], "onQuery")); + ASSERT_EQ(m_result["action"].get<std::string>(), "drop"); + } catch (const std::exception &ex) { + FAIL() << ex.what(); + } +} + +TEST_F(RuleEditCommandTest, addEventAndServer) +{ + try { + m_irccdctl.client().request({ + { "command", "rule-edit" }, + { "add-servers", { "new-s3" } }, + { "add-events", { "onQuery" } }, + { "index", 0 } + }); + + poll([&] () { + return m_result.is_object(); + }); + + ASSERT_TRUE(m_result.is_object()); + ASSERT_TRUE(m_result["status"].get<bool>()); + + m_result = nullptr; + m_irccdctl.client().request({ + { "command", "rule-info" }, + { "index", 0 } + }); + + poll([&] () { + return m_result.is_object(); + }); + + ASSERT_TRUE(m_result.is_object()); + ASSERT_TRUE(m_result["status"].get<bool>()); + ASSERT_TRUE(contains(m_result["servers"], "s1")); + ASSERT_TRUE(contains(m_result["servers"], "s2")); + ASSERT_TRUE(contains(m_result["servers"], "new-s3")); + ASSERT_TRUE(contains(m_result["channels"], "c1")); + ASSERT_TRUE(contains(m_result["channels"], "c2")); + ASSERT_TRUE(contains(m_result["plugins"], "p1")); + ASSERT_TRUE(contains(m_result["plugins"], "p2")); + ASSERT_TRUE(contains(m_result["events"], "onMessage")); + ASSERT_TRUE(contains(m_result["events"], "onCommand")); + ASSERT_TRUE(contains(m_result["events"], "onQuery")); + ASSERT_EQ(m_result["action"].get<std::string>(), "drop"); + } catch (const std::exception &ex) { + FAIL() << ex.what(); + } +} + +TEST_F(RuleEditCommandTest, changeAction) +{ + try { + m_irccdctl.client().request({ + { "command", "rule-edit" }, + { "action", "accept" }, + { "index", 0 } + }); + + poll([&] () { + return m_result.is_object(); + }); + + ASSERT_TRUE(m_result.is_object()); + ASSERT_TRUE(m_result["status"].get<bool>()); + + m_result = nullptr; + m_irccdctl.client().request({ + { "command", "rule-info" }, + { "index", 0 } + }); + + poll([&] () { + return m_result.is_object(); + }); + + ASSERT_TRUE(m_result.is_object()); + ASSERT_TRUE(m_result["status"].get<bool>()); + ASSERT_TRUE(contains(m_result["servers"], "s1")); + ASSERT_TRUE(contains(m_result["servers"], "s2")); + ASSERT_TRUE(contains(m_result["channels"], "c1")); + ASSERT_TRUE(contains(m_result["channels"], "c2")); + ASSERT_TRUE(contains(m_result["plugins"], "p1")); + ASSERT_TRUE(contains(m_result["plugins"], "p2")); + ASSERT_TRUE(contains(m_result["events"], "onMessage")); + ASSERT_TRUE(contains(m_result["events"], "onCommand")); + ASSERT_EQ(m_result["action"].get<std::string>(), "accept"); + } catch (const std::exception &ex) { + FAIL() << ex.what(); + } +} + +TEST_F(RuleEditCommandTest, removeServer) +{ + try { + m_irccdctl.client().request({ + { "command", "rule-edit" }, + { "remove-servers", { "s2" } }, + { "index", 0 } + }); + + poll([&] () { + return m_result.is_object(); + }); + + ASSERT_TRUE(m_result.is_object()); + ASSERT_TRUE(m_result["status"].get<bool>()); + + m_result = nullptr; + m_irccdctl.client().request({ + { "command", "rule-info" }, + { "index", 0 } + }); + + poll([&] () { + return m_result.is_object(); + }); + + ASSERT_TRUE(m_result.is_object()); + ASSERT_TRUE(m_result["status"].get<bool>()); + ASSERT_TRUE(contains(m_result["servers"], "s1")); + ASSERT_FALSE(contains(m_result["servers"], "s2")); + ASSERT_TRUE(contains(m_result["channels"], "c1")); + ASSERT_TRUE(contains(m_result["channels"], "c2")); + ASSERT_TRUE(contains(m_result["plugins"], "p1")); + ASSERT_TRUE(contains(m_result["plugins"], "p2")); + ASSERT_TRUE(contains(m_result["events"], "onMessage")); + ASSERT_TRUE(contains(m_result["events"], "onCommand")); + ASSERT_EQ(m_result["action"].get<std::string>(), "drop"); + } catch (const std::exception &ex) { + FAIL() << ex.what(); + } +} + +TEST_F(RuleEditCommandTest, removeChannel) +{ + try { + m_irccdctl.client().request({ + { "command", "rule-edit" }, + { "remove-channels", { "c2" } }, + { "index", 0 } + }); + + poll([&] () { + return m_result.is_object(); + }); + + ASSERT_TRUE(m_result.is_object()); + ASSERT_TRUE(m_result["status"].get<bool>()); + + m_result = nullptr; + m_irccdctl.client().request({ + { "command", "rule-info" }, + { "index", 0 } + }); + + poll([&] () { + return m_result.is_object(); + }); + + ASSERT_TRUE(m_result.is_object()); + ASSERT_TRUE(m_result["status"].get<bool>()); + ASSERT_TRUE(contains(m_result["servers"], "s1")); + ASSERT_TRUE(contains(m_result["servers"], "s2")); + ASSERT_TRUE(contains(m_result["channels"], "c1")); + ASSERT_FALSE(contains(m_result["channels"], "c2")); + ASSERT_TRUE(contains(m_result["plugins"], "p1")); + ASSERT_TRUE(contains(m_result["plugins"], "p2")); + ASSERT_TRUE(contains(m_result["events"], "onMessage")); + ASSERT_TRUE(contains(m_result["events"], "onCommand")); + ASSERT_EQ(m_result["action"].get<std::string>(), "drop"); + } catch (const std::exception &ex) { + FAIL() << ex.what(); + } +} + +TEST_F(RuleEditCommandTest, removePlugin) +{ + try { + m_irccdctl.client().request({ + { "command", "rule-edit" }, + { "remove-plugins", { "p2" } }, + { "index", 0 } + }); + + poll([&] () { + return m_result.is_object(); + }); + + ASSERT_TRUE(m_result.is_object()); + ASSERT_TRUE(m_result["status"].get<bool>()); + + m_result = nullptr; + m_irccdctl.client().request({ + { "command", "rule-info" }, + { "index", 0 } + }); + + poll([&] () { + return m_result.is_object(); + }); + + ASSERT_TRUE(m_result.is_object()); + ASSERT_TRUE(m_result["status"].get<bool>()); + ASSERT_TRUE(contains(m_result["servers"], "s1")); + ASSERT_TRUE(contains(m_result["servers"], "s2")); + ASSERT_TRUE(contains(m_result["channels"], "c1")); + ASSERT_TRUE(contains(m_result["channels"], "c2")); + ASSERT_TRUE(contains(m_result["plugins"], "p1")); + ASSERT_FALSE(contains(m_result["plugins"], "p2")); + ASSERT_TRUE(contains(m_result["events"], "onMessage")); + ASSERT_TRUE(contains(m_result["events"], "onCommand")); + ASSERT_EQ(m_result["action"].get<std::string>(), "drop"); + } catch (const std::exception &ex) { + FAIL() << ex.what(); + } +} + +TEST_F(RuleEditCommandTest, removeEvent) +{ + try { + m_irccdctl.client().request({ + { "command", "rule-edit" }, + { "remove-events", { "onCommand" } }, + { "index", 0 } + }); + + poll([&] () { + return m_result.is_object(); + }); + + ASSERT_TRUE(m_result.is_object()); + ASSERT_TRUE(m_result["status"].get<bool>()); + + m_result = nullptr; + m_irccdctl.client().request({ + { "command", "rule-info" }, + { "index", 0 } + }); + + poll([&] () { + return m_result.is_object(); + }); + + ASSERT_TRUE(m_result.is_object()); + ASSERT_TRUE(m_result["status"].get<bool>()); + ASSERT_TRUE(contains(m_result["servers"], "s1")); + ASSERT_TRUE(contains(m_result["servers"], "s2")); + ASSERT_TRUE(contains(m_result["channels"], "c1")); + ASSERT_TRUE(contains(m_result["channels"], "c2")); + ASSERT_TRUE(contains(m_result["plugins"], "p1")); + ASSERT_TRUE(contains(m_result["plugins"], "p2")); + ASSERT_TRUE(contains(m_result["events"], "onMessage")); + ASSERT_FALSE(contains(m_result["events"], "onCommand")); + ASSERT_EQ(m_result["action"].get<std::string>(), "drop"); + } catch (const std::exception &ex) { + FAIL() << ex.what(); + } +} + +TEST_F(RuleEditCommandTest, removeEventAndServer) +{ + try { + m_irccdctl.client().request({ + { "command", "rule-edit" }, + { "remove-servers", { "s2" } }, + { "remove-events", { "onCommand" } }, + { "index", 0 } + }); + + poll([&] () { + return m_result.is_object(); + }); + + ASSERT_TRUE(m_result.is_object()); + ASSERT_TRUE(m_result["status"].get<bool>()); + + m_result = nullptr; + m_irccdctl.client().request({ + { "command", "rule-info" }, + { "index", 0 } + }); + + poll([&] () { + return m_result.is_object(); + }); + + ASSERT_TRUE(m_result.is_object()); + ASSERT_TRUE(m_result["status"].get<bool>()); + ASSERT_TRUE(contains(m_result["servers"], "s1")); + ASSERT_FALSE(contains(m_result["servers"], "s2")); + ASSERT_TRUE(contains(m_result["channels"], "c1")); + ASSERT_TRUE(contains(m_result["channels"], "c2")); + ASSERT_TRUE(contains(m_result["plugins"], "p1")); + ASSERT_TRUE(contains(m_result["plugins"], "p2")); + ASSERT_TRUE(contains(m_result["events"], "onMessage")); + ASSERT_FALSE(contains(m_result["events"], "onCommand")); + ASSERT_EQ(m_result["action"].get<std::string>(), "drop"); + } catch (const std::exception &ex) { + FAIL() << ex.what(); + } +} + +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + + return RUN_ALL_TESTS(); +}