File: test_reader_with_mock_decompression.cpp

package info (click to toggle)
libosmium 2.23.0-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,564 kB
  • sloc: cpp: 53,570; sh: 148; makefile: 19
file content (152 lines) | stat: -rw-r--r-- 4,463 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include "catch.hpp"

#include "utils.hpp"

#include <osmium/io/compression.hpp>
#include <osmium/io/xml_input.hpp>

#include <stdexcept>
#include <string>
#include <utility>

// 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 final : public osmium::io::Decompressor {

    std::string m_fail_in;
    int m_read_count = 0;

public:

    explicit MockDecompressor(std::string fail_in) :
        m_fail_in(std::move(fail_in)) {
        if (m_fail_in == "constructor") {
            throw std::runtime_error{"error constructor"};
        }
    }

    MockDecompressor(const MockDecompressor&) = delete;
    MockDecompressor& operator=(const MockDecompressor&) = delete;

    MockDecompressor(MockDecompressor&&) = delete;
    MockDecompressor& operator=(MockDecompressor&&) = delete;

    ~MockDecompressor() noexcept override = default;

    static 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() override {
        std::string buffer;
        ++m_read_count;

        if (m_read_count == 1) {
            if (m_fail_in == "first read") {
                throw std::runtime_error{"error first read"};
            }
            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"};
            }
            for (int i = 1000; i < 2000; ++i) {
                add_node(buffer, i);
            }
        } else if (m_read_count == 3) {
            buffer += "</osm>";
        }

        return buffer;
    }

    void close() override {
        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().clear_register();

    osmium::io::CompressionFactory::instance().register_compression(osmium::io::file_compression::gzip,
        [](int /*unused*/, osmium::io::fsync /*unused*/) { return nullptr; },
        [&](int /*unused*/) { return new MockDecompressor(fail_in); },
        [](const char* /*unused*/, size_t /*unused*/) { return nullptr; }
    );

    SECTION("fail in constructor") {
        fail_in = "constructor";

        try {
            const 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);
    }

}