Browse Source

Add freeradius unit tests

Olivier Le Brouster 7 years ago
parent
commit
4997201f2a

+ 0 - 1
configure.ac

@@ -1254,7 +1254,6 @@ AC_CONFIG_FILES([Makefile
                  src/bin/admin/tests/memfile_tests.sh
                  src/bin/admin/tests/mysql_tests.sh
                  src/bin/admin/tests/pgsql_tests.sh
-                 src/bin/admin/tests/radius_tests.sh
                  src/bin/agent/Makefile
                  src/bin/agent/tests/Makefile
                  src/bin/agent/tests/ca_process_tests.sh

+ 0 - 4
src/bin/admin/tests/Makefile.am

@@ -14,10 +14,6 @@ if HAVE_CQL
 SHTESTS += cql_tests.sh
 endif
 
-if HAVE_RADCLI
-SHTESTS += radius_tests.sh
-endif
-
 noinst_SCRIPTS = $(SHTESTS)
 
 EXTRA_DIST = dhcpdb_create_1.0.mysql

+ 0 - 26
src/bin/admin/tests/radius_tests.sh.in

@@ -1,26 +0,0 @@
-#!/bin/sh
-
-# Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
-#
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-# Include common test library.
-. @abs_top_builddir@/src/lib/testutils/dhcp_test_lib.sh
-
-# Include admin utilities
-. @abs_top_srcdir@/src/bin/admin/admin-utils.sh
-
-# Set path to the production schema scripts
-db_scripts_dir=@abs_top_srcdir@/src/share/database/scripts
-
-db_user="keatest"
-db_password="keatest"
-db_name="keatest"
-
-# Set location of the kea-admin.
-keaadmin=@abs_top_builddir@/src/bin/admin/kea-admin
-
-# TODO: radius test. Be happy!
-assert_eq 0 1 "You need to write radius test. Be happy ! (expected status code %d, returned %d)"

+ 4 - 0
src/lib/dhcpsrv/tests/Makefile.am

@@ -123,6 +123,10 @@ endif
 if HAVE_CQL
 libdhcpsrv_unittests_SOURCES += cql_lease_mgr_unittest.cc
 endif
+if HAVE_RADCLI
+libdhcpsrv_unittests_SOURCES += radius_host_data_source_unittest.cc
+endif
+
 libdhcpsrv_unittests_SOURCES += pool_unittest.cc
 libdhcpsrv_unittests_SOURCES += shared_network_parser_unittest.cc
 libdhcpsrv_unittests_SOURCES += shared_network_unittest.cc

+ 71 - 52
src/lib/dhcpsrv/tests/generic_host_data_source_unittest.cc

@@ -545,7 +545,7 @@ GenericHostDataSourceTest::testReadOnlyDatabase(const char* valid_db_type) {
     // exception.
     HostPtr host2 = initializeHost6("2001:db8::2", Host::IDENT_DUID, false);
     ASSERT_TRUE(host2);
-    ASSERT_THROW(hdsptr_->add(host2), ReadOnlyDb);
+    ASSERT_THROW(add(host2), ReadOnlyDb);
     ASSERT_THROW(hdsptr_->commit(), ReadOnlyDb);
     ASSERT_THROW(hdsptr_->rollback(), ReadOnlyDb);
 
@@ -567,7 +567,7 @@ void GenericHostDataSourceTest::testBasic4(const Host::IdentifierType& id) {
     SubnetID subnet = host->getIPv4SubnetID();
 
     // Try to add it to the host data source.
-    ASSERT_NO_THROW(hdsptr_->add(host));
+    ASSERT_NO_THROW(add(host));
 
     // This should not return anything
     ConstHostPtr from_hds = hdsptr_->get4(subnet, IOAddress("10.10.10.10"));
@@ -581,6 +581,25 @@ void GenericHostDataSourceTest::testBasic4(const Host::IdentifierType& id) {
     compareHosts(host, from_hds);
 }
 
+void GenericHostDataSourceTest::add(const HostPtr& host) const {
+    hdsptr_->add(host);
+}
+
+bool GenericHostDataSourceTest::del(const SubnetID& subnet_id, const asiolink::IOAddress& addr) {
+    return hdsptr_->del(subnet_id, addr);
+}
+
+bool GenericHostDataSourceTest::del4(const SubnetID& subnet_id,
+                      const Host::IdentifierType& identifier_type,
+                      const uint8_t* identifier_begin, const size_t identifier_len) {
+    return hdsptr_->del4(subnet_id, identifier_type, identifier_begin, identifier_len);
+}
+
+bool GenericHostDataSourceTest::del6(const SubnetID& subnet_id,
+                      const Host::IdentifierType& identifier_type,
+                      const uint8_t* identifier_begin, const size_t identifier_len) {
+    return hdsptr_->del6(subnet_id, identifier_type, identifier_begin, identifier_len);
+}
 
 void GenericHostDataSourceTest::testGetByIPv4(const Host::IdentifierType& id) {
     // Make sure we have a pointer to the host data source.
@@ -593,10 +612,10 @@ void GenericHostDataSourceTest::testGetByIPv4(const Host::IdentifierType& id) {
     HostPtr host4 = initializeHost4("192.0.2.4", id);
 
     // ... and add them to the data source.
-    ASSERT_NO_THROW(hdsptr_->add(host1));
-    ASSERT_NO_THROW(hdsptr_->add(host2));
-    ASSERT_NO_THROW(hdsptr_->add(host3));
-    ASSERT_NO_THROW(hdsptr_->add(host4));
+    ASSERT_NO_THROW(add(host1));
+    ASSERT_NO_THROW(add(host2));
+    ASSERT_NO_THROW(add(host3));
+    ASSERT_NO_THROW(add(host4));
 
     SubnetID subnet1 = host1->getIPv4SubnetID();
     SubnetID subnet2 = host2->getIPv4SubnetID();
@@ -638,8 +657,8 @@ GenericHostDataSourceTest::testGet4ByIdentifier(const Host::IdentifierType& iden
     ASSERT_FALSE(host1->getIdentifier() == host2->getIdentifier());
 
     // Try to add both of them to the host data source.
-    ASSERT_NO_THROW(hdsptr_->add(host1));
-    ASSERT_NO_THROW(hdsptr_->add(host2));
+    ASSERT_NO_THROW(add(host1));
+    ASSERT_NO_THROW(add(host2));
 
     SubnetID subnet1 = host1->getIPv4SubnetID();
     SubnetID subnet2 = host2->getIPv4SubnetID();
@@ -671,7 +690,7 @@ void GenericHostDataSourceTest::testHWAddrNotClientId() {
     ASSERT_FALSE(host->getDuid());
 
     // Try to add it to the host data source.
-    ASSERT_NO_THROW(hdsptr_->add(host));
+    ASSERT_NO_THROW(add(host));
 
     SubnetID subnet = host->getIPv4SubnetID();
 
@@ -702,7 +721,7 @@ void GenericHostDataSourceTest::testClientIdNotHWAddr() {
     ASSERT_TRUE(host->getDuid());
 
     // Try to add it to the host data source.
-    ASSERT_NO_THROW(hdsptr_->add(host));
+    ASSERT_NO_THROW(add(host));
 
     SubnetID subnet = host->getIPv4SubnetID();
 
@@ -758,7 +777,7 @@ GenericHostDataSourceTest::testHostname(std::string name, int num) {
     for (vector<HostPtr>::const_iterator it = hosts.begin();
          it != hosts.end(); ++it) {
         // Try to add both of the to the host data source.
-        ASSERT_NO_THROW(hdsptr_->add(*it));
+        ASSERT_NO_THROW(add(*it));
     }
 
     // And finally retrieve them one by one and check
@@ -790,7 +809,7 @@ GenericHostDataSourceTest::testMultipleSubnets(int subnets,
         host->setIPv6SubnetID(i + 1000);
 
         // Check that the same host can have reservations in multiple subnets.
-        EXPECT_NO_THROW(hdsptr_->add(host));
+        EXPECT_NO_THROW(add(host));
     }
 
     // Now check that the reservations can be retrieved by IPv4 address from
@@ -853,8 +872,8 @@ void GenericHostDataSourceTest::testGet6ByHWAddr() {
     compareHwaddrs(host1, host2, false);
 
     // Try to add both of them to the host data source.
-    ASSERT_NO_THROW(hdsptr_->add(host1));
-    ASSERT_NO_THROW(hdsptr_->add(host2));
+    ASSERT_NO_THROW(add(host1));
+    ASSERT_NO_THROW(add(host2));
 
     SubnetID subnet1 = host1->getIPv6SubnetID();
     SubnetID subnet2 = host2->getIPv6SubnetID();
@@ -889,8 +908,8 @@ void GenericHostDataSourceTest::testGet6ByClientId() {
     compareDuids(host1, host2, false);
 
     // Try to add both of them to the host data source.
-    ASSERT_NO_THROW(hdsptr_->add(host1));
-    ASSERT_NO_THROW(hdsptr_->add(host2));
+    ASSERT_NO_THROW(add(host1));
+    ASSERT_NO_THROW(add(host2));
 
     SubnetID subnet1 = host1->getIPv6SubnetID();
     SubnetID subnet2 = host2->getIPv6SubnetID();
@@ -927,7 +946,7 @@ GenericHostDataSourceTest::testSubnetId6(int subnets, Host::IdentifierType id) {
         host->setIPv6SubnetID(i + 1000);
 
         // Check that the same host can have reservations in multiple subnets.
-        EXPECT_NO_THROW(hdsptr_->add(host));
+        EXPECT_NO_THROW(add(host));
 
         // Increase address to make sure we don't assign the same address
         // in different subnets.
@@ -971,10 +990,10 @@ void GenericHostDataSourceTest::testGetByIPv6(Host::IdentifierType id,
     HostPtr host4 = initializeHost6("2001:db8::4", id, prefix);
 
     // ... and add them to the data source.
-    ASSERT_NO_THROW(hdsptr_->add(host1));
-    ASSERT_NO_THROW(hdsptr_->add(host2));
-    ASSERT_NO_THROW(hdsptr_->add(host3));
-    ASSERT_NO_THROW(hdsptr_->add(host4));
+    ASSERT_NO_THROW(add(host1));
+    ASSERT_NO_THROW(add(host2));
+    ASSERT_NO_THROW(add(host3));
+    ASSERT_NO_THROW(add(host4));
 
     // Are we talking about addresses or prefixes?
     uint8_t len = prefix ? 64 : 128;
@@ -1013,10 +1032,10 @@ void GenericHostDataSourceTest::testGetBySubnetIPv6() {
     HostPtr host4 = initializeHost6("2001:db8:4::", Host::IDENT_DUID, true);
 
     // ... and add them to the data source.
-    ASSERT_NO_THROW(hdsptr_->add(host1));
-    ASSERT_NO_THROW(hdsptr_->add(host2));
-    ASSERT_NO_THROW(hdsptr_->add(host3));
-    ASSERT_NO_THROW(hdsptr_->add(host4));
+    ASSERT_NO_THROW(add(host1));
+    ASSERT_NO_THROW(add(host2));
+    ASSERT_NO_THROW(add(host3));
+    ASSERT_NO_THROW(add(host4));
 
     // And then try to retrieve them back.
     ConstHostPtr from_hds1 = hdsptr_->get6(host1->getIPv6SubnetID(),
@@ -1050,10 +1069,10 @@ void GenericHostDataSourceTest::testAddDuplicate6WithSameDUID() {
     HostPtr host = initializeHost6("2001:db8::1", Host::IDENT_DUID, true);
 
     // Add this reservation once.
-    ASSERT_NO_THROW(hdsptr_->add(host));
+    ASSERT_NO_THROW(add(host));
 
     // Then try to add it again, it should throw an exception.
-    ASSERT_THROW(hdsptr_->add(host), DuplicateEntry);
+    ASSERT_THROW(add(host), DuplicateEntry);
 }
 
 void GenericHostDataSourceTest::testAddDuplicate6WithSameHWAddr() {
@@ -1064,10 +1083,10 @@ void GenericHostDataSourceTest::testAddDuplicate6WithSameHWAddr() {
     HostPtr host = initializeHost6("2001:db8::1", Host::IDENT_HWADDR, true);
 
     // Add this reservation once.
-    ASSERT_NO_THROW(hdsptr_->add(host));
+    ASSERT_NO_THROW(add(host));
 
     // Then try to add it again, it should throw an exception.
-    ASSERT_THROW(hdsptr_->add(host), DuplicateEntry);
+    ASSERT_THROW(add(host), DuplicateEntry);
 }
 
 void GenericHostDataSourceTest::testAddDuplicate4() {
@@ -1078,21 +1097,21 @@ void GenericHostDataSourceTest::testAddDuplicate4() {
     HostPtr host = initializeHost4("192.0.2.1", Host::IDENT_DUID);
 
     // Add this reservation once.
-    ASSERT_NO_THROW(hdsptr_->add(host));
+    ASSERT_NO_THROW(add(host));
 
     // Then try to add it again, it should throw an exception.
-    ASSERT_THROW(hdsptr_->add(host), DuplicateEntry);
+    ASSERT_THROW(add(host), DuplicateEntry);
 
     // This time use a different host identifier and try again.
     // This update should be rejected because of duplicated
     // address.
     ASSERT_NO_THROW(host->setIdentifier("01:02:03:04:05:06", "hw-address"));
-    ASSERT_THROW(hdsptr_->add(host), DuplicateEntry);
+    ASSERT_THROW(add(host), DuplicateEntry);
 
     // Modify address to avoid its duplication and make sure
     // we can now add the host.
     ASSERT_NO_THROW(host->setIPv4Reservation(IOAddress("192.0.2.3")));
-    EXPECT_NO_THROW(hdsptr_->add(host));
+    EXPECT_NO_THROW(add(host));
 }
 
 void GenericHostDataSourceTest::testAddr6AndPrefix(){
@@ -1107,7 +1126,7 @@ void GenericHostDataSourceTest::testAddr6AndPrefix(){
     host->addReservation(resv);
 
     // Add this reservation
-    ASSERT_NO_THROW(hdsptr_->add(host));
+    ASSERT_NO_THROW(add(host));
 
     // Get this host by DUID
     ConstHostPtr from_hds = hdsptr_->get6(host->getIPv6SubnetID(),
@@ -1141,7 +1160,7 @@ void GenericHostDataSourceTest::testMultipleReservations(){
     host->addReservation(resv3);
     host->addReservation(resv4);
 
-    ASSERT_NO_THROW(hdsptr_->add(host));
+    ASSERT_NO_THROW(add(host));
 
 
     ConstHostPtr from_hds = hdsptr_->get6(IOAddress("2001:db8::1"), len);
@@ -1187,7 +1206,7 @@ void GenericHostDataSourceTest::testOptionsReservations4(const bool formatted) {
     // Add a bunch of DHCPv4 and DHCPv6 options for the host.
     ASSERT_NO_THROW(addTestOptions(host, formatted, DHCP4_ONLY));
     // Insert host and the options into respective tables.
-    ASSERT_NO_THROW(hdsptr_->add(host));
+    ASSERT_NO_THROW(add(host));
     // Subnet id will be used in queries to the database.
     SubnetID subnet_id = host->getIPv4SubnetID();
 
@@ -1213,7 +1232,7 @@ void GenericHostDataSourceTest::testOptionsReservations6(const bool formatted) {
     // Add a bunch of DHCPv4 and DHCPv6 options for the host.
     ASSERT_NO_THROW(addTestOptions(host, formatted, DHCP6_ONLY));
     // Insert host, options and IPv6 reservations into respective tables.
-    ASSERT_NO_THROW(hdsptr_->add(host));
+    ASSERT_NO_THROW(add(host));
     // Subnet id will be used in queries to the database.
     SubnetID subnet_id = host->getIPv6SubnetID();
 
@@ -1234,7 +1253,7 @@ void GenericHostDataSourceTest::testOptionsReservations46(const bool formatted)
     // Add a bunch of DHCPv4 and DHCPv6 options for the host.
     ASSERT_NO_THROW(addTestOptions(host, formatted, DHCP4_AND_DHCP6));
     // Insert host, options and IPv6 reservations into respective tables.
-    ASSERT_NO_THROW(hdsptr_->add(host));
+    ASSERT_NO_THROW(add(host));
 
     // getAll(identifier_type, identifier, identifier_size)
     ConstHostCollection hosts_by_id = hdsptr_->getAll(host->getIdentifierType(),
@@ -1259,7 +1278,7 @@ GenericHostDataSourceTest::testMultipleClientClasses4() {
     }
 
     // Add the host.
-    ASSERT_NO_THROW(hdsptr_->add(host));
+    ASSERT_NO_THROW(add(host));
 
     // Subnet id will be used in queries to the database.
     SubnetID subnet_id = host->getIPv4SubnetID();
@@ -1321,7 +1340,7 @@ GenericHostDataSourceTest::testMultipleClientClasses6() {
     }
 
     // Add the host.
-    ASSERT_NO_THROW(hdsptr_->add(host));
+    ASSERT_NO_THROW(add(host));
 
     // Subnet id will be used in queries to the database.
     SubnetID subnet_id = host->getIPv6SubnetID();
@@ -1387,7 +1406,7 @@ GenericHostDataSourceTest::testMultipleClientClassesBoth() {
     }
 
     // Add the host.
-    ASSERT_NO_THROW(hdsptr_->add(host));
+    ASSERT_NO_THROW(add(host));
 
     // Subnet id will be used in queries to the database.
     SubnetID subnet_id = host->getIPv6SubnetID();
@@ -1416,7 +1435,7 @@ GenericHostDataSourceTest::testMessageFields4() {
     });
 
     // Add the host.
-    ASSERT_NO_THROW(hdsptr_->add(host));
+    ASSERT_NO_THROW(add(host));
 
     // Subnet id will be used in queries to the database.
     SubnetID subnet_id = host->getIPv4SubnetID();
@@ -1472,13 +1491,13 @@ void GenericHostDataSourceTest::testDeleteByAddr4() {
     SubnetID subnet1 = host1->getIPv4SubnetID();
 
     // ... and add it to the data source.
-    ASSERT_NO_THROW(hdsptr_->add(host1));
+    ASSERT_NO_THROW(add(host1));
 
     // And then try to retrieve it back.
     ConstHostPtr before = hdsptr_->get4(subnet1, IOAddress("192.0.2.1"));
 
     // Now try to delete it: del(subnet-id, addr4)
-    EXPECT_TRUE(hdsptr_->del(subnet1, IOAddress("192.0.2.1")));
+    EXPECT_TRUE(del(subnet1, IOAddress("192.0.2.1")));
 
     // Check if it's still there.
     ConstHostPtr after = hdsptr_->get4(subnet1, IOAddress("192.0.2.1"));
@@ -1499,7 +1518,7 @@ void GenericHostDataSourceTest::testDeleteById4() {
     SubnetID subnet1 = host1->getIPv4SubnetID();
 
     // ... and add it to the data source.
-    ASSERT_NO_THROW(hdsptr_->add(host1));
+    ASSERT_NO_THROW(add(host1));
 
     // And then try to retrieve it back.
     ConstHostPtr before = hdsptr_->get4(subnet1,
@@ -1508,7 +1527,7 @@ void GenericHostDataSourceTest::testDeleteById4() {
                                         host1->getIdentifier().size());
 
     // Now try to delete it: del4(subnet4-id, identifier-type, identifier)
-    EXPECT_TRUE(hdsptr_->del4(subnet1, host1->getIdentifierType(),
+    EXPECT_TRUE(del4(subnet1, host1->getIdentifierType(),
                               &host1->getIdentifier()[0],
                               host1->getIdentifier().size()));
 
@@ -1540,7 +1559,7 @@ void GenericHostDataSourceTest::testDeleteById4Options() {
     SubnetID subnet1 = host1->getIPv4SubnetID();
 
     // ... and add it to the data source.
-    ASSERT_NO_THROW(hdsptr_->add(host1));
+    ASSERT_NO_THROW(add(host1));
 
     // There must be some options
     EXPECT_NE(0, countDBOptions4());
@@ -1552,7 +1571,7 @@ void GenericHostDataSourceTest::testDeleteById4Options() {
                                         host1->getIdentifier().size());
 
     // Now try to delete it: del4(subnet4-id, identifier-type, identifier)
-    EXPECT_TRUE(hdsptr_->del4(subnet1, host1->getIdentifierType(),
+    EXPECT_TRUE(del4(subnet1, host1->getIdentifierType(),
                               &host1->getIdentifier()[0],
                               host1->getIdentifier().size()));
 
@@ -1581,7 +1600,7 @@ void GenericHostDataSourceTest::testDeleteById6() {
     SubnetID subnet1 = host1->getIPv6SubnetID();
 
     // ... and add it to the data source.
-    ASSERT_NO_THROW(hdsptr_->add(host1));
+    ASSERT_NO_THROW(add(host1));
 
     // And then try to retrieve it back.
     ConstHostPtr before = hdsptr_->get6(subnet1,
@@ -1590,7 +1609,7 @@ void GenericHostDataSourceTest::testDeleteById6() {
                                         host1->getIdentifier().size());
 
     // Now try to delete it: del4(subnet4-id, identifier-type, identifier)
-    EXPECT_TRUE(hdsptr_->del6(subnet1, host1->getIdentifierType(),
+    EXPECT_TRUE(del6(subnet1, host1->getIdentifierType(),
                               &host1->getIdentifier()[0],
                               host1->getIdentifier().size()));
 
@@ -1617,7 +1636,7 @@ void GenericHostDataSourceTest::testDeleteById6Options() {
     ASSERT_NO_THROW(addTestOptions(host1, true, DHCP6_ONLY));
 
     // ... and add it to the data source.
-    ASSERT_NO_THROW(hdsptr_->add(host1));
+    ASSERT_NO_THROW(add(host1));
 
     // Check that the options are stored...
     EXPECT_NE(0, countDBOptions6());
@@ -1632,7 +1651,7 @@ void GenericHostDataSourceTest::testDeleteById6Options() {
                                         host1->getIdentifier().size());
 
     // Now try to delete it: del4(subnet4-id, identifier-type, identifier)
-    EXPECT_TRUE(hdsptr_->del6(subnet1, host1->getIdentifierType(),
+    EXPECT_TRUE(del6(subnet1, host1->getIdentifierType(),
                               &host1->getIdentifier()[0],
                               host1->getIdentifier().size()));
 

+ 14 - 5
src/lib/dhcpsrv/tests/generic_host_data_source_unittest.h

@@ -57,8 +57,8 @@ public:
     /// @param id Identifier type.
     ///
     /// @return generated Host object
-    HostPtr initializeHost4(const std::string& address,
-                            const Host::IdentifierType& id);
+    virtual HostPtr initializeHost4(const std::string& address,
+                                    const Host::IdentifierType& id);
 
     /// @brief Creates a host reservation for specified IPv6 address.
     ///
@@ -69,8 +69,8 @@ public:
     /// identifier should be generated or the same as previously.
     ///
     /// @return generated Host object
-    HostPtr initializeHost6(std::string address, Host::IdentifierType id,
-                            bool prefix, bool new_identifier = true);
+    virtual HostPtr initializeHost6(std::string address, Host::IdentifierType id,
+                                    bool prefix, bool new_identifier = true);
 
     /// @brief Generates a hardware address in text version.
     ///
@@ -120,7 +120,7 @@ public:
     ///
     /// @param host1 first host to compare
     /// @param host2 second host to compare
-    void compareHosts(const ConstHostPtr& host1, const ConstHostPtr& host2);
+    virtual void compareHosts(const ConstHostPtr& host1, const ConstHostPtr& host2);
 
     /// @brief Compares two IPv6 reservation lists.
     ///
@@ -367,6 +367,15 @@ public:
     void addTestOptions(const HostPtr& host, const bool formatted,
                         const AddedOptions& added_options) const;
 
+    virtual void add(const HostPtr& host) const;
+    virtual bool del(const SubnetID& subnet_id, const asiolink::IOAddress& addr);
+    virtual bool del4(const SubnetID& subnet_id,
+                      const Host::IdentifierType& identifier_type,
+                      const uint8_t* identifier_begin, const size_t identifier_len);
+    virtual bool del6(const SubnetID& subnet_id,
+                      const Host::IdentifierType& identifier_type,
+                      const uint8_t* identifier_begin, const size_t identifier_len);
+
     /// @brief Pointer to the host data source
     HostDataSourcePtr hdsptr_;
 

+ 445 - 0
src/lib/dhcpsrv/tests/radius_host_data_source_unittest.cc

@@ -0,0 +1,445 @@
+// Copyright (C) 2015-2017 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <asiolink/io_address.h>
+#include <dhcpsrv/tests/test_utils.h>
+#include <exceptions/exceptions.h>
+#include <dhcpsrv/host.h>
+#include <dhcpsrv/radius_host_data_source.h>
+#include <dhcpsrv/tests/generic_host_data_source_unittest.h>
+#include <dhcpsrv/testutils/radius_schema.h>
+#include <dhcpsrv/host_data_source_factory.h>
+
+#include <gtest/gtest.h>
+
+#include <algorithm>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <utility>
+
+using namespace isc;
+using namespace isc::asiolink;
+using namespace isc::dhcp;
+using namespace isc::dhcp::test;
+using namespace std;
+
+namespace {
+
+class RadiusHostDataSourceTest : public GenericHostDataSourceTest {
+public:
+    /// @brief Constructor
+    ///
+    /// Deletes everything from the database and opens it.
+    RadiusHostDataSourceTest() {
+
+        destroyRadiusSchema();
+        createRadiusSchema();
+
+        // Connect to the database
+        try {
+            HostDataSourceFactory::create(validRadiusConnectionString());
+        } catch (...) {
+            std::cerr << "*** ERROR: unable to open database. The test\n"
+                         "*** environment is broken and must be fixed before\n"
+                         "*** the radius tests will run correctly.\n"
+                         "*** The reason for the problem is described in the\n"
+                         "*** accompanying exception output.\n";
+            throw;
+        }
+
+        hdsptr_ = HostDataSourceFactory::getHostDataSourcePtr();
+    }
+
+    /// @brief Destructor
+    ///
+    /// Rolls back all pending transactions.  The deletion of myhdsptr_ will close
+    /// the database.  Then reopen it and delete everything created by the test.
+    virtual ~RadiusHostDataSourceTest() {
+        try {
+            hdsptr_->rollback();
+        } catch (...) {
+            // Rollback may fail if backend is in read only mode. That's ok.
+        }
+        HostDataSourceFactory::destroy();
+        hdsptr_.reset();
+        destroyRadiusSchema();
+    }
+
+    /// @brief Reopen the database
+    ///
+    /// Closes the database and re-open it.  Anything committed should be
+    /// visible.
+    ///
+    /// Parameter is ignored for Radius backend as the v4 and v6 leases share
+    /// the same database.
+    void reopen(Universe) {
+        HostDataSourceFactory::destroy();
+        HostDataSourceFactory::create(validRadiusConnectionString());
+        hdsptr_ = HostDataSourceFactory::getHostDataSourcePtr();
+    }
+
+    /// fake adding host
+    void add(const HostPtr& host) const {
+        freeradiusAdd(host);
+    }
+
+    bool del(const SubnetID& subnet_id, const asiolink::IOAddress& addr) {
+        return freeradiusDel(subnet_id, addr);
+    }
+
+    bool del4(const SubnetID& subnet_id,
+                      const Host::IdentifierType& identifier_type,
+                      const uint8_t* identifier_begin, const size_t identifier_len) {
+        return freeradiusDel4(subnet_id, identifier_type, identifier_begin, identifier_len);
+    }
+
+    bool del6(const SubnetID& subnet_id,
+                      const Host::IdentifierType& identifier_type,
+                      const uint8_t* identifier_begin, const size_t identifier_len) {
+        return freeradiusDel6(subnet_id, identifier_type, identifier_begin, identifier_len);
+    }
+
+
+    HostPtr initializeHost4(const std::string& address, const Host::IdentifierType& id) {
+        std::vector<uint8_t> ident;
+        if (id == Host::IDENT_HWADDR) {
+            ident = generateHWAddr();
+
+        } else {
+            ident = generateIdentifier();
+        }
+
+        // SubnetID are ignored with radius backend
+        static SubnetID subnet4 = 0;
+        static SubnetID subnet6 = 0;
+
+        IOAddress addr(address);
+        HostPtr host(new Host(&ident[0], ident.size(), id, subnet4, subnet6, addr));
+
+        return (host);
+    }
+
+    HostPtr initializeHost6(std::string address,
+                            Host::IdentifierType identifier,
+                            bool prefix,
+                            bool new_identifier) {
+        std::vector<uint8_t> ident;
+        switch (identifier) {
+        case Host::IDENT_HWADDR:
+            ident = generateHWAddr(new_identifier);
+            break;
+        case Host::IDENT_DUID:
+            ident = generateIdentifier(new_identifier);
+            break;
+        default:
+            ADD_FAILURE() << "Unknown IdType: " << identifier;
+            return HostPtr();
+        }
+
+        // SubnetID are ignored with radius backend
+        static SubnetID subnet4 = 0;
+        static SubnetID subnet6 = 0;
+
+        HostPtr host(new Host(&ident[0], ident.size(), identifier, subnet4,
+                              subnet6, IOAddress("0.0.0.0")));
+
+        if (!prefix) {
+            // Create IPv6 reservation (for an address)
+            IPv6Resrv resv(IPv6Resrv::TYPE_NA, IOAddress(address), 128);
+            host->addReservation(resv);
+        } else {
+            // Create IPv6 reservation for a /64 prefix
+            IPv6Resrv resv(IPv6Resrv::TYPE_PD, IOAddress(address), 64);
+            host->addReservation(resv);
+        }
+        return (host);
+    }
+
+
+
+
+    void compareHosts(const ConstHostPtr& host1, const ConstHostPtr& host2) {
+
+        // Let's compare HW addresses and expect match.
+        compareHwaddrs(host1, host2, true);
+
+        // Now compare DUIDs
+        compareDuids(host1, host2, true);
+
+        // Now check that the identifiers returned as vectors are the same
+        EXPECT_EQ(host1->getIdentifierType(), host2->getIdentifierType());
+        EXPECT_TRUE(host1->getIdentifier() == host2->getIdentifier());
+
+        // Check host parameters
+        //EXPECT_EQ(host1->getIPv4SubnetID(), host2->getIPv4SubnetID());
+        //EXPECT_EQ(host1->getIPv6SubnetID(), host2->getIPv6SubnetID());
+        EXPECT_EQ(host1->getIPv4Reservation(), host2->getIPv4Reservation());
+        EXPECT_EQ(host1->getHostname(), host2->getHostname());
+        EXPECT_EQ(host1->getNextServer(), host2->getNextServer());
+        EXPECT_EQ(host1->getServerHostname(), host2->getServerHostname());
+        EXPECT_EQ(host1->getBootFileName(), host2->getBootFileName());
+
+        // Compare IPv6 reservations
+        compareReservations6(host1->getIPv6Reservations(),
+                             host2->getIPv6Reservations());
+
+        // Compare client classification details
+        compareClientClasses(host1->getClientClasses4(),
+                             host2->getClientClasses4());
+
+        compareClientClasses(host1->getClientClasses6(),
+                             host2->getClientClasses6());
+
+        // Compare DHCPv4 and DHCPv6 options.
+        compareOptions(host1->getCfgOption4(), host2->getCfgOption4());
+        compareOptions(host1->getCfgOption6(), host2->getCfgOption6());
+    }
+
+
+
+
+};
+
+/// @brief Check that database can be opened
+///
+/// This test checks if the RadiusHostDataSource can be instantiated.  This happens
+/// only if the database can be opened.  Note that this is not part of the
+/// RadiusLeaseMgr test fixure set.  This test checks that the database can be
+/// opened: the fixtures assume that and check basic operations.
+
+TEST(RadiusHostDataSource, OpenDatabase) {
+
+    // Schema needs to be created for the test to work.
+    destroyRadiusSchema();
+    createRadiusSchema();
+
+    // Check that lease manager open the database opens correctly and tidy up.
+    //  If it fails, print the error message.
+    try {
+        HostDataSourceFactory::create(validRadiusConnectionString());
+        EXPECT_NO_THROW((void) HostDataSourceFactory::getHostDataSourcePtr());
+        HostDataSourceFactory::destroy();
+    } catch (const isc::Exception& ex) {
+        FAIL() << "*** ERROR: unable to open database, reason:\n"
+               << "    " << ex.what() << "\n"
+               << "*** The test environment is broken and must be fixed\n"
+               << "*** before the Radius tests will run correctly.\n";
+    }
+
+    // Check that lease manager open the database opens correctly with a longer
+    // timeout.  If it fails, print the error message.
+    try {
+        string connection_string = validRadiusConnectionString() + string(" ") +
+                                   string(VALID_TIMEOUT);
+        HostDataSourceFactory::create(connection_string);
+        EXPECT_NO_THROW((void) HostDataSourceFactory::getHostDataSourcePtr());
+        HostDataSourceFactory::destroy();
+    } catch (const isc::Exception& ex) {
+        FAIL() << "*** ERROR: unable to open database, reason:\n"
+               << "    " << ex.what() << "\n"
+               << "*** The test environment is broken and must be fixed\n"
+               << "*** before the Radius tests will run correctly.\n";
+    }
+
+    // Check that attempting to get an instance of the lease manager when
+    // none is set throws an exception.
+    EXPECT_FALSE(HostDataSourceFactory::getHostDataSourcePtr());
+
+    // Check that wrong specification of backend throws an exception.
+    // (This is really a check on LeaseMgrFactory, but is convenient to
+    // perform here.)
+    EXPECT_THROW(HostDataSourceFactory::create(connectionString(
+        NULL, VALID_NAME, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
+        InvalidParameter);
+    EXPECT_THROW(HostDataSourceFactory::create(connectionString(
+        INVALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD)),
+        InvalidType);
+
+    // Check that invalid login data causes an exception.
+    /* Not relevant for freeradius
+    EXPECT_THROW(HostDataSourceFactory::create(connectionString(
+        RADIUS_VALID_TYPE, INVALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD)),
+        DbOpenError);
+    EXPECT_THROW(HostDataSourceFactory::create(connectionString(
+        RADIUS_VALID_TYPE, VALID_NAME, INVALID_HOST, VALID_USER, VALID_PASSWORD)),
+        DbOpenError);
+    EXPECT_THROW(HostDataSourceFactory::create(connectionString(
+        RADIUS_VALID_TYPE, VALID_NAME, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
+        DbOpenError);
+    EXPECT_THROW(HostDataSourceFactory::create(connectionString(
+        RADIUS_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, INVALID_PASSWORD)),
+        DbOpenError);
+    EXPECT_THROW(HostDataSourceFactory::create(connectionString(
+        RADIUS_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD, INVALID_TIMEOUT_1)),
+        DbInvalidTimeout);
+    EXPECT_THROW(HostDataSourceFactory::create(connectionString(
+        RADIUS_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD, INVALID_TIMEOUT_2)),
+        DbInvalidTimeout);
+    EXPECT_THROW(HostDataSourceFactory::create(connectionString(
+        RADIUS_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD,
+        VALID_TIMEOUT, INVALID_READONLY_DB)), DbInvalidReadOnly);
+    // Check for missing parameters
+    EXPECT_THROW(HostDataSourceFactory::create(connectionString(
+        RADIUS_VALID_TYPE, NULL, VALID_HOST, INVALID_USER, VALID_PASSWORD)),
+        NoDatabaseName);
+    */
+
+    // Tidy up after the test
+    destroyRadiusSchema();
+}
+
+// Test verifies if a host reservation can be added and later retrieved by IPv4
+// address. Host uses hw address as identifier.
+/*
+TEST_F(RadiusHostDataSourceTest, basic4HWAddr) {
+    testBasic4(Host::IDENT_HWADDR);
+}
+
+// Test verifies if a host reservation can be added and later retrieved by IPv4
+// address. Host uses client-id (DUID) as identifier.
+TEST_F(RadiusHostDataSourceTest, basic4ClientId) {
+    testBasic4(Host::IDENT_DUID);
+}
+// Test verifies that multiple hosts can be added and later retrieved by their
+// reserved IPv4 address. This test uses HW addresses as identifiers.
+TEST_F(RadiusHostDataSourceTest, getByIPv4HWaddr) {
+    testGetByIPv4(Host::IDENT_HWADDR);
+}
+
+// Test verifies that multiple hosts can be added and later retrieved by their
+// reserved IPv4 address. This test uses client-id (DUID) as identifiers.
+TEST_F(RadiusHostDataSourceTest, getByIPv4ClientId) {
+    testGetByIPv4(Host::IDENT_DUID);
+}
+*/
+
+// Test verifies if a host reservation can be added and later retrieved by
+// hardware address.
+TEST_F(RadiusHostDataSourceTest, get4ByHWaddr) {
+    testGet4ByIdentifier(Host::IDENT_HWADDR);
+}
+
+// Test verifies if a host reservation can be added and later retrieved by
+// DUID.
+TEST_F(RadiusHostDataSourceTest, get4ByDUID) {
+    testGet4ByIdentifier(Host::IDENT_DUID);
+}
+
+// Test verifies if a host reservation can be added and later retrieved by
+// circuit id.
+TEST_F(RadiusHostDataSourceTest, get4ByCircuitId) {
+    testGet4ByIdentifier(Host::IDENT_CIRCUIT_ID);
+}
+
+// Test verifies if a host reservation can be added and later retrieved by
+// client-id.
+TEST_F(RadiusHostDataSourceTest, get4ByClientId) {
+    testGet4ByIdentifier(Host::IDENT_CLIENT_ID);
+}
+
+// Test verifies if hardware address and client identifier are not confused.
+// XXX: Is it relevant for freeradius backend ?
+// TEST_F(RadiusHostDataSourceTest, hwaddrNotClientId1) {
+//    testHWAddrNotClientId();
+//}
+
+// Test verifies if hardware address and client identifier are not confused.
+// XXX: Is it relevant for freeradius backend ?
+// TEST_F(RadiusHostDataSourceTest, hwaddrNotClientId2) {
+//     testClientIdNotHWAddr();
+// }
+
+// Test verifies if a host with FQDN hostname can be stored and later retrieved.
+// XXX: Is it relevant for freeradius backend ?
+// TEST_F(RadiusHostDataSourceTest, hostnameFQDN) {
+//     testHostname("foo.example.org", 1);
+// }
+
+// Test verifies if 100 hosts with unique FQDN hostnames can be stored and later
+// retrieved.
+// XXX: Is it relevant for freeradius backend ?
+// TEST_F(RadiusHostDataSourceTest, hostnameFQDN100) {
+//    testHostname("foo.example.org", 100);
+// }
+
+// Test verifies if a host without any hostname specified can be stored and later
+// retrieved.
+// TEST_F(RadiusHostDataSourceTest, noHostname) {
+//     testHostname("", 1);
+// }
+
+// // Test verifies if the hardware or client-id query can match hardware address.
+// TEST_F(RadiusHostDataSourceTest, DISABLED_hwaddrOrClientId1) {
+//     /// @todo: The logic behind ::get4(subnet_id, hwaddr, duid) call needs to
+//     /// be discussed.
+//     ///
+//     /// @todo: Add host reservation with hardware address X, try to retrieve
+//     /// host for hardware address X or client identifier Y, verify that the
+//     /// reservation is returned.
+// }
+//
+// // Test verifies if the hardware or client-id query can match client-id.
+// TEST_F(RadiusHostDataSourceTest, DISABLED_hwaddrOrClientId2) {
+//     /// @todo: The logic behind ::get4(subnet_id, hwaddr, duid) call needs to
+//     /// be discussed.
+//     ///
+//     /// @todo: Add host reservation with client identifier Y, try to retrieve
+//     /// host for hardware address X or client identifier Y, verify that the
+//     /// reservation is returned.
+// }
+
+// Test verifies that host with IPv6 address and DUID can be added and
+// later retrieved by IPv6 address.
+// TEST_F(RadiusHostDataSourceTest, get6AddrWithDuid) {
+//     testGetByIPv6(Host::IDENT_DUID, false);
+// }
+
+// Test verifies that host with IPv6 address and HWAddr can be added and
+// later retrieved by IPv6 address.
+// TEST_F(RadiusHostDataSourceTest, get6AddrWithHWAddr) {
+//     testGetByIPv6(Host::IDENT_HWADDR, false);
+// }
+
+// Test verifies that host with IPv6 prefix and DUID can be added and
+// later retrieved by IPv6 prefix.
+// TEST_F(RadiusHostDataSourceTest, get6PrefixWithDuid) {
+//     testGetByIPv6(Host::IDENT_DUID, true);
+// }
+
+// Test verifies that host with IPv6 prefix and HWAddr can be added and
+// later retrieved by IPv6 prefix.
+// TEST_F(RadiusHostDataSourceTest, get6PrefixWithHWaddr) {
+//     testGetByIPv6(Host::IDENT_HWADDR, true);
+// }
+
+// Test verifies that host with IPv6 prefix reservation can be retrieved
+// by subnet id and prefix value.
+// TEST_F(RadiusHostDataSourceTest, get6SubnetPrefix) {
+//     testGetBySubnetIPv6();
+// }
+
+// Test verifies if a host reservation can be added and later retrieved by
+// hardware address.
+TEST_F(RadiusHostDataSourceTest, get6ByHWaddr) {
+    testGet6ByHWAddr();
+}
+
+// Test verifies if a host reservation can be added and later retrieved by
+// client identifier.
+TEST_F(RadiusHostDataSourceTest, get6ByClientId) {
+    testGet6ByClientId();
+}
+
+// Test verifies if a host reservation can be stored with both IPv6 address and
+// prefix.
+TEST_F(RadiusHostDataSourceTest, addr6AndPrefix) {
+    testAddr6AndPrefix();
+}
+
+}; // Of anonymous namespace

+ 3 - 0
src/lib/dhcpsrv/testutils/Makefile.am

@@ -26,6 +26,9 @@ endif
 if HAVE_CQL
 libdhcpsrvtest_la_SOURCES += cql_schema.cc cql_schema.h
 endif
+if HAVE_RADCLI
+libdhcpsrvtest_la_SOURCES += radius_schema.cc radius_schema.h
+endif
 
 libdhcpsrvtest_la_CXXFLAGS = $(AM_CXXFLAGS)
 libdhcpsrvtest_la_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)

+ 134 - 0
src/lib/dhcpsrv/testutils/radius_schema.cc

@@ -0,0 +1,134 @@
+// Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+#include <string>
+#include <dhcpsrv/testutils/radius_schema.h>
+#include <gtest/gtest.h>
+
+#include <fstream>
+#include <sstream>
+#include <stdlib.h>
+
+using namespace std;
+
+namespace isc {
+namespace dhcp {
+namespace test {
+
+const char* RADIUS_AUTHORIZE_FILE = "/tmp/freeradius-authorize";
+const char* RADIUS_VALID_TYPE = "type=radius";
+const char* VALID_RADIUS_REALM = "name=kea.isc.org";
+const char* RADIUS_REALM = "kea.isc.org";
+
+string
+validRadiusConnectionString() {
+    return (connectionString(RADIUS_VALID_TYPE, VALID_RADIUS_REALM, VALID_HOST,
+                             VALID_USER, VALID_PASSWORD));
+}
+
+void freeradiusReload() {
+    std::string line;
+    ifstream myfile(RADIUS_AUTHORIZE_FILE);
+    while(std::getline(myfile, line)) {
+        std::cerr << line << "\n";
+    }
+    std::ostringstream cmd;
+    cmd << "sudo service freeradius stop && sudo service freeradius start";
+    int retval = ::system(cmd.str().c_str());
+
+    ASSERT_EQ(0, retval) << "failed:" << cmd.str();
+    myfile.close();
+}
+
+void destroyRadiusSchema(bool show_err) {
+}
+
+void createRadiusSchema(bool show_err) {
+    std::ostringstream cmd;
+    cmd << "sudo sh -c 'echo >" << RADIUS_AUTHORIZE_FILE << "'";
+    int retval = ::system(cmd.str().c_str());
+    ASSERT_EQ(0, retval) << "failed:" << cmd.str();
+
+    freeradiusReload();
+}
+
+void freeradiusAdd(const HostPtr& host) {
+    ofstream myfile;
+    myfile.open(RADIUS_AUTHORIZE_FILE, std::ios_base::app);
+    myfile << "# " << host->getIdentifierAsText() << "\n";
+
+    if( host->getHWAddress()) {
+        myfile << host->getHWAddress()->toText(false) ;
+        if( RADIUS_REALM ) {
+            myfile << "@" << RADIUS_REALM;
+        }
+    } else if( host->getDuid()) {
+        myfile << host->getDuid()->toText() ;
+        if( RADIUS_REALM ) {
+            myfile << "@" << RADIUS_REALM;
+        }
+    } else {
+        std::stringstream tmp;
+        tmp << std::hex;
+        bool delim = false;
+        for (std::vector<uint8_t>::const_iterator it = host->getIdentifier().begin();
+             it != host->getIdentifier().end(); ++it) {
+            if (delim) {
+                tmp << ":";
+            }
+            tmp << std::setw(2) << std::setfill('0') << static_cast<unsigned int>(*it);
+            delim = true;
+        }
+        myfile << tmp.str();
+        if( RADIUS_REALM ) {
+            myfile << "@" << RADIUS_REALM;
+        }
+    }
+
+    myfile << " Auth-Type := Accept\n";
+    myfile << "        Service-Type = Framed-User";
+
+    if(! host->getIPv4Reservation().isV4Zero()) {
+        myfile << ",\n        Framed-IP-Address = " << host->getIPv4Reservation();
+    }
+
+    IPv6ResrvRange resrv = host->getIPv6Reservations();
+    if (std::distance(resrv.first, resrv.second) > 0) {
+        int na = 0;
+        int pd = 0;
+        for (IPv6ResrvIterator resv = resrv.first; resv != resrv.second;
+             ++resv) {
+
+            if(resv->first == IPv6Resrv::TYPE_NA) {
+                myfile << ",\n        Framed-IPv6-Address:" << na++ << " = " << resv->second.getPrefix();
+            } else {
+                myfile << ",\n        Delegated-IPv6-Prefix:" << pd++ << " = " << resv->second.toText();
+            }
+        }
+    }
+    myfile << "\n";
+    myfile.close();
+    freeradiusReload();
+}
+
+bool freeradiusDel(const SubnetID& subnet_id, const asiolink::IOAddress& addr) {
+}
+
+bool freeradiusDel4(const SubnetID& subnet_id,
+                  const Host::IdentifierType& identifier_type,
+                  const uint8_t* identifier_begin, const size_t identifier_len) {
+}
+
+bool freeradiusDel6(const SubnetID& subnet_id,
+                  const Host::IdentifierType& identifier_type,
+                  const uint8_t* identifier_begin, const size_t identifier_len) {
+}
+
+
+};
+};
+};

+ 69 - 0
src/lib/dhcpsrv/testutils/radius_schema.h

@@ -0,0 +1,69 @@
+// Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef TEST_RADIUS_SCHEMA_H
+#define TEST_RADIUS_SCHEMA_H
+
+#include <config.h>
+#include <dhcpsrv/host.h>
+#include <dhcpsrv/testutils/schema.h>
+#include <string>
+
+namespace isc {
+namespace dhcp {
+namespace test {
+
+extern const char* RADIUS_VALID_TYPE;
+
+/// Return valid connection string
+///
+/// @return valid Radius connection string.
+std::string validRadiusConnectionString();
+
+/// @brief Clear everything from the database
+///
+/// Submits the current schema drop script:
+///
+///  <TEST_ADMIN_SCRIPTS_DIR>/mysql/dhcpdb_drop.mysql
+///
+/// to the unit test Radius database. If the script fails, the invoking test
+/// will fail. The output of stderr is suppressed unless the parameter,
+/// show_err is true.
+///
+/// @param show_err flag which governs whether or not stderr is suppressed.
+void destroyRadiusSchema(bool show_err = false);
+
+/// @brief Create the Radius Schema
+///
+/// Submits the current schema creation script:
+///
+///  <TEST_ADMIN_SCRIPTS_DIR>/mysql/dhcpdb_create.mysql
+///
+/// to the unit test Radius database. If the script fails, the invoking test
+/// will fail. The output of stderr is suppressed unless the parameter,
+/// show_err is true.
+///
+/// @param show_err flag which governs whether or not stderr is suppressed.
+void createRadiusSchema(bool show_err = false);
+
+void freeradiusAdd(const HostPtr& host);
+
+bool freeradiusDel(const SubnetID& subnet_id, const asiolink::IOAddress& addr);
+
+bool freeradiusDel4(const SubnetID& subnet_id,
+          const Host::IdentifierType& identifier_type,
+          const uint8_t* identifier_begin, const size_t identifier_len);
+
+bool freeradiusDel6(const SubnetID& subnet_id,
+                  const Host::IdentifierType& identifier_type,
+                  const uint8_t* identifier_begin, const size_t identifier_len);
+
+
+};
+};
+};
+
+#endif