#include "catch.hpp" #include #include #include #include #include #include #include #include #include #include TEST_CASE("create node using builders") { using namespace osmium::builder::attr; // NOLINT(google-build-using-namespace) osmium::memory::Buffer buffer{1024 * 10}; SECTION("add node with only id") { const auto pos = osmium::builder::add_node(buffer, _id(22)); const auto& node = buffer.get(pos); REQUIRE(node.id() == 22); REQUIRE(node.version() == 0); REQUIRE(node.timestamp() == osmium::Timestamp{}); REQUIRE(node.changeset() == 0); REQUIRE(node.uid() == 0); REQUIRE(std::string{node.user()}.empty()); REQUIRE(node.location() == osmium::Location{}); REQUIRE(node.tags().empty()); } SECTION("add node with complete info but no tags") { const osmium::Location loc{3.14, 1.59}; const auto pos = osmium::builder::add_node(buffer, _id(1), _version(17), _timestamp(osmium::Timestamp{"2015-01-01T10:20:30Z"}), _cid(21), _uid(222), _location(loc), _user("foo") ); const auto& node = buffer.get(pos); REQUIRE(node.id() == 1); REQUIRE(node.version() == 17); REQUIRE(node.timestamp() == osmium::Timestamp{"2015-01-01T10:20:30Z"}); REQUIRE(node.changeset() == 21); REQUIRE(node.uid() == 222); REQUIRE(std::string{node.user()} == "foo"); REQUIRE(node.location() == loc); REQUIRE(node.tags().empty()); REQUIRE(std::distance(node.cbegin(), node.cend()) == 0); } SECTION("visible/deleted flag") { osmium::builder::add_node(buffer, _id(1), _deleted()); osmium::builder::add_node(buffer, _id(2), _deleted(true)); osmium::builder::add_node(buffer, _id(3), _deleted(false)); osmium::builder::add_node(buffer, _id(4), _visible()); osmium::builder::add_node(buffer, _id(5), _visible(true)); osmium::builder::add_node(buffer, _id(6), _visible(false)); auto it = buffer.select().cbegin(); REQUIRE_FALSE(it++->visible()); REQUIRE_FALSE(it++->visible()); REQUIRE(it++->visible()); REQUIRE(it++->visible()); REQUIRE(it++->visible()); REQUIRE_FALSE(it++->visible()); REQUIRE(it == buffer.select().cend()); } SECTION("order of attributes doesn't matter") { const osmium::Location loc{3.14, 1.59}; const auto pos = osmium::builder::add_node(buffer, _timestamp("2015-01-01T10:20:30Z"), _version(17), _cid(21), _uid(222), _user(std::string{"foo"}), _id(1), _location(3.14, 1.59) ); const auto& node = buffer.get(pos); REQUIRE(node.id() == 1); REQUIRE(node.version() == 17); REQUIRE(node.timestamp() == osmium::Timestamp{"2015-01-01T10:20:30Z"}); REQUIRE(node.changeset() == 21); REQUIRE(node.uid() == 222); REQUIRE(std::string{node.user()} == "foo"); REQUIRE(node.location() == loc); REQUIRE(node.tags().empty()); } } TEST_CASE("create node with tags using builders") { using namespace osmium::builder::attr; // NOLINT(google-build-using-namespace) osmium::memory::Buffer buffer{1024 * 10}; SECTION("add tags using _tag") { std::pair t1 = {"name", "Node Inn"}; std::pair t2 = {"phone", "+1-123-555-4567"}; const auto pos = osmium::builder::add_node(buffer, _id(2), _tag("amenity", "restaurant"), _tag(t1), _tag(t2), _tag(std::string{"cuisine"}, std::string{"italian"}) ); const auto& node = buffer.get(pos); REQUIRE(node.id() == 2); REQUIRE(node.tags().size() == 4); REQUIRE(std::distance(node.cbegin(), node.cend()) == 1); auto it = node.tags().cbegin(); REQUIRE(std::string{it->key()} == "amenity"); REQUIRE(std::string{it->value()} == "restaurant"); ++it; REQUIRE(std::string{it->key()} == "name"); REQUIRE(std::string{it->value()} == "Node Inn"); ++it; REQUIRE(std::string{it->key()} == "phone"); REQUIRE(std::string{it->value()} == "+1-123-555-4567"); ++it; REQUIRE(std::string{it->key()} == "cuisine"); REQUIRE(std::string{it->value()} == "italian"); ++it; REQUIRE(it == node.tags().cend()); } SECTION("add tags using _tags from initializer list") { const auto pos = osmium::builder::add_node(buffer, _id(3), _tags({{"amenity", "post_box"}}) ); const auto& node = buffer.get(pos); REQUIRE(node.id() == 3); REQUIRE(node.tags().size() == 1); auto it = node.tags().cbegin(); REQUIRE(std::string{it->key()} == "amenity"); REQUIRE(std::string{it->value()} == "post_box"); ++it; REQUIRE(it == node.tags().cend()); REQUIRE(std::distance(node.cbegin(), node.cend()) == 1); } SECTION("add tags using _tags from TagList") { const auto pos1 = osmium::builder::add_node(buffer, _id(3), _tag("a", "d"), _tag("b", "e"), _tag("c", "f") ); const auto& node1 = buffer.get(pos1); const auto pos2 = osmium::builder::add_node(buffer, _id(4), _tags(node1.tags()) ); const auto& node2 = buffer.get(pos2); REQUIRE(node2.id() == 4); REQUIRE(node2.tags().size() == 3); auto it = node2.tags().cbegin(); REQUIRE(std::string{it++->key()} == "a"); REQUIRE(std::string{it++->key()} == "b"); REQUIRE(std::string{it++->key()} == "c"); REQUIRE(it == node2.tags().cend()); REQUIRE(std::distance(node2.cbegin(), node2.cend()) == 1); } SECTION("add tags using mixed tag sources") { const std::vector tags = { {"t5", "t5"}, {"t6", "t6"} }; const auto pos = osmium::builder::add_node(buffer, _id(4), _tag("t1", "t1"), _tags({{"t2", "t2"}, {"t3", "t3"}}), _tag("t4", "t4"), _tags(tags) ); const auto& node = buffer.get(pos); REQUIRE(node.id() == 4); REQUIRE(node.tags().size() == 6); auto it = node.tags().cbegin(); REQUIRE(std::string{it->key()} == "t1"); ++it; REQUIRE(std::string{it->key()} == "t2"); ++it; REQUIRE(std::string{it->key()} == "t3"); ++it; REQUIRE(std::string{it->key()} == "t4"); ++it; REQUIRE(std::string{it->key()} == "t5"); ++it; REQUIRE(std::string{it->key()} == "t6"); ++it; REQUIRE(it == node.tags().cend()); REQUIRE(std::distance(node.cbegin(), node.cend()) == 1); } } TEST_CASE("create way using builders") { using namespace osmium::builder::attr; // NOLINT(google-build-using-namespace) osmium::memory::Buffer buffer{1024 * 10}; SECTION("add way without nodes") { const auto pos = osmium::builder::add_way(buffer, _id(999), _cid(21), _uid(222), _user("foo") ); const auto& way = buffer.get(pos); REQUIRE(way.id() == 999); REQUIRE(way.version() == 0); REQUIRE(way.timestamp() == osmium::Timestamp{}); REQUIRE(way.changeset() == 21); REQUIRE(way.uid() == 222); REQUIRE(std::string{way.user()} == "foo"); REQUIRE(way.tags().empty()); REQUIRE(way.nodes().empty()); REQUIRE(std::distance(way.cbegin(), way.cend()) == 0); } } TEST_CASE("create way with nodes") { std::vector nrvec = { { 1, osmium::Location{1.1, 0.1} }, { 2, osmium::Location{2.2, 0.2} }, { 4, osmium::Location{4.4, 0.4} }, { 8, osmium::Location{8.8, 0.8} } }; using namespace osmium::builder::attr; // NOLINT(google-build-using-namespace) osmium::memory::Buffer wbuffer{1024 * 10}; osmium::builder::add_way(wbuffer, _id(1), _nodes({1, 2, 4, 8}) ); const osmium::NodeRefList& nodes = wbuffer.get(0).nodes(); osmium::memory::Buffer buffer{1024 * 10}; SECTION("add nodes using an OSM object id or NodeRef") { osmium::builder::add_way(buffer, _id(1), _node(1), _node(2), _node(osmium::NodeRef{4}), _node(8) ); } SECTION("add nodes using iterator list with object ids") { osmium::builder::add_way(buffer, _id(1), _nodes({1, 2, 4, 8}) ); } SECTION("add way with nodes in initializer_list of NodeRefs") { osmium::builder::add_way(buffer, _id(1), _nodes({ { 1, {1.1, 0.1} }, { 2, {2.2, 0.2} }, { 4, {4.4, 0.4} }, { 8, {8.8, 0.8} } }) ); } SECTION("add nodes using WayNodeList") { osmium::builder::add_way(buffer, _id(1), _nodes(nodes) ); } SECTION("add nodes using vector of OSM object ids") { const std::vector some_nodes = { 1, 2, 4, 8 }; osmium::builder::add_way(buffer, _id(1), _nodes(some_nodes) ); } SECTION("add nodes using vector of NodeRefs") { osmium::builder::add_way(buffer, _id(1), _nodes(nrvec) ); } SECTION("add nodes using different means together") { osmium::builder::add_way(buffer, _id(1), _node(1), _nodes({2, 4}), _node(8) ); } SECTION("add nodes using different means together") { osmium::builder::add_way(buffer, _id(1), _nodes(nodes.begin(), nodes.begin() + 1), _nodes({2, 4, 8}) ); } const auto& way = buffer.get(0); REQUIRE(way.id() == 1); REQUIRE(way.nodes().size() == 4); REQUIRE(std::distance(way.cbegin(), way.cend()) == 1); auto it = way.nodes().cbegin(); REQUIRE(it->ref() == 1); if (it->location().valid()) { REQUIRE(*it == nrvec[0]); } it++; REQUIRE(it->ref() == 2); if (it->location().valid()) { REQUIRE(*it == nrvec[1]); } it++; REQUIRE(it->ref() == 4); if (it->location().valid()) { REQUIRE(*it == nrvec[2]); } it++; REQUIRE(it->ref() == 8); if (it->location().valid()) { REQUIRE(*it == nrvec[3]); } it++; REQUIRE(it == way.nodes().cend()); } TEST_CASE("create relation using builders") { using namespace osmium::builder::attr; // NOLINT(google-build-using-namespace) osmium::memory::Buffer buffer{1024 * 10}; SECTION("create relation") { osmium::builder::attr::member_type m{osmium::item_type::way, 113, "inner"}; osmium::builder::add_relation(buffer, _id(123), _member(osmium::item_type::node, 123, ""), _member(osmium::item_type::node, 132), _member(osmium::item_type::way, 111, "outer"), _member(osmium::builder::attr::member_type{osmium::item_type::way, 112, "inner"}), _member(m) ); const auto& relation = buffer.get(0); REQUIRE(relation.id() == 123); REQUIRE(relation.members().size() == 5); REQUIRE(std::distance(relation.cbegin(), relation.cend()) == 1); auto it = relation.members().begin(); REQUIRE(it->type() == osmium::item_type::node); REQUIRE(it->ref() == 123); REQUIRE(std::string{it->role()}.empty()); ++it; REQUIRE(it->type() == osmium::item_type::node); REQUIRE(it->ref() == 132); REQUIRE(std::string{it->role()}.empty()); ++it; REQUIRE(it->type() == osmium::item_type::way); REQUIRE(it->ref() == 111); REQUIRE(std::string{it->role()} == "outer"); ++it; REQUIRE(it->type() == osmium::item_type::way); REQUIRE(it->ref() == 112); REQUIRE(std::string{it->role()} == "inner"); ++it; REQUIRE(it->type() == osmium::item_type::way); REQUIRE(it->ref() == 113); REQUIRE(std::string{it->role()} == "inner"); ++it; REQUIRE(it == relation.members().end()); } SECTION("create relation member from existing relation member") { osmium::builder::add_relation(buffer, _id(123), _member(osmium::item_type::way, 111, "outer"), _member(osmium::item_type::way, 112, "inner") ); const auto& relation1 = buffer.get(0); const auto pos = osmium::builder::add_relation(buffer, _id(124), _member(*relation1.members().begin()), _members(std::next(relation1.members().begin()), relation1.members().end()) ); const auto& relation = buffer.get(pos); REQUIRE(relation.id() == 124); REQUIRE(relation.members().size() == 2); auto it = relation.members().begin(); REQUIRE(it->type() == osmium::item_type::way); REQUIRE(it->ref() == 111); REQUIRE(std::string{it->role()} == "outer"); ++it; REQUIRE(it->type() == osmium::item_type::way); REQUIRE(it->ref() == 112); REQUIRE(std::string{it->role()} == "inner"); ++it; REQUIRE(it == relation.members().end()); } SECTION("create relation with members from initializer list") { const auto pos = osmium::builder::add_relation(buffer, _id(123), _members({ {osmium::item_type::node, 123, ""}, {osmium::item_type::way, 111, "outer"} }) ); const auto& relation = buffer.get(pos); REQUIRE(relation.id() == 123); REQUIRE(relation.members().size() == 2); REQUIRE(std::distance(relation.cbegin(), relation.cend()) == 1); auto it = relation.members().begin(); REQUIRE(it->type() == osmium::item_type::node); REQUIRE(it->ref() == 123); REQUIRE(std::string{it->role()}.empty()); ++it; REQUIRE(it->type() == osmium::item_type::way); REQUIRE(it->ref() == 111); REQUIRE(std::string{it->role()} == "outer"); ++it; REQUIRE(it == relation.members().end()); } SECTION("create relation with members from iterators and some tags") { const std::vector members = { {osmium::item_type::node, 123}, {osmium::item_type::way, 111, "outer"} }; SECTION("using iterators") { osmium::builder::add_relation(buffer, _id(123), _members(members.begin(), members.end()), _tag("a", "x"), _tag("b", "y") ); } SECTION("using container") { osmium::builder::add_relation(buffer, _id(123), _members(members), _tag("a", "x"), _tag("b", "y") ); } const auto& relation = buffer.get(0); REQUIRE(relation.id() == 123); REQUIRE(relation.members().size() == 2); REQUIRE(relation.tags().size() == 2); REQUIRE(std::distance(relation.cbegin(), relation.cend()) == 2); auto it = relation.members().begin(); REQUIRE(it->type() == osmium::item_type::node); REQUIRE(it->ref() == 123); REQUIRE(std::string{it->role()}.empty()); ++it; REQUIRE(it->type() == osmium::item_type::way); REQUIRE(it->ref() == 111); REQUIRE(std::string{it->role()} == "outer"); ++it; REQUIRE(it == relation.members().end()); } } TEST_CASE("create area using builders") { using namespace osmium::builder::attr; // NOLINT(google-build-using-namespace) osmium::memory::Buffer buffer{1024 * 10}; SECTION("add area without rings") { const auto pos = osmium::builder::add_area(buffer, _id(999), _cid(21), _uid(222), _user("foo"), _tag("landuse", "residential") ); const auto& area = buffer.get(pos); REQUIRE(area.id() == 999); REQUIRE(area.version() == 0); REQUIRE(area.timestamp() == osmium::Timestamp{}); REQUIRE(area.changeset() == 21); REQUIRE(area.uid() == 222); REQUIRE(std::string{area.user()} == "foo"); REQUIRE(area.tags().size() == 1); REQUIRE(std::distance(area.cbegin(), area.cend()) == 1); } }