1 #include "catch.hpp"
2 
3 #include <osmium/index/detail/tmpfile.hpp>
4 #include <osmium/index/map/dense_file_array.hpp>
5 #include <osmium/index/map/sparse_mem_array.hpp>
6 #include <osmium/index/map/sparse_mmap_array.hpp>
7 #include <osmium/index/node_locations_map.hpp>
8 #include <osmium/osm/node_ref.hpp>
9 #include <osmium/osm/types.hpp>
10 #include <osmium/util/file.hpp>
11 
12 #include <vector>
13 
14 using dense_file_array = osmium::index::map::DenseFileArray<osmium::unsigned_object_id_type, osmium::Location>;
15 
16 template <class TSparseIndex>
test_index()17 void test_index() {
18     const int fd = osmium::detail::create_tmp_file();
19     constexpr const size_t value_size = sizeof(typename TSparseIndex::element_type::second_type);
20     constexpr const size_t buffer_size = (10L * 1024L * 1024L) / value_size;
21 
22     REQUIRE(osmium::file_size(fd) == 0);
23 
24     std::vector<osmium::NodeRef> refs = {
25         osmium::NodeRef{1,                   osmium::Location{1.2, 4.5}},
26         osmium::NodeRef{6,                   osmium::Location{3.5, -7.2}},
27         osmium::NodeRef{2 * buffer_size,     osmium::Location{10.2, 64.5}},
28         osmium::NodeRef{2 * buffer_size + 1, osmium::Location{39.5, -71.2}},
29         osmium::NodeRef{3 * buffer_size - 1, osmium::Location{-1.2, 54.6}},
30         osmium::NodeRef{3 * buffer_size,     osmium::Location{-171.2, 9.3}},
31         osmium::NodeRef{3 * buffer_size + 1, osmium::Location{-171.21, 9.26}},
32         osmium::NodeRef{3 * buffer_size + 2, osmium::Location{-171.22, 9.25}},
33         osmium::NodeRef{3 * buffer_size + 3, osmium::Location{-171.24, 9.23}},
34         osmium::NodeRef{3 * buffer_size + 4, osmium::Location{-171.25, 9.22}},
35         osmium::NodeRef{3 * buffer_size + 5, osmium::Location{-171.26, 9.21}}
36     };
37 
38     TSparseIndex sparse_index;
39     for (const auto& r : refs) {
40         sparse_index.set(r.ref(), r.location());
41     }
42     sparse_index.sort();
43     sparse_index.dump_as_array(fd);
44 
45     dense_file_array dense_index{fd};
46     const auto max_id_in_refs = std::max_element(refs.begin(), refs.end())->ref();
47 
48     // Array index should be as large as necessary.
49     REQUIRE(osmium::file_size(fd) >= max_id_in_refs * sizeof(osmium::Location));
50 
51     // check beyond largest ID
52     REQUIRE_THROWS_AS(dense_index.get(max_id_in_refs + 1), osmium::not_found);
53 
54     // check if written values can be retrieved
55     for (const auto& r : refs) {
56         REQUIRE(dense_index.get(r.ref()) == r.location());
57     }
58 
59     // check if all other values are invalid locations
60     size_t invalid_count = 0;
61     for (osmium::object_id_type id = 0; id <= max_id_in_refs; ++id) {
62         if (!dense_index.get_noexcept(id).valid()) {
63             ++invalid_count;
64         }
65     }
66     REQUIRE(invalid_count == max_id_in_refs - refs.size() + 1);
67 }
68 
69 
70 #ifdef __linux__
71 using sparse_mmap_array = osmium::index::map::SparseMmapArray<osmium::unsigned_object_id_type, osmium::Location>;
72 
73 TEST_CASE("Dump SparseMmapArray as array and load it as DenseFileArray") {
74     test_index<sparse_mmap_array>();
75 }
76 #else
77 # pragma message("not running 'SparseMmapArray' test case on this machine")
78 #endif
79 
80 using sparse_mem_array = osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, osmium::Location>;
81 
82 TEST_CASE("Dump SparseMemArray as array and load it as DenseFileArray") {
83     test_index<sparse_mem_array>();
84 }
85 
86