Mercurial > irccd
diff tests/src/libirccd-daemon/hook/main.cpp @ 895:f0d6bc79aa32
irccd: implement hooks, closes #2342 @2h
The hook mechanism is an alternative approach to plugins which allow the user to
write lightweight scripts in any language.
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 05 Sep 2019 13:39:32 +0200 |
parents | |
children | b594a9269f49 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/src/libirccd-daemon/hook/main.cpp Thu Sep 05 13:39:32 2019 +0200 @@ -0,0 +1,280 @@ +/* + * main.cpp -- test hook functions + * + * Copyright (c) 2013-2019 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 "hook" +#include <boost/test/unit_test.hpp> + +#include <string> +#include <vector> + +#include <irccd/daemon/bot.hpp> +#include <irccd/daemon/hook.hpp> +#include <irccd/daemon/logger.hpp> + +#include <irccd/test/mock_server.hpp> + +using std::string; +using std::vector; +using std::shared_ptr; +using std::make_unique; +using std::make_shared; + +using boost::asio::io_context; + +using irccd::daemon::logger::sink; + +using irccd::test::mock_server; + +namespace irccd::daemon { + +namespace { + +/* + * Since stdout/stderr from the hook is logger through the irccd's logger, we'll + * gonna store every message logged into it and compare if the values are + * appropriate. + */ +class memory_sink : public logger::sink { +public: + using list = vector<string>; + +private: + list debug_; + list warning_; + list info_; + +public: + auto get_debug() const noexcept -> const list&; + auto get_info() const noexcept -> const list&; + auto get_warning() const noexcept -> const list&; + void write_debug(const std::string& line) override; + void write_info(const std::string& line) override; + void write_warning(const std::string& line) override; +}; + +auto memory_sink::get_debug() const noexcept -> const list& +{ + return debug_; +} + +auto memory_sink::get_info() const noexcept -> const list& +{ + return info_; +} + +auto memory_sink::get_warning() const noexcept -> const list& +{ + return warning_; +} + +void memory_sink::write_debug(const std::string& line) +{ + debug_.push_back(line); +} + +void memory_sink::write_info(const std::string& line) +{ + info_.push_back(line); +} + +void memory_sink::write_warning(const std::string& line) +{ + warning_.push_back(line); +} + +class hook_fixture { +protected: + io_context io_; + bot bot_{io_}; + hook hook_{"test", HOOK_FILE}; + memory_sink* sink_{nullptr}; + shared_ptr<mock_server> server_; + +public: + hook_fixture(); +}; + +hook_fixture::hook_fixture() + : server_(make_shared<mock_server>(io_, "test")) +{ + auto sink = make_unique<memory_sink>(); + + sink_ = sink.get(); + bot_.set_log(std::move(sink)); + bot_.get_log().set_verbose(true); +} + +BOOST_FIXTURE_TEST_SUITE(hook_fixture_suite, hook_fixture) + +BOOST_AUTO_TEST_CASE(connect) +{ + hook_.handle_connect(bot_, {server_}); + + BOOST_TEST(sink_->get_info().size() == 2U); + BOOST_TEST(sink_->get_warning().empty()); + BOOST_TEST(sink_->get_info()[0] == "hook test: event: onConnect"); + BOOST_TEST(sink_->get_info()[1] == "hook test: server: test"); +} + +BOOST_AUTO_TEST_CASE(disconnect) +{ + hook_.handle_disconnect(bot_, {server_}); + + BOOST_TEST(sink_->get_info().size() == 2U); + BOOST_TEST(sink_->get_warning().empty()); + BOOST_TEST(sink_->get_info()[0] == "hook test: event: onDisconnect"); + BOOST_TEST(sink_->get_info()[1] == "hook test: server: test"); +} + +BOOST_AUTO_TEST_CASE(invite) +{ + hook_.handle_invite(bot_, {server_, "jean", "#staff", "NiReaS"}); + + BOOST_TEST(sink_->get_info().size() == 5U); + BOOST_TEST(sink_->get_warning().empty()); + BOOST_TEST(sink_->get_info()[0] == "hook test: event: onInvite"); + BOOST_TEST(sink_->get_info()[1] == "hook test: server: test"); + BOOST_TEST(sink_->get_info()[2] == "hook test: origin: jean"); + BOOST_TEST(sink_->get_info()[3] == "hook test: channel: #staff"); + BOOST_TEST(sink_->get_info()[4] == "hook test: target: NiReaS"); +} + +BOOST_AUTO_TEST_CASE(join) +{ + hook_.handle_join(bot_, {server_, "jean", "#staff"}); + + BOOST_TEST(sink_->get_info().size() == 4U); + BOOST_TEST(sink_->get_warning().empty()); + BOOST_TEST(sink_->get_info()[0] == "hook test: event: onJoin"); + BOOST_TEST(sink_->get_info()[1] == "hook test: server: test"); + BOOST_TEST(sink_->get_info()[2] == "hook test: origin: jean"); + BOOST_TEST(sink_->get_info()[3] == "hook test: channel: #staff"); +} + +BOOST_AUTO_TEST_CASE(kick) +{ + hook_.handle_kick(bot_, {server_, "jean", "#staff", "NiReaS", "stop it"}); + + BOOST_TEST(sink_->get_info().size() == 6U); + BOOST_TEST(sink_->get_warning().empty()); + BOOST_TEST(sink_->get_info()[0] == "hook test: event: onKick"); + BOOST_TEST(sink_->get_info()[1] == "hook test: server: test"); + BOOST_TEST(sink_->get_info()[2] == "hook test: origin: jean"); + BOOST_TEST(sink_->get_info()[3] == "hook test: channel: #staff"); + BOOST_TEST(sink_->get_info()[4] == "hook test: target: NiReaS"); + BOOST_TEST(sink_->get_info()[5] == "hook test: reason: stop it"); +} + +BOOST_AUTO_TEST_CASE(message) +{ + hook_.handle_message(bot_, {server_, "jean", "#staff", "coucou tout le monde"}); + + BOOST_TEST(sink_->get_info().size() == 5U); + BOOST_TEST(sink_->get_warning().empty()); + BOOST_TEST(sink_->get_info()[0] == "hook test: event: onMessage"); + BOOST_TEST(sink_->get_info()[1] == "hook test: server: test"); + BOOST_TEST(sink_->get_info()[2] == "hook test: origin: jean"); + BOOST_TEST(sink_->get_info()[3] == "hook test: channel: #staff"); + BOOST_TEST(sink_->get_info()[4] == "hook test: message: coucou tout le monde"); +} + +BOOST_AUTO_TEST_CASE(me) +{ + hook_.handle_me(bot_, {server_, "jean", "#staff", "coucou tout le monde"}); + + BOOST_TEST(sink_->get_info().size() == 5U); + BOOST_TEST(sink_->get_warning().empty()); + BOOST_TEST(sink_->get_info()[0] == "hook test: event: onMe"); + BOOST_TEST(sink_->get_info()[1] == "hook test: server: test"); + BOOST_TEST(sink_->get_info()[2] == "hook test: origin: jean"); + BOOST_TEST(sink_->get_info()[3] == "hook test: channel: #staff"); + BOOST_TEST(sink_->get_info()[4] == "hook test: message: coucou tout le monde"); +} + +BOOST_AUTO_TEST_CASE(mode) +{ + hook_.handle_mode(bot_, {server_, "jean", "#staff", "+o", "franck", "abc", "xyz" }); + + BOOST_TEST(sink_->get_info().size() == 8U); + BOOST_TEST(sink_->get_warning().empty()); + BOOST_TEST(sink_->get_info()[0] == "hook test: event: onMode"); + BOOST_TEST(sink_->get_info()[1] == "hook test: server: test"); + BOOST_TEST(sink_->get_info()[2] == "hook test: origin: jean"); + BOOST_TEST(sink_->get_info()[3] == "hook test: channel: #staff"); + BOOST_TEST(sink_->get_info()[4] == "hook test: mode: +o"); + BOOST_TEST(sink_->get_info()[5] == "hook test: limit: franck"); + BOOST_TEST(sink_->get_info()[6] == "hook test: user: abc"); + BOOST_TEST(sink_->get_info()[7] == "hook test: mask: xyz"); +} + +BOOST_AUTO_TEST_CASE(nick) +{ + hook_.handle_nick(bot_, {server_, "jean", "doctor"}); + + BOOST_TEST(sink_->get_info().size() == 4U); + BOOST_TEST(sink_->get_warning().empty()); + BOOST_TEST(sink_->get_info()[0] == "hook test: event: onNick"); + BOOST_TEST(sink_->get_info()[1] == "hook test: server: test"); + BOOST_TEST(sink_->get_info()[2] == "hook test: origin: jean"); + BOOST_TEST(sink_->get_info()[3] == "hook test: nick: doctor"); +} + +BOOST_AUTO_TEST_CASE(notice) +{ + hook_.handle_notice(bot_, {server_, "jean", "#staff", "coucou tout le monde"}); + + BOOST_TEST(sink_->get_info().size() == 5U); + BOOST_TEST(sink_->get_warning().empty()); + BOOST_TEST(sink_->get_info()[0] == "hook test: event: onNotice"); + BOOST_TEST(sink_->get_info()[1] == "hook test: server: test"); + BOOST_TEST(sink_->get_info()[2] == "hook test: origin: jean"); + BOOST_TEST(sink_->get_info()[3] == "hook test: channel: #staff"); + BOOST_TEST(sink_->get_info()[4] == "hook test: message: coucou tout le monde"); +} + +BOOST_AUTO_TEST_CASE(part) +{ + hook_.handle_part(bot_, {server_, "jean", "#windows", "je n'aime pas ici"}); + + BOOST_TEST(sink_->get_info().size() == 5U); + BOOST_TEST(sink_->get_warning().empty()); + BOOST_TEST(sink_->get_info()[0] == "hook test: event: onPart"); + BOOST_TEST(sink_->get_info()[1] == "hook test: server: test"); + BOOST_TEST(sink_->get_info()[2] == "hook test: origin: jean"); + BOOST_TEST(sink_->get_info()[3] == "hook test: channel: #windows"); + BOOST_TEST(sink_->get_info()[4] == "hook test: reason: je n'aime pas ici"); +} + +BOOST_AUTO_TEST_CASE(topic) +{ + hook_.handle_topic(bot_, {server_, "jean", "#windows", "attention Windows est un malware"}); + + BOOST_TEST(sink_->get_info().size() == 5U); + BOOST_TEST(sink_->get_warning().empty()); + BOOST_TEST(sink_->get_info()[0] == "hook test: event: onTopic"); + BOOST_TEST(sink_->get_info()[1] == "hook test: server: test"); + BOOST_TEST(sink_->get_info()[2] == "hook test: origin: jean"); + BOOST_TEST(sink_->get_info()[3] == "hook test: channel: #windows"); + BOOST_TEST(sink_->get_info()[4] == "hook test: topic: attention Windows est un malware"); +} + +BOOST_AUTO_TEST_SUITE_END() + +} // !namespace + +} // !irccd::daemon