Commit 9c807997 authored by Marcin Siodelski's avatar Marcin Siodelski

[3534] Implemented (in)equality operators for CfgIface.

parent c962fd54
...@@ -34,6 +34,13 @@ CfgIface::closeSockets() const { ...@@ -34,6 +34,13 @@ CfgIface::closeSockets() const {
IfaceMgr::instance().closeSockets(); IfaceMgr::instance().closeSockets();
} }
bool
CfgIface::equals(const CfgIface& other) const {
return (iface_set_ == other.iface_set_ &&
unicast_map_ == other.unicast_map_ &&
wildcard_used_ == other.wildcard_used_);
}
void void
CfgIface::openSockets(const Family& family, const uint16_t port, CfgIface::openSockets(const Family& family, const uint16_t port,
const bool use_bcast) const { const bool use_bcast) const {
......
...@@ -86,6 +86,13 @@ public: ...@@ -86,6 +86,13 @@ public:
/// @brief Convenience function which closes all open sockets. /// @brief Convenience function which closes all open sockets.
void closeSockets() const; void closeSockets() const;
/// @brief Compares two @c CfgIface objects for equality.
///
/// @param other An object to be compared with this object.
///
/// @return true if objects are equal, false otherwise.
bool equals(const CfgIface& other) const;
/// @brief Tries to open sockets on selected interfaces. /// @brief Tries to open sockets on selected interfaces.
/// ///
/// This function opens sockets bound to link-local address as well as /// This function opens sockets bound to link-local address as well as
...@@ -139,6 +146,24 @@ public: ...@@ -139,6 +146,24 @@ public:
/// @c CfgIface::use has been already called for this interface. /// @c CfgIface::use has been already called for this interface.
void use(const Family& family, const std::string& iface_name); void use(const Family& family, const std::string& iface_name);
/// @brief Equality operator.
///
/// @param other Object to be compared with this object.
///
/// @return true if objects are equal, false otherwise.
bool operator==(const CfgIface& other) const {
return (equals(other));
}
/// @brief Inequality operator.
///
/// @param other Object to be compared with this object.
///
/// @return true if objects are not equal, false otherwise.
bool operator!=(const CfgIface& other) const {
return (!equals(other));
}
private: private:
/// @brief Selects or deselects interfaces. /// @brief Selects or deselects interfaces.
...@@ -165,9 +190,6 @@ private: ...@@ -165,9 +190,6 @@ private:
/// @param errmsg Error message being logged by the function. /// @param errmsg Error message being logged by the function.
static void socketOpenErrorHandler(const std::string& errmsg); static void socketOpenErrorHandler(const std::string& errmsg);
/// @brief Protocol family.
Family family_;
/// @brief Represents a set of interface names. /// @brief Represents a set of interface names.
typedef std::set<std::string> IfaceSet; typedef std::set<std::string> IfaceSet;
......
...@@ -25,6 +25,8 @@ using namespace isc::util; ...@@ -25,6 +25,8 @@ using namespace isc::util;
namespace isc { namespace isc {
namespace dhcp { namespace dhcp {
const size_t CfgMgr::CONFIG_LIST_SIZE = 10;
CfgMgr& CfgMgr&
CfgMgr::instance() { CfgMgr::instance() {
static CfgMgr cfg_mgr; static CfgMgr cfg_mgr;
...@@ -376,6 +378,13 @@ CfgMgr::commit() { ...@@ -376,6 +378,13 @@ CfgMgr::commit() {
ensureCurrentAllocated(); ensureCurrentAllocated();
if (!configs_.back()->sequenceEquals(*configuration_)) { if (!configs_.back()->sequenceEquals(*configuration_)) {
configuration_ = configs_.back(); configuration_ = configs_.back();
// Keep track of the maximum size of the configs history. Before adding
// new element, we have to remove the oldest one.
if (configs_.size() > CONFIG_LIST_SIZE) {
ConfigurationList::iterator it = configs_.begin();
std::advance(it, configs_.size() - CONFIG_LIST_SIZE);
configs_.erase(configs_.begin(), it);
}
} }
} }
......
...@@ -95,6 +95,11 @@ public: ...@@ -95,6 +95,11 @@ public:
class CfgMgr : public boost::noncopyable { class CfgMgr : public boost::noncopyable {
public: public:
/// @brief A number of configurations held by @c CfgMgr.
///
/// @todo Make it configurable.
static const size_t CONFIG_LIST_SIZE;
/// @brief returns a single instance of Configuration Manager /// @brief returns a single instance of Configuration Manager
/// ///
/// CfgMgr is a singleton and this method is the only way of /// CfgMgr is a singleton and this method is the only way of
...@@ -385,6 +390,8 @@ public: ...@@ -385,6 +390,8 @@ public:
/// @todo Migrate all configuration parameters to use the model supported /// @todo Migrate all configuration parameters to use the model supported
/// by these functions. /// by these functions.
/// ///
/// @todo Make the size of the configurations history configurable.
///
//@{ //@{
/// @brief Removes current, staging and all previous configurations. /// @brief Removes current, staging and all previous configurations.
...@@ -399,7 +406,9 @@ public: ...@@ -399,7 +406,9 @@ public:
/// @brief Commits the staging configuration. /// @brief Commits the staging configuration.
/// ///
/// The staging configuration becomes current configuration when this /// The staging configuration becomes current configuration when this
/// function is called. /// function is called. It removes the oldest configurations held in the
/// history so as the size of the list of configuration does not excide
/// the @c CONFIG_LIST_SIZE.
/// ///
/// This function is exception safe. /// This function is exception safe.
void commit(); void commit();
......
...@@ -218,9 +218,60 @@ TEST_F(CfgIfaceTest, invalidValues) { ...@@ -218,9 +218,60 @@ TEST_F(CfgIfaceTest, invalidValues) {
ASSERT_THROW(cfg.use(CfgIface::V6, "eth0/fe80::3a60:77ff:fed5:cdef"), ASSERT_THROW(cfg.use(CfgIface::V6, "eth0/fe80::3a60:77ff:fed5:cdef"),
InvalidIfaceName); InvalidIfaceName);
ASSERT_THROW(cfg.use(CfgIface::V6, "eth0/2001:db8:1::2"), NoSuchAddress); ASSERT_THROW(cfg.use(CfgIface::V6, "eth0/2001:db8:1::2"), NoSuchAddress);
ASSERT_NO_THROW(cfg.use(CfgIface::V6, "*")); ASSERT_NO_THROW(cfg.use(CfgIface::V6, "*"));
ASSERT_THROW(cfg.use(CfgIface::V6, "*"), DuplicateIfaceName); ASSERT_THROW(cfg.use(CfgIface::V6, "*"), DuplicateIfaceName);
} }
// Test that the equality and inequality operators work fine for CfgIface.
TEST_F(CfgIfaceTest, equality) {
CfgIface cfg1;
CfgIface cfg2;
// Initially objects must be equal.
EXPECT_TRUE(cfg1 == cfg2);
EXPECT_FALSE(cfg1 != cfg2);
// Differ by one interface.
cfg1.use(CfgIface::V4, "eth0");
EXPECT_FALSE(cfg1 == cfg2);
EXPECT_TRUE(cfg1 != cfg2);
// Now interfaces should be equal.
cfg2.use(CfgIface::V4, "eth0");
EXPECT_TRUE(cfg1 == cfg2);
EXPECT_FALSE(cfg1 != cfg2);
// Differ by unicast address.
cfg1.use(CfgIface::V6, "eth0/2001:db8:1::1");
EXPECT_FALSE(cfg1 == cfg2);
EXPECT_TRUE(cfg1 != cfg2);
// Differ by unicast address and one interface.
cfg2.use(CfgIface::V6, "eth1");
EXPECT_FALSE(cfg1 == cfg2);
EXPECT_TRUE(cfg1 != cfg2);
// Now, the unicast addresses are equal but still differ by one interface.
cfg2.use(CfgIface::V6, "eth0/2001:db8:1::1");
EXPECT_FALSE(cfg1 == cfg2);
EXPECT_TRUE(cfg1 != cfg2);
// They should be now back to equal.
cfg1.use(CfgIface::V6, "eth1");
EXPECT_TRUE(cfg1 == cfg2);
EXPECT_FALSE(cfg1 != cfg2);
// Even though the wildcard doesn't change anything because all interfaces
// are already in use, the fact that the wildcard is specified should
// cause them to be not equal.
cfg1.use(CfgIface::V6, "*");
EXPECT_FALSE(cfg1 == cfg2);
EXPECT_TRUE(cfg1 != cfg2);
// Finally, both are equal as they use wildacard.
cfg2.use(CfgIface::V4, "*");
EXPECT_TRUE(cfg1 == cfg2);
EXPECT_FALSE(cfg1 != cfg2);
}
} // end of anonymous namespace } // end of anonymous namespace
...@@ -1125,7 +1125,7 @@ TEST_F(CfgMgrTest, subnet6Duplication) { ...@@ -1125,7 +1125,7 @@ TEST_F(CfgMgrTest, subnet6Duplication) {
} }
// This test verifies that the configuration staging and commit works // This test verifies that the configuration staging, commit and rollback works
// as expected. // as expected.
TEST_F(CfgMgrTest, staging) { TEST_F(CfgMgrTest, staging) {
CfgMgr& cfg_mgr = CfgMgr::instance(); CfgMgr& cfg_mgr = CfgMgr::instance();
...@@ -1159,7 +1159,7 @@ TEST_F(CfgMgrTest, staging) { ...@@ -1159,7 +1159,7 @@ TEST_F(CfgMgrTest, staging) {
// This should change the staging configuration so as it becomes a current // This should change the staging configuration so as it becomes a current
// one. // one.
CfgMgr::instance().commit(); cfg_mgr.commit();
const_config = cfg_mgr.getCurrentCfg(); const_config = cfg_mgr.getCurrentCfg();
ASSERT_TRUE(const_config); ASSERT_TRUE(const_config);
// Sequence id equal to 1 indicates that the current configuration points // Sequence id equal to 1 indicates that the current configuration points
...@@ -1176,7 +1176,7 @@ TEST_F(CfgMgrTest, staging) { ...@@ -1176,7 +1176,7 @@ TEST_F(CfgMgrTest, staging) {
// changes the configuration having sequence 2 to current configuration. // changes the configuration having sequence 2 to current configuration.
// Other commits are no-op. // Other commits are no-op.
for (int i = 0; i < 5; ++i) { for (int i = 0; i < 5; ++i) {
CfgMgr::instance().commit(); cfg_mgr.commit();
} }
// The current configuration now have sequence number 2. // The current configuration now have sequence number 2.
...@@ -1185,15 +1185,29 @@ TEST_F(CfgMgrTest, staging) { ...@@ -1185,15 +1185,29 @@ TEST_F(CfgMgrTest, staging) {
EXPECT_EQ(2, const_config->getSequence()); EXPECT_EQ(2, const_config->getSequence());
// Clear configuration along with a history. // Clear configuration along with a history.
CfgMgr::instance().clear(); cfg_mgr.clear();
// After clearing configuration we should successfully get the // After clearing configuration we should successfully get the
// new staging configuration. // new staging configuration.
const_config = cfg_mgr.getStagingCfg(); config = cfg_mgr.getStagingCfg();
ASSERT_TRUE(const_config); ASSERT_TRUE(config);
EXPECT_EQ(1, const_config->getSequence()); EXPECT_EQ(1, config->getSequence());
}
// Modify the staging configuration.
config->addLoggingInfo(LoggingInfo());
ASSERT_TRUE(config);
// The modified staging configuration should have one logger configured.
ASSERT_EQ(1, config->getLoggingInfo().size());
// Rollback should remove a staging configuration, including the logger.
ASSERT_NO_THROW(cfg_mgr.rollback());
// Make sure that the logger is not set. This is an indication that the
// rollback worked.
config = cfg_mgr.getStagingCfg();
ASSERT_TRUE(config);
EXPECT_EQ(0, config->getLoggingInfo().size());
}
/// @todo Add unit-tests for testing: /// @todo Add unit-tests for testing:
/// - addActiveIface() with invalid interface name /// - addActiveIface() with invalid interface name
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment