Commit 3ae0d93d authored by Thomas Markwalder's avatar Thomas Markwalder
Browse files

[master] Merge branch 'trac3339'

data::merge function now merges map sub elements.
parents 10fa44e1 ed75a8dd
// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2010-2014 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
......@@ -964,9 +964,26 @@ merge(ElementPtr element, ConstElementPtr other) {
const std::map<std::string, ConstElementPtr>& m = other->mapValue();
for (std::map<std::string, ConstElementPtr>::const_iterator it = m.begin();
it != m.end() ; ++it) {
it != m.end() ; ++it) {
if ((*it).second && (*it).second->getType() != Element::null) {
element->set((*it).first, (*it).second);
if (((*it).second->getType() == Element::map) &&
element->contains((*it).first)) {
// Sub-element is a map and is also in the original config,
// so we need to merge them too.
boost::shared_ptr<MapElement> merged_map(new MapElement());
ConstElementPtr orig_map = element->get((*it).first);
ConstElementPtr other_map = (*it).second;
if (orig_map->getType() == Element::map) {
merged_map->setValue(orig_map->mapValue());
}
// Now go recursive to merge the map sub-elements.
merge(merged_map, other_map);
element->set((*it).first, merged_map);
}
else {
element->set((*it).first, (*it).second);
}
} else if (element->contains((*it).first)) {
element->remove((*it).first);
}
......
// Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2009-2014 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
......@@ -848,7 +848,7 @@ TEST(Element, merge) {
ElementPtr a = Element::createMap();
ElementPtr b = Element::createMap();
ConstElementPtr c = Element::createMap();
merge(a, b);
ASSERT_NO_THROW(merge(a, b));
EXPECT_EQ(*a, *c);
a = Element::fromJSON("1");
......@@ -858,75 +858,102 @@ TEST(Element, merge) {
a = Element::createMap();
b = Element::fromJSON("{ \"a\": 1 }");
c = Element::fromJSON("{ \"a\": 1 }");
merge(a, b);
ASSERT_NO_THROW(merge(a, b));
EXPECT_EQ(*a, *c);
a = Element::createMap();
b = Element::fromJSON("{ \"a\": 1 }");
c = Element::fromJSON("{ \"a\": 1 }");
merge(b, a);
ASSERT_NO_THROW(merge(b, a));
EXPECT_EQ(*b, *c);
a = Element::fromJSON("{ \"a\": 1 }");
b = Element::fromJSON("{ \"a\": 2 }");
c = Element::fromJSON("{ \"a\": 2 }");
merge(a, b);
ASSERT_NO_THROW(merge(a, b));
EXPECT_EQ(*a, *c);
a = Element::fromJSON("{ \"a\": 1 }");
b = Element::fromJSON("{ \"a\": 2 }");
c = Element::fromJSON("{ \"a\": 1 }");
merge(b, a);
ASSERT_NO_THROW(merge(b, a));
EXPECT_EQ(*b, *c);
a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
b = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
c = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
merge(a, b);
ASSERT_NO_THROW(merge(a, b));
EXPECT_EQ(*a, *c);
a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
b = Element::fromJSON("{ \"a\": { \"b\": \"d\" } }");
c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
merge(b, a);
ASSERT_NO_THROW(merge(b, a));
EXPECT_EQ(*b, *c);
a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
b = Element::fromJSON("{ \"a\": null }");
c = Element::fromJSON("{ }");
merge(a, b);
ASSERT_NO_THROW(merge(a, b));
EXPECT_EQ(*a, *c);
a = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
b = Element::fromJSON("{ \"a\": null }");
c = Element::fromJSON("{ \"a\": { \"b\": \"c\" } }");
merge(b, a);
ASSERT_NO_THROW(merge(b, a));
EXPECT_EQ(*b, *c);
// And some tests with multiple values
a = Element::fromJSON("{ \"a\": 1, \"b\": true, \"c\": null }");
b = Element::fromJSON("{ \"a\": 1, \"b\": null, \"c\": \"a string\" }");
c = Element::fromJSON("{ \"a\": 1, \"c\": \"a string\" }");
merge(a, b);
ASSERT_NO_THROW(merge(a, b));
EXPECT_EQ(*a, *c);
a = Element::fromJSON("{ \"a\": 1, \"b\": true, \"c\": null }");
b = Element::fromJSON("{ \"a\": 1, \"b\": null, \"c\": \"a string\" }");
c = Element::fromJSON("{ \"a\": 1, \"b\": true }");
merge(b, a);
ASSERT_NO_THROW(merge(b, a));
EXPECT_EQ(*b, *c);
a = Element::fromJSON("{ \"a\": 1, \"b\": 2, \"c\": 3 }");
b = Element::fromJSON("{ \"a\": 3, \"b\": 2, \"c\": 1 }");
c = Element::fromJSON("{ \"a\": 3, \"b\": 2, \"c\": 1 }");
merge(a, b);
ASSERT_NO_THROW(merge(a, b));
EXPECT_EQ(*a, *c);
a = Element::fromJSON("{ \"a\": 1, \"b\": 2, \"c\": 3 }");
b = Element::fromJSON("{ \"a\": 3, \"b\": 2, \"c\": 1 }");
c = Element::fromJSON("{ \"a\": 1, \"b\": 2, \"c\": 3 }");
merge(b, a);
ASSERT_NO_THROW(merge(b, a));
EXPECT_EQ(*b, *c);
// Map sub-elements: original map element is null
a = Element::fromJSON("{ \"a\": 1, \"m\": null }");
b = Element::fromJSON("{ \"a\": 3, \"m\": { \"b\": 9 } }");
c = Element::fromJSON("{ \"a\": 3, \"m\": { \"b\": 9 } }");
ASSERT_NO_THROW(merge(a, b));
EXPECT_EQ(*a, *c);
// Map sub-elements new map element has less elements than original
a = Element::fromJSON("{ \"a\": 1, \"m\": { \"b\": 2, \"c\": 3 } }");
b = Element::fromJSON("{ \"a\": 3, \"m\": { \"b\": 9 } }");
c = Element::fromJSON("{ \"a\": 3, \"m\": { \"b\": 9, \"c\": 3 } }");
ASSERT_NO_THROW(merge(a, b));
EXPECT_EQ(*a, *c);
// Map sub-elements new map element is null
a = Element::fromJSON("{ \"a\": 1, \"m\": { \"b\": 2, \"c\": 3 } }");
b = Element::fromJSON("{ \"a\": 3, \"m\": null }");
c = Element::fromJSON("{ \"a\": 3 }");
ASSERT_NO_THROW(merge(a, b));
EXPECT_EQ(*a, *c);
// Map sub-elements new map element has more elments than origina
a = Element::fromJSON("{ \"a\": 1, \"m\": { \"b\": 2, \"c\": 3 } }");
b = Element::fromJSON("{ \"a\": 3, \"m\": { \"b\": 2, \"c\": 3, \"d\": 4} }");
c = Element::fromJSON("{ \"a\": 3, \"m\": { \"b\": 2, \"c\": 3, \"d\": 4} }");
ASSERT_NO_THROW(merge(a, b));
EXPECT_EQ(*a, *c);
}
}
Supports Markdown
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