#include "catch.hpp" #include "utils.hpp" #include #include #include struct EmptyRM : public osmium::relations::RelationsManager { }; struct TestRM : public osmium::relations::RelationsManager { std::size_t count_new_rels = 0; std::size_t count_new_members = 0; std::size_t count_complete_rels = 0; std::size_t count_before = 0; std::size_t count_not_in_any = 0; std::size_t count_after = 0; bool new_relation(const osmium::Relation& /*relation*/) noexcept { ++count_new_rels; return true; } bool new_member(const osmium::Relation& /*relation*/, const osmium::RelationMember& /*member*/, std::size_t /*n*/) noexcept { ++count_new_members; return true; } void complete_relation(const osmium::Relation& /*relation*/) noexcept { ++count_complete_rels; } void before_node(const osmium::Node& /*node*/) noexcept { ++count_before; } void node_not_in_any_relation(const osmium::Node& /*node*/) noexcept { ++count_not_in_any; } void after_node(const osmium::Node& /*node*/) noexcept { ++count_after; } void before_way(const osmium::Way& /*way*/) noexcept { ++count_before; } void way_not_in_any_relation(const osmium::Way& /*way*/) noexcept { ++count_not_in_any; } void after_way(const osmium::Way& /*way*/) noexcept { ++count_after; } void before_relation(const osmium::Relation& /*relation*/) noexcept { ++count_before; } void relation_not_in_any_relation(const osmium::Relation& /*relation*/) noexcept { ++count_not_in_any; } void after_relation(const osmium::Relation& /*relation*/) noexcept { ++count_after; } }; struct CallbackRM : public osmium::relations::RelationsManager { std::size_t count_nodes = 0; bool new_relation(const osmium::Relation& /*relation*/) noexcept { return true; } bool new_member(const osmium::Relation& /*relation*/, const osmium::RelationMember& member, std::size_t /*n*/) noexcept { return member.type() == osmium::item_type::node; } void complete_relation(const osmium::Relation& relation) noexcept { for (const auto& member : relation.members()) { if (member.type() == osmium::item_type::node) { ++count_nodes; const auto* node = get_member_node(member.ref()); REQUIRE(node); buffer().add_item(*node); buffer().commit(); } } } }; TEST_CASE("Use RelationsManager without any overloaded functions in derived class") { osmium::io::File file{with_data_dir("t/relations/data.osm")}; EmptyRM manager; osmium::relations::read_relations(file, manager); REQUIRE(manager.member_nodes_database().size() == 2); REQUIRE(manager.member_ways_database().size() == 2); REQUIRE(manager.member_relations_database().size() == 1); REQUIRE(manager.member_database(osmium::item_type::node).size() == 2); REQUIRE(manager.member_database(osmium::item_type::way).size() == 2); REQUIRE(manager.member_database(osmium::item_type::relation).size() == 1); const auto& m = manager; REQUIRE(m.member_database(osmium::item_type::node).size() == 2); REQUIRE(m.member_database(osmium::item_type::way).size() == 2); REQUIRE(m.member_database(osmium::item_type::relation).size() == 1); osmium::io::Reader reader{file}; osmium::apply(reader, manager.handler()); reader.close(); } TEST_CASE("Relations manager derived class") { osmium::io::File file{with_data_dir("t/relations/data.osm")}; TestRM manager; osmium::relations::read_relations(file, manager); REQUIRE(manager.member_nodes_database().size() == 2); REQUIRE(manager.member_ways_database().size() == 2); REQUIRE(manager.member_relations_database().size() == 1); bool callback_called = false; osmium::io::Reader reader{file}; osmium::apply(reader, manager.handler([&](osmium::memory::Buffer&&) { callback_called = true; })); reader.close(); REQUIRE_FALSE(callback_called); REQUIRE(manager.count_new_rels == 3); REQUIRE(manager.count_new_members == 5); REQUIRE(manager.count_complete_rels == 2); REQUIRE(manager.count_before == 10); REQUIRE(manager.count_not_in_any == 6); REQUIRE(manager.count_after == 10); int n = 0; manager.for_each_incomplete_relation([&](const osmium::relations::RelationHandle& handle){ ++n; REQUIRE(handle->id() == 31); for (const auto& member : handle->members()) { const auto* obj = manager.get_member_object(member); if (member.ref() == 22) { REQUIRE_FALSE(obj); } else { REQUIRE(obj); } } }); REQUIRE(n == 1); } TEST_CASE("Relations manager with callback") { osmium::io::File file{with_data_dir("t/relations/data.osm")}; CallbackRM manager; osmium::relations::read_relations(file, manager); REQUIRE(manager.member_nodes_database().size() == 2); REQUIRE(manager.member_ways_database().size() == 0); REQUIRE(manager.member_relations_database().size() == 0); bool callback_called = false; osmium::io::Reader reader{file}; osmium::apply(reader, manager.handler([&](osmium::memory::Buffer&& buffer) { callback_called = true; REQUIRE(std::distance(buffer.begin(), buffer.end()) == 2); })); reader.close(); REQUIRE(manager.count_nodes == 2); REQUIRE(callback_called); } TEST_CASE("Relations manager reading buffer without callback") { osmium::io::File file{with_data_dir("t/relations/data.osm")}; CallbackRM manager; osmium::relations::read_relations(file, manager); REQUIRE(manager.member_nodes_database().size() == 2); REQUIRE(manager.member_ways_database().size() == 0); REQUIRE(manager.member_relations_database().size() == 0); osmium::io::Reader reader{file}; osmium::apply(reader, manager.handler()); reader.close(); auto buffer = manager.read(); REQUIRE(std::distance(buffer.begin(), buffer.end()) == 2); REQUIRE(manager.count_nodes == 2); } TEST_CASE("Access members via RelationsManager") { EmptyRM manager; manager.prepare_for_lookup(); REQUIRE(nullptr == manager.get_member_node(0)); REQUIRE(nullptr == manager.get_member_way(0)); REQUIRE(nullptr == manager.get_member_relation(0)); REQUIRE(nullptr == manager.get_member_node(17)); REQUIRE(nullptr == manager.get_member_way(17)); REQUIRE(nullptr == manager.get_member_relation(17)); } TEST_CASE("Handle duplicate members correctly") { osmium::io::File file{with_data_dir("t/relations/dupl_member.osm")}; TestRM manager; osmium::relations::read_relations(file, manager); auto c = manager.member_nodes_database().count(); REQUIRE(c.tracked == 5); REQUIRE(c.available == 0); REQUIRE(c.removed == 0); osmium::io::Reader reader{file}; osmium::apply(reader, manager.handler()); reader.close(); c = manager.member_nodes_database().count(); REQUIRE(c.tracked == 0); REQUIRE(c.available == 0); REQUIRE(c.removed == 5); REQUIRE(manager.count_new_rels == 2); REQUIRE(manager.count_new_members == 5); REQUIRE(manager.count_complete_rels == 2); REQUIRE(manager.count_not_in_any == 2); // 2 relations }