Commit 2f66bfbe authored by Jelte Jansen's avatar Jelte Jansen

equality functions for data::Element + tests

added a removeIdentical(mapelement, mapelement) for use in config update handlers


git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@1040 e5f2f494-b856-4b98-b285-d166d9295462
parent 6caebd56
......@@ -58,6 +58,11 @@ std::ostream& operator <<(std::ostream &out, const isc::data::ElementPtr& e) {
return out << e->str();
}
bool operator==(const isc::data::ElementPtr a, const isc::data::ElementPtr b)
{
return a->equals(b);
};
//
// factory functions
//
......@@ -911,9 +916,110 @@ MapElement::find(const std::string& id, ElementPtr& t) {
return false;
}
bool
IntElement::equals(ElementPtr other)
{
return (other->getType() == Element::integer) &&
(i == other->intValue());
}
bool
DoubleElement::equals(ElementPtr other)
{
return (other->getType() == Element::real) &&
(d == other->doubleValue());
}
bool
BoolElement::equals(ElementPtr other)
{
return (other->getType() == Element::boolean) &&
(b == other->boolValue());
}
bool
StringElement::equals(ElementPtr other)
{
return (other->getType() == Element::string) &&
(s == other->stringValue());
}
bool
ListElement::equals(ElementPtr other)
{
if (other->getType() == Element::list) {
int s = size();
if (s != other->size()) {
return false;
}
for (int i = 0; i < s; i++) {
if (!get(i)->equals(other->get(i))) {
return false;
}
}
return true;
} else {
return false;
}
}
bool
MapElement::equals(ElementPtr other)
{
if (other->getType() == Element::map) {
std::map<std::string, ElementPtr> m = mapValue();
for (std::map<std::string, ElementPtr>::iterator it = m.begin() ;
it != m.end() ; ++it) {
if (other->contains((*it).first)) {
if (!get((*it).first)->equals(other->get((*it).first))) {
return false;
}
} else {
return false;
}
}
// quickly walk through the other map too, to see if there's
// anything in there that we don't have. We don't need to
// compare those elements; if one of them is missing we
// differ (and if it's not missing the loop above has checked
// it)
m = other->mapValue();
for (std::map<std::string, ElementPtr>::iterator it = m.begin() ;
it != m.end() ; ++it) {
if (!contains((*it).first)) {
return false;
}
}
return true;
} else {
return false;
}
}
bool
isc::data::isNull(ElementPtr p)
{
return !p;
}
void
isc::data::removeIdentical(ElementPtr a, const ElementPtr b)
{
if (a->getType() != Element::map || b->getType() != Element::map) {
dns_throw(TypeError, "Non-map Elements passed to removeIdentical");
}
std::cout<<"[XX] removeidentical from " << a << " and " << b << std::endl;
std::map<std::string, ElementPtr> m = a->mapValue();
for (std::map<std::string, ElementPtr>::iterator it = m.begin() ;
it != m.end() ; ++it) {
if (b->contains((*it).first)) {
if (a->get((*it).first)->equals(b->get((*it).first))) {
std::cout<<"[XX] remove " << (*it).first << std::endl;
a->remove((*it).first);
}
}
}
std::cout<<"[XX] a now " << a << std::endl;
}
......@@ -103,6 +103,10 @@ public:
/// \return the type of this element
int getType() { return type; };
/// \returns true if the other ElementPtr has the same type and
/// value
virtual bool equals(ElementPtr other) = 0;
// pure virtuals, every derived class must implement these
......@@ -332,6 +336,7 @@ public:
bool setValue(const int v) { i = v; return true; };
std::string str();
void toWire(std::stringstream& ss, int omit_length = 1);
bool equals(ElementPtr other);
};
class DoubleElement : public Element {
......@@ -346,6 +351,7 @@ public:
bool setValue(const double v) { d = v; return true; };
std::string str();
void toWire(std::stringstream& ss, int omit_length = 1);
bool equals(ElementPtr other);
};
class BoolElement : public Element {
......@@ -360,6 +366,7 @@ public:
bool setValue(const bool v) { b = v; return true; };
std::string str();
void toWire(std::stringstream& ss, int omit_length = 1);
bool equals(ElementPtr other);
};
class StringElement : public Element {
......@@ -374,6 +381,7 @@ public:
bool setValue(const std::string& v) { s = v; return true; };
std::string str();
void toWire(std::stringstream& ss, int omit_length = 1);
bool equals(ElementPtr other);
};
class ListElement : public Element {
......@@ -396,6 +404,7 @@ public:
std::string str();
void toWire(std::stringstream& ss, int omit_length = 1);
size_t size() { return l.size(); }
bool equals(ElementPtr other);
};
class MapElement : public Element {
......@@ -435,6 +444,8 @@ public:
// it doesnt exist or one of the elements in the path is not
// a MapElement)
bool find(const std::string& id, ElementPtr& t);
bool equals(ElementPtr other);
};
/// Checks whether the given ElementPtr is a NULL pointer
......@@ -442,6 +453,14 @@ public:
/// \return true if it is NULL, false if not.
bool isNull(ElementPtr p);
///
/// \brief Remove all values from the first ElementPtr that are
/// also present in the second. Both ElementPtrs MUST be MapElements
/// The use for this function is to end up with a MapElement that
/// only contains new and changed values (for ModuleCCSession and
/// configuration update handlers)
/// Raises a TypeError if a or b are not MapElements
void removeIdentical(ElementPtr a, const ElementPtr b);
} }
......@@ -462,6 +481,8 @@ bool isNull(ElementPtr p);
/// parameter \c os after the insertion operation.
std::ostream& operator <<(std::ostream &out, const isc::data::ElementPtr& e);
bool operator==(const isc::data::ElementPtr a, const isc::data::ElementPtr b);
#endif // _ISC_DATA_H
// Local Variables:
......
......@@ -276,3 +276,107 @@ TEST(Element, to_and_from_wire) {
EXPECT_EQ(ddef, ddef2);
}
ElementPtr efs(const std::string& str) {
return Element::createFromString(str);
}
TEST(Element, equals) {
// why does EXPECT_EQ not work?
EXPECT_TRUE(efs("1") == efs("1"));
EXPECT_FALSE(efs("1") == efs("2"));
EXPECT_FALSE(efs("1") == efs("\"1\""));
EXPECT_FALSE(efs("1") == efs("[]"));
EXPECT_FALSE(efs("1") == efs("True"));
EXPECT_FALSE(efs("1") == efs("{}"));
EXPECT_TRUE(efs("1.1") == efs("1.1"));
EXPECT_FALSE(efs("1.0") == efs("1"));
EXPECT_FALSE(efs("1.1") == efs("\"1\""));
EXPECT_FALSE(efs("1.1") == efs("[]"));
EXPECT_FALSE(efs("1.1") == efs("True"));
EXPECT_FALSE(efs("1.1") == efs("{}"));
EXPECT_TRUE(efs("True") == efs("True"));
EXPECT_FALSE(efs("True") == efs("False"));
EXPECT_FALSE(efs("True") == efs("1"));
EXPECT_FALSE(efs("True") == efs("\"1\""));
EXPECT_FALSE(efs("True") == efs("[]"));
EXPECT_FALSE(efs("True") == efs("{}"));
EXPECT_TRUE(efs("\"foo\"") == efs("\"foo\""));
EXPECT_FALSE(efs("\"foo\"") == efs("\"bar\""));
EXPECT_FALSE(efs("\"foo\"") == efs("1"));
EXPECT_FALSE(efs("\"foo\"") == efs("\"1\""));
EXPECT_FALSE(efs("\"foo\"") == efs("True"));
EXPECT_FALSE(efs("\"foo\"") == efs("[]"));
EXPECT_FALSE(efs("\"foo\"") == efs("{}"));
EXPECT_TRUE(efs("[]") == efs("[]"));
EXPECT_TRUE(efs("[ 1, 2, 3 ]") == efs("[ 1, 2, 3 ]"));
EXPECT_TRUE(efs("[ \"a\", [ True, 1], 2.2 ]") == efs("[ \"a\", [ True, 1], 2.2 ]"));
EXPECT_FALSE(efs("[ \"a\", [ True, 1], 2.2 ]") == efs("[ \"a\", [ True, 2], 2.2 ]"));
EXPECT_FALSE(efs("[]") == efs("[1]"));
EXPECT_FALSE(efs("[]") == efs("1"));
EXPECT_FALSE(efs("[]") == efs("\"1\""));
EXPECT_FALSE(efs("[]") == efs("{}"));
EXPECT_TRUE(efs("{}") == efs("{}"));
EXPECT_TRUE(efs("{ \"foo\": \"bar\" }") == efs("{ \"foo\": \"bar\" }"));
EXPECT_TRUE(efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }") == efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }"));
EXPECT_FALSE(efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }") == efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar2\" } }"));
EXPECT_FALSE(efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\" ], \"item3\": { \"foo\": \"bar\" } }") == efs("{ \"item1\": 1, \"item2\": [ \"a\", \"list\", 1 ], \"item3\": { \"foo\": \"bar\" } }"));
EXPECT_FALSE(efs("{ \"foo\": \"bar\" }") == efs("1"));
EXPECT_FALSE(efs("{ \"foo\": \"bar\" }") == efs("\"1\""));
EXPECT_FALSE(efs("{ \"foo\": \"bar\" }") == efs("[]"));
EXPECT_FALSE(efs("{ \"foo\": \"bar\" }") == efs("{}"));
}
TEST(Element, removeIdentical) {
ElementPtr a = Element::createFromString("{}");
ElementPtr b = Element::createFromString("{}");
ElementPtr c = Element::createFromString("{}");
removeIdentical(a, b);
EXPECT_TRUE(a == c);
a = Element::createFromString("{ \"a\": 1 }");
b = Element::createFromString("{ \"a\": 1 }");
c = Element::createFromString("{}");
removeIdentical(a, b);
EXPECT_TRUE(a == c);
a = Element::createFromString("{ \"a\": 1, \"b\": [ 1, 2 ] }");
b = Element::createFromString("{}");
c = Element::createFromString("{ \"a\": 1, \"b\": [ 1, 2 ] }");
removeIdentical(a, b);
EXPECT_TRUE(a == c);
a = Element::createFromString("{ \"a\": 1, \"b\": [ 1, 2 ] }");
b = Element::createFromString("{ \"a\": 1, \"b\": [ 1, 2 ] }");
c = Element::createFromString("{}");
removeIdentical(a, b);
EXPECT_TRUE(a == c);
a = Element::createFromString("{ \"a\": 1, \"b\": [ 1, 2 ] }");
b = Element::createFromString("{ \"a\": 1, \"b\": [ 1, 3 ] }");
c = Element::createFromString("{ \"b\": [ 1, 2 ] }");
removeIdentical(a, b);
EXPECT_TRUE(a == c);
a = Element::createFromString("{ \"a\": { \"b\": \"c\" } }");
b = Element::createFromString("{}");
c = Element::createFromString("{ \"a\": { \"b\": \"c\" } }");
removeIdentical(a, b);
EXPECT_TRUE(a == c);
a = Element::createFromString("{ \"a\": { \"b\": \"c\" } }");
b = Element::createFromString("{ \"a\": { \"b\": \"c\" } }");
c = Element::createFromString("{}");
removeIdentical(a, b);
EXPECT_TRUE(a == c);
a = Element::createFromString("{ \"a\": { \"b\": \"c\" } }");
b = Element::createFromString("{ \"a\": { \"b\": \"d\" } }");
c = Element::createFromString("{ \"a\": { \"b\": \"c\" } }");
removeIdentical(a, b);
EXPECT_TRUE(a == c);
}
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