osrm-backend/test/t/io/test_reader_with_mock_decompression.cpp
Patrick Niklaus 6eb4f090f9 Squashed 'third_party/libosmium/' content from commit ce865381f
git-subtree-dir: third_party/libosmium
git-subtree-split: ce865381fb752323ff1e66181f5a49b7f500ffa3
2017-08-30 09:30:27 +00:00

146 lines
4.0 KiB
C++

#include "catch.hpp"
#include "utils.hpp"
#include <string>
#include <osmium/io/compression.hpp>
#include <osmium/io/xml_input.hpp>
// The MockDecompressor behaves like other Decompressor classes, but "invents"
// OSM data in XML format that can be read. Through a parameter to the
// constructor it can be instructed to throw an exception in specific parts
// of its code. This is then used to test the internals of the Reader.
class MockDecompressor : public osmium::io::Decompressor {
std::string m_fail_in;
int m_read_count = 0;
public:
explicit MockDecompressor(const std::string& fail_in) :
Decompressor(),
m_fail_in(fail_in) {
if (m_fail_in == "constructor") {
throw std::runtime_error{"error constructor"};
}
}
~MockDecompressor() noexcept final = default;
void add_node(std::string& s, int i) {
s += "<node id='";
s += std::to_string(i);
s += "' version='1' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' changeset='1' lon='1.02' lat='1.02'/>\n";
}
std::string read() final {
std::string buffer;
++m_read_count;
if (m_read_count == 1) {
if (m_fail_in == "first read") {
throw std::runtime_error{"error first read"};
} else {
buffer += "<?xml version='1.0' encoding='UTF-8'?>\n<osm version='0.6' generator='testdata'>\n";
for (int i = 0; i < 1000; ++i) {
add_node(buffer, i);
}
}
} else if (m_read_count == 2) {
if (m_fail_in == "second read") {
throw std::runtime_error{"error second read"};
} else {
for (int i = 1000; i < 2000; ++i) {
add_node(buffer, i);
}
}
} else if (m_read_count == 3) {
buffer += "</osm>";
}
return buffer;
}
void close() final {
if (m_fail_in == "close") {
throw std::runtime_error{"error close"};
}
}
}; // class MockDecompressor
TEST_CASE("Test Reader using MockDecompressor") {
std::string fail_in;
osmium::io::CompressionFactory::instance().register_compression(osmium::io::file_compression::gzip,
[](int, osmium::io::fsync) { return nullptr; },
[&](int) { return new MockDecompressor(fail_in); },
[](const char*, size_t) { return nullptr; }
);
SECTION("fail in constructor") {
fail_in = "constructor";
try {
osmium::io::Reader reader{with_data_dir("t/io/data.osm.gz")};
REQUIRE(false);
} catch (const std::runtime_error& e) {
REQUIRE(std::string{e.what()} == "error constructor");
}
}
SECTION("fail in first read") {
fail_in = "first read";
try {
osmium::io::Reader reader{with_data_dir("t/io/data.osm.gz")};
reader.read();
REQUIRE(false);
} catch (const std::runtime_error& e) {
REQUIRE(std::string{e.what()} == "error first read");
}
}
SECTION("fail in second read") {
fail_in = "second read";
try {
osmium::io::Reader reader{with_data_dir("t/io/data.osm.gz")};
reader.read();
reader.read();
REQUIRE(false);
} catch (const std::runtime_error& e) {
REQUIRE(std::string{e.what()} == "error second read");
}
}
SECTION("fail in close") {
fail_in = "close";
try {
osmium::io::Reader reader{with_data_dir("t/io/data.osm.gz")};
reader.read();
reader.read();
reader.read();
reader.close();
REQUIRE(false);
} catch (const std::runtime_error& e) {
REQUIRE(std::string{e.what()} == "error close");
}
}
SECTION("not failing") {
fail_in = "not";
osmium::io::Reader reader{with_data_dir("t/io/data.osm.gz")};
reader.read();
reader.close();
REQUIRE(true);
}
}