|
10 | 10 | #include "common-options.hpp" |
11 | 11 | #include "common-pg.hpp" |
12 | 12 |
|
| 13 | +#include <algorithm> |
| 14 | + |
13 | 15 | static pg::tempdb_t db; |
14 | 16 |
|
15 | 17 | namespace { |
@@ -497,6 +499,32 @@ static void check_way(std::shared_ptr<middle_pgsql_t> const &mid, |
497 | 499 | REQUIRE(orig_crc().checksum() == test_crc().checksum()); |
498 | 500 | } |
499 | 501 |
|
| 502 | +/** |
| 503 | + * Check that the nodes (ids and locations) of the way with the way_id in the |
| 504 | + * mid are identical to the nodes in the nodes vector. |
| 505 | + */ |
| 506 | +static void check_way_nodes(std::shared_ptr<middle_pgsql_t> const &mid, |
| 507 | + osmid_t way_id, |
| 508 | + std::vector<osmium::Node const *> nodes) |
| 509 | +{ |
| 510 | + auto const mid_q = mid->get_query_instance(); |
| 511 | + |
| 512 | + osmium::memory::Buffer outbuf{4096, osmium::memory::Buffer::auto_grow::yes}; |
| 513 | + REQUIRE(mid_q->way_get(way_id, outbuf)); |
| 514 | + auto &way = outbuf.get<osmium::Way>(0); |
| 515 | + |
| 516 | + REQUIRE(mid_q->nodes_get_list(&way.nodes()) == way.nodes().size()); |
| 517 | + REQUIRE(way.nodes().size() == nodes.size()); |
| 518 | + |
| 519 | + auto it = way.nodes().cbegin(); |
| 520 | + for (auto const *nptr : nodes) { |
| 521 | + REQUIRE(nptr->id() == it->ref()); |
| 522 | + REQUIRE(nptr->location() == it->location()); |
| 523 | + ++it; |
| 524 | + } |
| 525 | + REQUIRE(it == way.nodes().cend()); |
| 526 | +} |
| 527 | + |
500 | 528 | /// Return true if the way with the specified id is not in the mid. |
501 | 529 | static bool no_way(std::shared_ptr<middle_pgsql_t> const &mid, osmid_t id) |
502 | 530 | { |
@@ -978,3 +1006,176 @@ TEMPLATE_TEST_CASE("middle: add relation with attributes", "", |
978 | 1006 | mid->commit(); |
979 | 1007 | } |
980 | 1008 | } |
| 1009 | + |
| 1010 | +class test_pending_processor : public middle_t::pending_processor |
| 1011 | +{ |
| 1012 | +public: |
| 1013 | + test_pending_processor() = default; |
| 1014 | + |
| 1015 | + void enqueue_ways(osmid_t id) override { m_way_ids.push_back(id); } |
| 1016 | + |
| 1017 | + void process_ways() override{}; |
| 1018 | + void enqueue_relations(osmid_t) override{}; |
| 1019 | + void process_relations() override{}; |
| 1020 | + |
| 1021 | + void check_way_ids_equal_to(std::initializer_list<osmid_t> list) noexcept |
| 1022 | + { |
| 1023 | + REQUIRE(!m_way_ids.empty()); |
| 1024 | + |
| 1025 | + // The last tracked id is always the invalid id, which we ignore |
| 1026 | + REQUIRE_FALSE(id_tracker::is_valid(m_way_ids.back())); |
| 1027 | + m_way_ids.pop_back(); |
| 1028 | + |
| 1029 | + REQUIRE(m_way_ids.size() == list.size()); |
| 1030 | + REQUIRE(std::equal(m_way_ids.cbegin(), m_way_ids.cend(), list.begin())); |
| 1031 | + } |
| 1032 | + |
| 1033 | +private: |
| 1034 | + std::vector<osmid_t> m_way_ids; |
| 1035 | +}; |
| 1036 | + |
| 1037 | +TEMPLATE_TEST_CASE("middle: change nodes in way", "", options_slim_default, |
| 1038 | + options_slim_dense_cache, options_flat_node_cache) |
| 1039 | +{ |
| 1040 | + options_t options = TestType::options(db); |
| 1041 | + |
| 1042 | + testing::cleanup::file_t flatnode_cleaner{ |
| 1043 | + options.flat_node_file.get_value_or("")}; |
| 1044 | + |
| 1045 | + // create some nodes and ways we'll use for the tests |
| 1046 | + test_buffer_t buffer; |
| 1047 | + auto const &node10 = buffer.add_node_and_get(10, 1.0, 0.0); |
| 1048 | + auto const &node11 = buffer.add_node_and_get(11, 1.1, 0.0); |
| 1049 | + auto const &node12 = buffer.add_node_and_get(12, 1.2, 0.0); |
| 1050 | + auto const &node10a = buffer.add_node_and_get(10, 2.0, 0.0); |
| 1051 | + |
| 1052 | + auto const &way20 = buffer.add_way_and_get(20, {10, 11}); |
| 1053 | + auto const &way21 = buffer.add_way_and_get(21, {11, 12}); |
| 1054 | + auto const &way22 = buffer.add_way_and_get(22, {12, 10}); |
| 1055 | + auto const &way20a = buffer.add_way_and_get(20, {11, 12}); |
| 1056 | + |
| 1057 | + // Set up middle in "create" mode to get a cleanly initialized database and |
| 1058 | + // add some nodes and ways. Does this in its own scope so that the mid is |
| 1059 | + // closed properly. |
| 1060 | + { |
| 1061 | + auto mid = std::make_shared<middle_pgsql_t>(&options); |
| 1062 | + mid->start(); |
| 1063 | + |
| 1064 | + mid->node_set(node10); |
| 1065 | + mid->node_set(node11); |
| 1066 | + mid->node_set(node12); |
| 1067 | + mid->flush(); |
| 1068 | + mid->way_set(way20); |
| 1069 | + mid->way_set(way21); |
| 1070 | + mid->flush(); |
| 1071 | + |
| 1072 | + check_node(mid, node10); |
| 1073 | + check_node(mid, node11); |
| 1074 | + check_node(mid, node12); |
| 1075 | + check_way(mid, way20); |
| 1076 | + check_way_nodes(mid, way20.id(), {&node10, &node11}); |
| 1077 | + check_way(mid, way21); |
| 1078 | + check_way_nodes(mid, way21.id(), {&node11, &node12}); |
| 1079 | + |
| 1080 | + // Nothing pending yet |
| 1081 | + REQUIRE_FALSE(mid->has_pending()); |
| 1082 | + test_pending_processor proc; |
| 1083 | + mid->iterate_ways(proc); |
| 1084 | + proc.check_way_ids_equal_to({}); |
| 1085 | + |
| 1086 | + mid->commit(); |
| 1087 | + } |
| 1088 | + |
| 1089 | + // From now on use append mode to not destroy the data we just added. |
| 1090 | + options.append = true; |
| 1091 | + |
| 1092 | + SECTION("single way affected") |
| 1093 | + { |
| 1094 | + auto mid = std::make_shared<middle_pgsql_t>(&options); |
| 1095 | + mid->start(); |
| 1096 | + |
| 1097 | + mid->node_delete(10); |
| 1098 | + mid->node_set(node10a); |
| 1099 | + mid->node_changed(10); |
| 1100 | + mid->flush(); |
| 1101 | + |
| 1102 | + REQUIRE(mid->has_pending()); |
| 1103 | + test_pending_processor proc; |
| 1104 | + mid->iterate_ways(proc); |
| 1105 | + proc.check_way_ids_equal_to({20}); |
| 1106 | + |
| 1107 | + check_way(mid, way20); |
| 1108 | + check_way_nodes(mid, way20.id(), {&node10a, &node11}); |
| 1109 | + |
| 1110 | + mid->commit(); |
| 1111 | + } |
| 1112 | + |
| 1113 | + SECTION("two ways affected") |
| 1114 | + { |
| 1115 | + { |
| 1116 | + auto mid = std::make_shared<middle_pgsql_t>(&options); |
| 1117 | + mid->start(); |
| 1118 | + |
| 1119 | + mid->way_set(way22); |
| 1120 | + mid->flush(); |
| 1121 | + check_way(mid, way22); |
| 1122 | + |
| 1123 | + mid->commit(); |
| 1124 | + } |
| 1125 | + { |
| 1126 | + auto mid = std::make_shared<middle_pgsql_t>(&options); |
| 1127 | + mid->start(); |
| 1128 | + |
| 1129 | + mid->node_delete(10); |
| 1130 | + mid->node_set(node10a); |
| 1131 | + mid->node_changed(10); |
| 1132 | + mid->flush(); |
| 1133 | + |
| 1134 | + REQUIRE(mid->has_pending()); |
| 1135 | + test_pending_processor proc; |
| 1136 | + mid->iterate_ways(proc); |
| 1137 | + proc.check_way_ids_equal_to({20, 22}); |
| 1138 | + |
| 1139 | + check_way(mid, way20); |
| 1140 | + check_way_nodes(mid, way20.id(), {&node10a, &node11}); |
| 1141 | + check_way(mid, way22); |
| 1142 | + check_way_nodes(mid, way22.id(), {&node12, &node10a}); |
| 1143 | + |
| 1144 | + mid->commit(); |
| 1145 | + } |
| 1146 | + } |
| 1147 | + |
| 1148 | + SECTION("change way so the changing node isn't in it any more") |
| 1149 | + { |
| 1150 | + { |
| 1151 | + auto mid = std::make_shared<middle_pgsql_t>(&options); |
| 1152 | + mid->start(); |
| 1153 | + |
| 1154 | + mid->way_delete(20); |
| 1155 | + mid->way_set(way20a); |
| 1156 | + mid->flush(); |
| 1157 | + |
| 1158 | + check_way(mid, way20a); |
| 1159 | + check_way_nodes(mid, way20.id(), {&node11, &node12}); |
| 1160 | + |
| 1161 | + mid->commit(); |
| 1162 | + } |
| 1163 | + |
| 1164 | + { |
| 1165 | + auto mid = std::make_shared<middle_pgsql_t>(&options); |
| 1166 | + mid->start(); |
| 1167 | + |
| 1168 | + mid->node_delete(10); |
| 1169 | + mid->node_set(node10a); |
| 1170 | + mid->node_changed(10); |
| 1171 | + mid->flush(); |
| 1172 | + |
| 1173 | + REQUIRE_FALSE(mid->has_pending()); |
| 1174 | + test_pending_processor proc; |
| 1175 | + mid->iterate_ways(proc); |
| 1176 | + proc.check_way_ids_equal_to({}); |
| 1177 | + |
| 1178 | + mid->commit(); |
| 1179 | + } |
| 1180 | + } |
| 1181 | +} |
0 commit comments