/* The code in this file is released into the Public Domain. */ #define CATCH_CONFIG_MAIN #include "catch.hpp" #include #include #include #include #include #include #include std::string filename(const char* test_id, const char* suffix = "osm") { const char* testdir = getenv("TESTDIR"); if (!testdir) { std::cerr << "You have to set TESTDIR environment variable before running testdata-xml\n"; exit(2); } std::string f; f += testdir; f += "/"; f += test_id; f += "/data."; f += suffix; return f; } struct header_buffer_type { osmium::io::Header header; osmium::memory::Buffer buffer; }; // ============================================= // The following helper functions are used to call different parts of the // Osmium internals used to read and parse XML files. This way those parts // can be tested individually. These function can not be used in normal // operations, because they make certain assumptions, for instance that // file contents fit into small buffers. std::string read_file(const char* test_id) { int fd = osmium::io::detail::open_for_reading(filename(test_id)); assert(fd >= 0); std::string input(10000, '\0'); ssize_t n = ::read(fd, reinterpret_cast(const_cast(input.data())), 10000); assert(n >= 0); input.resize(static_cast(n)); close(fd); return input; } std::string read_gz_file(const char* test_id, const char* suffix) { int fd = osmium::io::detail::open_for_reading(filename(test_id, suffix)); assert(fd >= 0); osmium::io::GzipDecompressor gzip_decompressor(fd); std::string input = gzip_decompressor.read(); gzip_decompressor.close(); return input; } header_buffer_type parse_xml(std::string input) { osmium::thread::Queue input_queue; osmium::thread::Queue output_queue; std::promise header_promise; std::atomic done {false}; input_queue.push(input); input_queue.push(std::string()); // EOF marker osmium::io::detail::XMLParser parser(input_queue, output_queue, header_promise, osmium::osm_entity_bits::all, done); parser(); header_buffer_type result; result.header = header_promise.get_future().get(); output_queue.wait_and_pop(result.buffer); if (result.buffer) { osmium::memory::Buffer buffer; output_queue.wait_and_pop(buffer); assert(!buffer); } return result; } header_buffer_type read_xml(const char* test_id) { std::string input = read_file(test_id); return parse_xml(input); } // ============================================= TEST_CASE("Reading OSM XML 100") { SECTION("Direct") { header_buffer_type r = read_xml("100-correct_but_no_data"); REQUIRE(r.header.get("generator") == "testdata"); REQUIRE(0 == r.buffer.committed()); REQUIRE(! r.buffer); } SECTION("Using Reader") { osmium::io::Reader reader(filename("100-correct_but_no_data")); osmium::io::Header header = reader.header(); REQUIRE(header.get("generator") == "testdata"); osmium::memory::Buffer buffer = reader.read(); REQUIRE(0 == buffer.committed()); REQUIRE(! buffer); reader.close(); } SECTION("Using Reader asking for header only") { osmium::io::Reader reader(filename("100-correct_but_no_data"), osmium::osm_entity_bits::nothing); osmium::io::Header header = reader.header(); REQUIRE(header.get("generator") == "testdata"); reader.close(); } } // ============================================= TEST_CASE("Reading OSM XML 101") { SECTION("Direct") { REQUIRE_THROWS_AS(read_xml("101-missing_version"), osmium::format_version_error); try { read_xml("101-missing_version"); } catch (osmium::format_version_error& e) { REQUIRE(e.version.empty()); } } SECTION("Using Reader") { REQUIRE_THROWS_AS({ osmium::io::Reader reader(filename("101-missing_version")); osmium::io::Header header = reader.header(); osmium::memory::Buffer buffer = reader.read(); reader.close(); }, osmium::format_version_error); } } // ============================================= TEST_CASE("Reading OSM XML 102") { SECTION("Direct") { REQUIRE_THROWS_AS(read_xml("102-wrong_version"), osmium::format_version_error); try { read_xml("102-wrong_version"); } catch (osmium::format_version_error& e) { REQUIRE(e.version == "0.1"); } } SECTION("Using Reader") { REQUIRE_THROWS_AS({ osmium::io::Reader reader(filename("102-wrong_version")); osmium::io::Header header = reader.header(); osmium::memory::Buffer buffer = reader.read(); reader.close(); }, osmium::format_version_error); } } // ============================================= TEST_CASE("Reading OSM XML 103") { SECTION("Direct") { REQUIRE_THROWS_AS(read_xml("103-old_version"), osmium::format_version_error); try { read_xml("103-old_version"); } catch (osmium::format_version_error& e) { REQUIRE(e.version == "0.5"); } } SECTION("Using Reader") { REQUIRE_THROWS_AS({ osmium::io::Reader reader(filename("103-old_version")); osmium::io::Header header = reader.header(); osmium::memory::Buffer buffer = reader.read(); reader.close(); }, osmium::format_version_error); } } // ============================================= TEST_CASE("Reading OSM XML 104") { SECTION("Direct") { REQUIRE_THROWS_AS(read_xml("104-empty_file"), osmium::xml_error); try { read_xml("104-empty_file"); } catch (osmium::xml_error& e) { REQUIRE(e.line == 1); REQUIRE(e.column == 0); } } SECTION("Using Reader") { REQUIRE_THROWS_AS({ osmium::io::Reader reader(filename("104-empty_file")); osmium::io::Header header = reader.header(); osmium::memory::Buffer buffer = reader.read(); reader.close(); }, osmium::xml_error); } } // ============================================= TEST_CASE("Reading OSM XML 105") { SECTION("Direct") { REQUIRE_THROWS_AS(read_xml("105-incomplete_xml_file"), osmium::xml_error); } SECTION("Using Reader") { REQUIRE_THROWS_AS({ osmium::io::Reader reader(filename("105-incomplete_xml_file")); osmium::io::Header header = reader.header(); osmium::memory::Buffer buffer = reader.read(); reader.close(); }, osmium::xml_error); } } // ============================================= TEST_CASE("Reading OSM XML 120") { SECTION("Direct") { std::string data = read_gz_file("120-correct_gzip_file_without_data", "osm.gz"); REQUIRE(data.size() == 102); header_buffer_type r = parse_xml(data); REQUIRE(r.header.get("generator") == "testdata"); REQUIRE(0 == r.buffer.committed()); REQUIRE(! r.buffer); } SECTION("Using Reader") { osmium::io::Reader reader(filename("120-correct_gzip_file_without_data", "osm.gz")); osmium::io::Header header = reader.header(); REQUIRE(header.get("generator") == "testdata"); osmium::memory::Buffer buffer = reader.read(); REQUIRE(0 == buffer.committed()); REQUIRE(! buffer); reader.close(); } } // ============================================= TEST_CASE("Reading OSM XML 121") { SECTION("Direct") { REQUIRE_THROWS_AS( { read_gz_file("121-truncated_gzip_file", "osm.gz"); }, osmium::gzip_error); } #if 0 SECTION("Using Reader") { REQUIRE_THROWS_AS({ osmium::io::Reader reader(filename("121-truncated_gzip_file", "osm.gz")); osmium::io::Header header = reader.header(); osmium::memory::Buffer buffer = reader.read(); reader.close(); }, osmium::gzip_error); } #endif } // ============================================= TEST_CASE("Reading OSM XML 200") { SECTION("Direct") { header_buffer_type r = read_xml("200-nodes"); REQUIRE(r.header.get("generator") == "testdata"); REQUIRE(r.buffer.committed() > 0); REQUIRE(r.buffer.get(0).type() == osmium::item_type::node); REQUIRE(r.buffer.get(0).id() == 36966060); REQUIRE(std::distance(r.buffer.begin(), r.buffer.end()) == 3); } SECTION("Using Reader") { osmium::io::Reader reader(filename("200-nodes")); osmium::io::Header header = reader.header(); REQUIRE(header.get("generator") == "testdata"); osmium::memory::Buffer buffer = reader.read(); REQUIRE(buffer.committed() > 0); REQUIRE(buffer.get(0).type() == osmium::item_type::node); REQUIRE(buffer.get(0).id() == 36966060); REQUIRE(std::distance(buffer.begin(), buffer.end()) == 3); reader.close(); } SECTION("Using Reader asking for nodes") { osmium::io::Reader reader(filename("200-nodes"), osmium::osm_entity_bits::node); osmium::io::Header header = reader.header(); REQUIRE(header.get("generator") == "testdata"); osmium::memory::Buffer buffer = reader.read(); REQUIRE(buffer.committed() > 0); REQUIRE(buffer.get(0).type() == osmium::item_type::node); REQUIRE(buffer.get(0).id() == 36966060); REQUIRE(std::distance(buffer.begin(), buffer.end()) == 3); reader.close(); } SECTION("Using Reader asking for header only") { osmium::io::Reader reader(filename("200-nodes"), osmium::osm_entity_bits::nothing); osmium::io::Header header = reader.header(); REQUIRE(header.get("generator") == "testdata"); osmium::memory::Buffer buffer = reader.read(); REQUIRE(0 == buffer.committed()); REQUIRE(! buffer); reader.close(); } SECTION("Using Reader asking for ways") { osmium::io::Reader reader(filename("200-nodes"), osmium::osm_entity_bits::way); osmium::io::Header header = reader.header(); REQUIRE(header.get("generator") == "testdata"); osmium::memory::Buffer buffer = reader.read(); REQUIRE(0 == buffer.committed()); REQUIRE(! buffer); reader.close(); } }