changeset 869:c885cb16540d

tests: add server-service test, continue #742
author David Demelier <markand@malikania.fr>
date Fri, 26 Jul 2019 21:10:00 +0000
parents 7619105cc818
children 2b335166e641
files libirccd-daemon/irccd/daemon/server_service.cpp libirccd-daemon/irccd/daemon/server_service.hpp tests/src/libirccd-daemon/CMakeLists.txt tests/src/libirccd-daemon/server-service/CMakeLists.txt tests/src/libirccd-daemon/server-service/main.cpp
diffstat 5 files changed, 249 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/libirccd-daemon/irccd/daemon/server_service.cpp	Fri Jul 26 21:01:00 2019 +0000
+++ b/libirccd-daemon/irccd/daemon/server_service.cpp	Fri Jul 26 21:10:00 2019 +0000
@@ -569,7 +569,9 @@
 void server_service::add(std::shared_ptr<server> server)
 {
 	assert(server);
-	assert(!has(server->get_id()));
+
+	if (has(server->get_id()))
+		throw server_error(server_error::already_exists);
 
 	servers_.push_back(server);
 	connect(server);
@@ -605,6 +607,19 @@
 	disconnect(require(id));
 }
 
+void server_service::disconnect()
+{
+	const auto save = servers_;
+
+	for (const auto& s : save) {
+		try {
+			disconnect(s);
+		} catch (const server_error& ex) {
+			bot_.get_log().warning(*s) << ex.what() << std::endl;
+		}
+	}
+}
+
 void server_service::reconnect(std::string_view id)
 {
 	reconnect(require(id));
--- a/libirccd-daemon/irccd/daemon/server_service.hpp	Fri Jul 26 21:01:00 2019 +0000
+++ b/libirccd-daemon/irccd/daemon/server_service.hpp	Fri Jul 26 21:10:00 2019 +0000
@@ -27,6 +27,7 @@
 #include <irccd/sysconfig.hpp>
 
 #include <memory>
+#include <string_view>
 #include <system_error>
 #include <vector>
 
@@ -43,6 +44,9 @@
 /**
  * \brief Manage IRC servers.
  * \ingroup services
+ *
+ * This class holds servers and wait for IRC events to come and then are
+ * dispatched through the plugins.
  */
 class server_service {
 private:
@@ -77,48 +81,53 @@
 	/**
 	 * Check if a server exists.
 	 *
-	 * \param name the name
+	 * \param id the server identifier
 	 * \return true if exists
 	 */
-	auto has(std::string_view name) const noexcept -> bool;
+	auto has(std::string_view id) const noexcept -> bool;
 
 	/**
 	 * Add a new server to the application.
 	 *
-	 * \pre hasServer must return false
 	 * \param sv the server
+	 * \throw server_error on errors
 	 */
 	void add(std::shared_ptr<server> sv);
 
 	/**
 	 * Get a server or empty one if not found
 	 *
-	 * \param name the server name
+	 * \param id the server identifier
 	 * \return the server or empty one if not found
 	 */
-	auto get(std::string_view name) const noexcept -> std::shared_ptr<server>;
+	auto get(std::string_view id) const noexcept -> std::shared_ptr<server>;
 
 	/**
 	 * Find a server from a JSON object.
 	 *
-	 * \param name the server name
+	 * \param id the server identifier
 	 * \return the server
 	 * \throw server_error on errors
 	 */
-	auto require(std::string_view name) const -> std::shared_ptr<server>;
+	auto require(std::string_view id) const -> std::shared_ptr<server>;
 
 	/**
 	 * Force disconnection, this also call plugin::handle_disconnect handler.
 	 *
-	 * \param id the server id
+	 * \param id the server identifier
 	 * \throw server_error on errors
 	 */
 	void disconnect(std::string_view id);
 
 	/**
+	 * Disconnect all servers.
+	 */
+	void disconnect();
+
+	/**
 	 * Force reconnection, this also call plugin::handle_disconnect handler.
 	 *
-	 * \param id the server id
+	 * \param id the server identifier
 	 * \return the server
 	 * \throw server_error on errors
 	 */
@@ -134,9 +143,9 @@
 	 *
 	 * The server if any, will be disconnected.
 	 *
-	 * \param name the server name
+	 * \param id the server identifier
 	 */
-	void remove(std::string_view name);
+	void remove(std::string_view id);
 
 	/**
 	 * Remove all servers.
--- a/tests/src/libirccd-daemon/CMakeLists.txt	Fri Jul 26 21:01:00 2019 +0000
+++ b/tests/src/libirccd-daemon/CMakeLists.txt	Fri Jul 26 21:10:00 2019 +0000
@@ -51,4 +51,5 @@
 add_subdirectory(rule-util)
 add_subdirectory(server)
 add_subdirectory(server-util)
+add_subdirectory(server-service)
 add_subdirectory(transports)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/libirccd-daemon/server-service/CMakeLists.txt	Fri Jul 26 21:10:00 2019 +0000
@@ -0,0 +1,23 @@
+#
+# CMakeLists.txt -- CMake build system for irccd
+#
+# 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.
+#
+
+irccd_define_test(
+	NAME server-service
+	SOURCES main.cpp
+	LIBRARIES libirccd-daemon
+)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/src/libirccd-daemon/server-service/main.cpp	Fri Jul 26 21:10:00 2019 +0000
@@ -0,0 +1,189 @@
+/*
+ * main.cpp -- test server_service object
+ *
+ * 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 "server_service"
+#include <boost/test/unit_test.hpp>
+
+#include <irccd/daemon/server_service.hpp>
+
+#include <irccd/test/mock_server.hpp>
+#include <irccd/test/irccd_fixture.hpp>
+
+namespace test = irccd::test;
+
+namespace irccd::daemon {
+
+namespace {
+
+BOOST_FIXTURE_TEST_SUITE(server_service_test_suite, test::irccd_fixture)
+
+BOOST_AUTO_TEST_CASE(add)
+{
+	auto sv1 = std::make_shared<test::mock_server>(ctx_, "m1", "local");
+	auto sv2 = std::make_shared<test::mock_server>(ctx_, "m2", "local");
+
+	bot_.get_servers().add(sv1);
+	bot_.get_servers().add(sv2);
+
+	BOOST_TEST(sv1->find("connect").size() == 1U);
+	BOOST_TEST(sv2->find("connect").size() == 1U);
+	BOOST_TEST(static_cast<int>(sv1->get_state()) == static_cast<int>(server::state::connected));
+	BOOST_TEST(static_cast<int>(sv2->get_state()) == static_cast<int>(server::state::connected));
+}
+
+BOOST_AUTO_TEST_CASE(remove)
+{
+	auto sv1 = std::make_shared<test::mock_server>(ctx_, "m1", "local");
+	auto sv2 = std::make_shared<test::mock_server>(ctx_, "m2", "local");
+
+	bot_.get_servers().add(sv1);
+	bot_.get_servers().add(sv2);
+
+	sv1->clear();
+	sv2->clear();
+
+	bot_.get_servers().remove("m2");
+
+	BOOST_TEST(bot_.get_servers().has("m1"));
+	BOOST_TEST(!bot_.get_servers().has("m2"));
+	BOOST_TEST(sv2->find("disconnect").size() == 1U);
+	BOOST_TEST(static_cast<int>(sv1->get_state()) == static_cast<int>(server::state::connected));
+	BOOST_TEST(static_cast<int>(sv2->get_state()) == static_cast<int>(server::state::disconnected));
+}
+
+BOOST_AUTO_TEST_CASE(reconnect_one)
+{
+	auto sv1 = std::make_shared<test::mock_server>(ctx_, "m1", "local");
+	auto sv2 = std::make_shared<test::mock_server>(ctx_, "m2", "local");
+
+	bot_.get_servers().add(sv1);
+	bot_.get_servers().add(sv2);
+
+	sv1->clear();
+	sv2->clear();
+
+	bot_.get_servers().reconnect("m1");
+
+	BOOST_TEST(sv1->find("disconnect").size() == 1U);
+	BOOST_TEST(sv2->find("disconnect").size() == 0U);
+	BOOST_TEST(sv1->find("connect").size() == 1U);
+	BOOST_TEST(sv2->find("connect").size() == 0U);
+	BOOST_TEST(static_cast<int>(sv1->get_state()) == static_cast<int>(server::state::connected));
+	BOOST_TEST(static_cast<int>(sv2->get_state()) == static_cast<int>(server::state::connected));
+}
+
+BOOST_AUTO_TEST_CASE(reconnect_all)
+{
+	auto sv1 = std::make_shared<test::mock_server>(ctx_, "m1", "local");
+	auto sv2 = std::make_shared<test::mock_server>(ctx_, "m2", "local");
+
+	bot_.get_servers().add(sv1);
+	bot_.get_servers().add(sv2);
+
+	sv1->clear();
+	sv2->clear();
+
+	bot_.get_servers().reconnect();
+
+	BOOST_TEST(sv1->find("disconnect").size() == 1U);
+	BOOST_TEST(sv2->find("disconnect").size() == 1U);
+	BOOST_TEST(sv1->find("connect").size() == 1U);
+	BOOST_TEST(sv2->find("connect").size() == 1U);
+	BOOST_TEST(static_cast<int>(sv1->get_state()) == static_cast<int>(server::state::connected));
+	BOOST_TEST(static_cast<int>(sv2->get_state()) == static_cast<int>(server::state::connected));
+}
+
+BOOST_AUTO_TEST_CASE(disconnect_one)
+{
+	auto sv1 = std::make_shared<test::mock_server>(ctx_, "m1", "local");
+	auto sv2 = std::make_shared<test::mock_server>(ctx_, "m2", "local");
+
+	bot_.get_servers().add(sv1);
+	bot_.get_servers().add(sv2);
+
+	sv1->clear();
+	sv2->clear();
+
+	bot_.get_servers().disconnect("m1");
+
+	BOOST_TEST(sv1->find("disconnect").size() == 1U);
+	BOOST_TEST(sv2->find("disconnect").size() == 0U);
+	BOOST_TEST(static_cast<int>(sv1->get_state()) == static_cast<int>(server::state::disconnected));
+	BOOST_TEST(static_cast<int>(sv2->get_state()) == static_cast<int>(server::state::connected));
+}
+
+BOOST_AUTO_TEST_CASE(disconnect_all)
+{
+	auto sv1 = std::make_shared<test::mock_server>(ctx_, "m1", "local");
+	auto sv2 = std::make_shared<test::mock_server>(ctx_, "m2", "local");
+
+	bot_.get_servers().add(sv1);
+	bot_.get_servers().add(sv2);
+
+	sv1->clear();
+	sv2->clear();
+
+	bot_.get_servers().disconnect();
+
+	BOOST_TEST(sv1->find("disconnect").size() == 1U);
+	BOOST_TEST(sv2->find("disconnect").size() == 1U);
+	BOOST_TEST(static_cast<int>(sv1->get_state()) == static_cast<int>(server::state::disconnected));
+	BOOST_TEST(static_cast<int>(sv2->get_state()) == static_cast<int>(server::state::disconnected));
+}
+
+BOOST_AUTO_TEST_CASE(clear)
+{
+	auto sv1 = std::make_shared<test::mock_server>(ctx_, "m1", "local");
+	auto sv2 = std::make_shared<test::mock_server>(ctx_, "m2", "local");
+
+	bot_.get_servers().add(sv1);
+	bot_.get_servers().add(sv2);
+
+	sv1->clear();
+	sv2->clear();
+
+	bot_.get_servers().clear();
+
+	BOOST_TEST(bot_.get_servers().list().empty());
+	BOOST_TEST(sv1->find("disconnect").size() == 1U);
+	BOOST_TEST(sv2->find("disconnect").size() == 1U);
+	BOOST_TEST(static_cast<int>(sv1->get_state()) == static_cast<int>(server::state::disconnected));
+	BOOST_TEST(static_cast<int>(sv2->get_state()) == static_cast<int>(server::state::disconnected));
+}
+
+BOOST_AUTO_TEST_CASE(get)
+{
+	bot_.get_servers().add(std::make_shared<test::mock_server>(ctx_, "m1", "local"));
+
+	BOOST_TEST(bot_.get_servers().get("m1"));
+	BOOST_TEST(!bot_.get_servers().get("none"));
+}
+
+BOOST_AUTO_TEST_CASE(require)
+{
+	bot_.get_servers().add(std::make_shared<test::mock_server>(ctx_, "m1", "local"));
+
+	BOOST_TEST(bot_.get_servers().require("m1"));
+	BOOST_REQUIRE_THROW(bot_.get_servers().require("none"), server_error);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // !namespace
+
+} // !irccd::daemon