diff options
Diffstat (limited to 'src/lib/dhcp/tests/iface_mgr_test_config.h')
-rw-r--r-- | src/lib/dhcp/tests/iface_mgr_test_config.h | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/src/lib/dhcp/tests/iface_mgr_test_config.h b/src/lib/dhcp/tests/iface_mgr_test_config.h new file mode 100644 index 0000000..26167e8 --- /dev/null +++ b/src/lib/dhcp/tests/iface_mgr_test_config.h @@ -0,0 +1,274 @@ +// Copyright (C) 2014-2020 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 IFACE_MGR_TEST_CONFIG_H +#define IFACE_MGR_TEST_CONFIG_H + +#include <asiolink/io_address.h> +#include <dhcp/iface_mgr.h> +#include <boost/noncopyable.hpp> + +namespace isc { +namespace dhcp { +namespace test { + +//@{ +/// @brief Index of the lo fake interface. +const uint32_t LO_INDEX = 0; + +/// @brief Index of the eth0 fake interface. +const uint32_t ETH0_INDEX = 1; + +/// @brief Index of the eth1 fake interface. +const uint32_t ETH1_INDEX = 2; + +/// @brief Index of the eth1961 fake interface. +const uint32_t ETH1961_INDEX = 1962; +//@} + +/// +/// @name Set of structures describing interface flags. +/// +/// These flags encapsulate the boolean type to pass the flags values +/// to @c IfaceMgrTestConfig methods. If the values passed to these methods +/// were not encapsulated by the types defined here, the API would become +/// prone to errors like swapping parameters being passed to specific functions. +/// For example, in the call to @c IfaceMgrTestConfig::setIfaceFlags: +/// @code +/// IfaceMgrTestConfig test_config(true); +/// test_config.setIfaceFlags("eth1", false, false, true, false, false); +/// @endcode +/// +/// it is quite likely that the developer by mistake swaps the values and +/// assigns them to wrong flags. When the flags are encapsulated with dedicated +/// structs, the compiler will return an error if values are swapped. For +/// example: +/// @code +/// IfaceMgrTestConfig test_config(true); +/// test_config.setIfaceFlags("eth1", FlagLoopback(false), FlagUp(false), +/// FlagRunning(true), FlagInactive4(false), +/// FlagInactive6(false)); +/// @endcode +/// will succeed, but the following code will result in the compilation error +/// and thus protect a developer from making an error: +/// @code +/// IfaceMgrTestConfig test_config(true); +/// test_config.setIfaceFlags("eth1", FlagLoopback(false), +/// FlagRunning(true), FlagUp(false), +/// FlagInactive4(false), FlagInactive6(false)); +/// @endcode +/// +//@{ +/// @brief Structure describing the loopback interface flag. +struct FlagLoopback { + explicit FlagLoopback(bool flag) : flag_(flag) { } + bool flag_; +}; + +/// @brief Structure describing the up interface flag. +struct FlagUp { + explicit FlagUp(bool flag) : flag_(flag) { } + bool flag_; +}; + +/// @brief Structure describing the running interface flag. +struct FlagRunning { + explicit FlagRunning(bool flag) : flag_(flag) { } + bool flag_; +}; + +/// @brief Structure describing the inactive4 interface flag. +struct FlagInactive4 { + explicit FlagInactive4(bool flag) : flag_(flag) { } + bool flag_; +}; + +/// @brief Structure describing the inactive6 interface flag. +struct FlagInactive6 { + explicit FlagInactive6(bool flag) : flag_(flag) { } + bool flag_; +}; +//@} + +/// @brief Convenience class for configuring @c IfaceMgr for unit testing. +/// +/// This class is used by various unit tests which test the code relaying +/// on IfaceMgr. The use of this class is not limited to libdhcp++ validation. +/// There are other libraries and applications (e.g. DHCP servers) which +/// depend on @c IfaceMgr. +/// +/// During the normal operation, the @c IfaceMgr detects interfaces present +/// on the machine where it is running. It also provides the means for +/// applications to open sockets on these interfaces and perform other +/// IO operations. This however creates dependency of the applications +/// using @c IfaceMgr on the physical properties of the system and effectively +/// makes it very hard to unit test the dependent code. +/// +/// Unit tests usually require that @c IfaceMgr holds a list of well known +/// interfaces with the well known set of IP addresses and other properties +/// (a.k.a. interface flags). The solution which works for many test scenarios +/// is to provide a set of well known fake interfaces, by bypassing the +/// standard interface detection procedure and manually adding @c Iface objects +/// which encapsulate the fake interfaces. As a consequence, it becomes +/// impossible to test IO operations (e.g. sending packets) because real sockets +/// can't be opened on these interfaces. The @c PktFilterTestStub class +/// is used by this class to mimic behavior of IO operations on fake sockets. +/// +/// This class provides a set of convenience functions that should be called +/// by unit tests to configure the @c IfaceMgr with fake interfaces. +/// +/// The class allows the caller to create custom fake interfaces (with custom +/// IPv4 and IPv6 addresses, flags etc.), but it also provides a default +/// test configuration for interfaces as follows: +/// - lo #0 +/// - 127.0.0.1 +/// - ::1 +/// - eth0 #1 +/// - 10.0.0.1 +/// - fe80::3a60:77ff:fed5:cdef +/// - 2001:db8:1::1 +/// - eth1 #2 +/// - 192.0.2.3 +/// - fe80::3a60:77ff:fed5:abcd +/// - eth1961 #1962 +/// - 198.51.100.1 +/// - fe80::3a60:77ff:fed5:9876 +/// +/// For all interfaces the following flags are set: +/// - multicast +/// - up +/// - running +class IfaceMgrTestConfig : public boost::noncopyable { +public: + + /// @brief Constructor. + /// + /// It closes all sockets opened by @c IfaceMgr and removes all interfaces + /// being used by @c IfaceMgr. + IfaceMgrTestConfig(const bool default_config = false); + + /// @brief Destructor. + /// + /// Closes all currently opened sockets, removes current interfaces and + /// sets the default packet filtering classes. The default packet filtering + /// classes are used for IO operations on real sockets/interfaces. + /// Receiver is stopped. + /// + /// Destructor also re-detects real interfaces. + ~IfaceMgrTestConfig(); + + /// @brief Adds new IPv4 or IPv6 address to the interface. + /// + /// @param iface_name Name of the interface on which new address should + /// be configured. + /// @param address IPv4 or IPv6 address to be configured on the interface. + void addAddress(const std::string& iface_name, + const asiolink::IOAddress& address); + + /// @brief Configures new interface for the @c IfaceMgr. + /// + /// @param iface Object encapsulating interface to be added. + void addIface(const IfacePtr& iface); + + /// @brief Configures new interface for the @c IfaceMgr. + /// + /// @param name Name of the new interface. + /// @param ifindex Index for a new interface. + void addIface(const std::string& name, const int ifindex); + + /// @brief Create an object representing interface. + /// + /// Apart from creating an interface, this function also sets the + /// interface flags: + /// - loopback flag if interface name is "lo" + /// - up always true + /// - running always true + /// - inactive4 set to false for non-loopback interface + /// - inactive6 set to false for non-loopback interface + /// - multicast always to true + /// - broadcast always to false + /// + /// If one needs to modify the default flag settings, the setIfaceFlags + /// function should be used. + /// + /// @param name A name of the interface to be created. + /// @param ifindex An index of the interface to be created. + /// + /// @return An object representing interface. + static IfacePtr createIface(const std::string& name, const int ifindex); + + /// @brief Creates a default (example) set of fake interfaces. + void createIfaces(); + + /// @brief Returns currently used packet filter for DHCPv4. + PktFilterPtr getPacketFilter4() const { + return (packet_filter4_); + } + + /// @brief Sets the direct response capability for current packet filter. + /// + /// The test uses stub implementation of packet filter object. It is + /// possible to configure that object to report having a capability + /// to directly respond to clients which don't have an address yet. + /// This function sets this property for packet filter object. + /// + /// @param direct_resp Value to be set. + /// + /// @throw isc::Unexpected if unable to set the property. + void setDirectResponse(const bool direct_resp); + + /// @brief Sets various flags on the specified interface. + /// + /// This function configures interface with new values for flags. + /// + /// @param name Interface name. + /// @param loopback Specifies if interface is a loopback interface. + /// @param up Specifies if the interface is up. + /// @param running Specifies if the interface is running. + /// @param inactive4 Specifies if the interface is inactive for V4 + /// traffic, i.e. @c IfaceMgr opens V4 sockets on this interface. + /// @param inactive6 Specifies if the interface is inactive for V6 + /// traffic, i.e. @c IfaceMgr opens V6 sockets on this interface. + void setIfaceFlags(const std::string& name, + const FlagLoopback& loopback, + const FlagUp& up, + const FlagRunning& running, + const FlagInactive4& inactive4, + const FlagInactive6& inactive6); + + /// @brief Checks if socket of the specified family is opened on interface. + /// + /// @param iface_name Interface name. + /// @param family One of: AF_INET or AF_INET6 + bool socketOpen(const std::string& iface_name, const int family) const; + + /// @brief Checks is socket is opened on the interface and bound to a + /// specified address. + /// + /// @param iface_name Interface name. + /// @param address Address to which the socket is bound. + bool socketOpen(const std::string& iface_name, + const std::string& address) const; + + /// @brief Checks if unicast socket is opened on interface. + /// + /// @param iface_name Interface name. + bool unicastOpen(const std::string& iface_name) const; + + +private: + /// @brief Currently used packet filter for DHCPv4. + PktFilterPtr packet_filter4_; + + /// @brief Currently used packet filter for DHCPv6. + PktFilter6Ptr packet_filter6_; +}; + +}; +}; +}; + +#endif // IFACE_MGR_TEST_CONFIG_H |