--- /dev/null
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef BOOST_TEST_DYN_LINK
+#define BOOST_TEST_DYN_LINK
+#endif
+#define BOOST_TEST_NO_MAIN
+
+#include <boost/test/unit_test.hpp>
+
+#include "dnsdist-server-pool.hh"
+#include "dnsdist.hh"
+
+BOOST_AUTO_TEST_SUITE(dnsdistserverpool)
+
+BOOST_AUTO_TEST_CASE(test_ServerPoolBasics)
+{
+ ServerPool pool{};
+ BOOST_CHECK(!pool.getCache());
+
+ BOOST_CHECK(!pool.getECS());
+ /* will be ignored because there is no server with ECS
+ in the pool at this point */
+ pool.setECS(true);
+ BOOST_CHECK(!pool.getECS());
+ pool.setECS(false);
+ BOOST_CHECK(!pool.getECS());
+
+ BOOST_CHECK(pool.getZeroScope());
+ /* will be ignored because there is no server with the
+ zero scope feature disabled in the pool at this point */
+ pool.setZeroScope(false);
+ BOOST_CHECK(pool.getZeroScope());
+ pool.setZeroScope(true);
+ BOOST_CHECK(pool.getZeroScope());
+
+ BOOST_CHECK(!pool.isTCPOnly());
+ BOOST_CHECK(pool.isConsistent());
+ BOOST_CHECK(!pool.hasAtLeastOneServerAvailable());
+ BOOST_CHECK_EQUAL(pool.countServers(true), 0U);
+ BOOST_CHECK_EQUAL(pool.countServers(false), 0U);
+ BOOST_CHECK_EQUAL(pool.poolLoad(), 0U);
+
+ {
+ const auto& servers = pool.getServers();
+ BOOST_CHECK(servers.empty());
+ }
+
+ {
+ /* add one server */
+ DownstreamState::Config config;
+ auto ds = std::make_shared<DownstreamState>(std::move(config), nullptr, false);
+ pool.addServer(ds);
+ BOOST_CHECK(!pool.isTCPOnly());
+ BOOST_CHECK(pool.isConsistent());
+ /* the server is unavailable by default */
+ BOOST_CHECK(!pool.hasAtLeastOneServerAvailable());
+ BOOST_CHECK_EQUAL(pool.countServers(true), 0U);
+ BOOST_CHECK_EQUAL(pool.countServers(false), 1U);
+
+ BOOST_CHECK_EQUAL(pool.poolLoad(), 0U);
+ {
+ const auto& servers = pool.getServers();
+ BOOST_CHECK(!servers.empty());
+ }
+
+ /* let's make it available */
+ ds->setUp();
+ BOOST_CHECK(pool.hasAtLeastOneServerAvailable());
+ BOOST_CHECK_EQUAL(pool.countServers(true), 1U);
+ BOOST_CHECK_EQUAL(pool.countServers(false), 1U);
+
+ /* now remove it */
+ pool.removeServer(ds);
+ BOOST_CHECK_EQUAL(pool.countServers(true), 0U);
+ BOOST_CHECK_EQUAL(pool.countServers(false), 0U);
+ {
+ const auto& servers = pool.getServers();
+ BOOST_CHECK(servers.empty());
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_ServerPoolECSConsistency)
+{
+ ServerPool pool{};
+
+ /* one server with ECS */
+ DownstreamState::Config config1;
+ config1.useECS = true;
+ auto ds1 = std::make_shared<DownstreamState>(std::move(config1), nullptr, false);
+ pool.addServer(ds1);
+ BOOST_CHECK_EQUAL(pool.countServers(false), 1U);
+ BOOST_CHECK(!pool.isTCPOnly());
+ BOOST_CHECK(pool.isConsistent());
+ BOOST_CHECK(pool.getECS());
+ /* should be ignored */
+ pool.setECS(false);
+ BOOST_CHECK(pool.getECS());
+
+ /* and now one without ECS */
+ DownstreamState::Config config2;
+ config2.useECS = false;
+ auto ds2 = std::make_shared<DownstreamState>(std::move(config2), nullptr, false);
+ pool.addServer(ds2);
+ BOOST_CHECK_EQUAL(pool.countServers(false), 2U);
+ BOOST_CHECK(!pool.isTCPOnly());
+ BOOST_CHECK(!pool.isConsistent());
+ /* the first backend has ECS so the pool automatically picked up
+ ECS-enabled, and after that the inconsistency meant the state
+ was not longer automatically updated */
+ BOOST_CHECK(pool.getECS());
+ /* should NOT be ignored */
+ pool.setECS(false);
+ BOOST_CHECK(!pool.getECS());
+ /* should NOT be ignored */
+ pool.setECS(true);
+ BOOST_CHECK(pool.getECS());
+
+ /* remove the server with ECS */
+ pool.removeServer(ds1);
+ BOOST_CHECK_EQUAL(pool.countServers(false), 1U);
+ BOOST_CHECK(!pool.isTCPOnly());
+ BOOST_CHECK(pool.isConsistent());
+ BOOST_CHECK(!pool.getECS());
+
+ /* re-add the server with ECS */
+ pool.addServer(ds1);
+ BOOST_CHECK_EQUAL(pool.countServers(false), 2U);
+ BOOST_CHECK(!pool.isTCPOnly());
+ BOOST_CHECK(!pool.isConsistent());
+ /* the pool was in a consistent state without ECS,
+ and now is in a inconsistent state so it not automatically
+ updated */
+ BOOST_CHECK(!pool.getECS());
+}
+
+BOOST_AUTO_TEST_CASE(test_ServerPoolTCPOnlyConsistency)
+{
+ ServerPool pool{};
+
+ DownstreamState::Config config1;
+ config1.d_tcpOnly = true;
+ auto ds1 = std::make_shared<DownstreamState>(std::move(config1), nullptr, false);
+ pool.addServer(ds1);
+ BOOST_CHECK_EQUAL(pool.countServers(false), 1U);
+ BOOST_CHECK(pool.isTCPOnly());
+ BOOST_CHECK(pool.isConsistent());
+ BOOST_CHECK(!pool.getECS());
+
+ DownstreamState::Config config2;
+ config2.d_tcpOnly = false;
+ auto ds2 = std::make_shared<DownstreamState>(std::move(config2), nullptr, false);
+ pool.addServer(ds2);
+ BOOST_CHECK_EQUAL(pool.countServers(false), 2U);
+ BOOST_CHECK(!pool.isTCPOnly());
+ BOOST_CHECK(!pool.isConsistent());
+
+ /* remove the TCP-only server */
+ pool.removeServer(ds1);
+ BOOST_CHECK_EQUAL(pool.countServers(false), 1U);
+ BOOST_CHECK(!pool.isTCPOnly());
+ BOOST_CHECK(pool.isConsistent());
+
+ /* re-add the server with TCP-only */
+ pool.addServer(ds1);
+ BOOST_CHECK_EQUAL(pool.countServers(false), 2U);
+ BOOST_CHECK(!pool.isTCPOnly());
+ BOOST_CHECK(!pool.isConsistent());
+}
+
+BOOST_AUTO_TEST_SUITE_END()