1076 lines
34 KiB
C++
1076 lines
34 KiB
C++
|
|
||
|
#include <algorithm>
|
||
|
#include <cstring>
|
||
|
|
||
|
#include "catch.hpp"
|
||
|
|
||
|
#include <osmium/io/detail/opl_input_format.hpp>
|
||
|
#include <osmium/opl.hpp>
|
||
|
|
||
|
namespace oid = osmium::io::detail;
|
||
|
|
||
|
TEST_CASE("Parse OPL: base exception") {
|
||
|
osmium::opl_error e{"foo"};
|
||
|
REQUIRE(e.data == nullptr);
|
||
|
REQUIRE(e.line == 0);
|
||
|
REQUIRE(e.column == 0);
|
||
|
REQUIRE(e.msg == "OPL error: foo");
|
||
|
REQUIRE(std::string{e.what()} == "OPL error: foo");
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse OPL: exception with line and column") {
|
||
|
const char* d = "data";
|
||
|
osmium::opl_error e{"bar", d};
|
||
|
e.set_pos(17, 23);
|
||
|
REQUIRE(e.data == d);
|
||
|
REQUIRE(e.line == 17);
|
||
|
REQUIRE(e.column == 23);
|
||
|
REQUIRE(e.msg == "OPL error: bar on line 17 column 23");
|
||
|
REQUIRE(std::string{e.what()} == "OPL error: bar on line 17 column 23");
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse OPL: space") {
|
||
|
std::string d{"a b \t c"};
|
||
|
|
||
|
const char* s = d.data();
|
||
|
REQUIRE_THROWS_AS({
|
||
|
oid::opl_parse_space(&s);
|
||
|
}, osmium::opl_error);
|
||
|
|
||
|
s = d.data() + 1;
|
||
|
oid::opl_parse_space(&s);
|
||
|
REQUIRE(*s == 'b');
|
||
|
|
||
|
REQUIRE_THROWS_AS({
|
||
|
oid::opl_parse_space(&s);
|
||
|
}, osmium::opl_error);
|
||
|
|
||
|
++s;
|
||
|
oid::opl_parse_space(&s);
|
||
|
REQUIRE(*s == 'c');
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse OPL: check for space") {
|
||
|
REQUIRE(oid::opl_non_empty("aaa"));
|
||
|
REQUIRE(oid::opl_non_empty("a b"));
|
||
|
REQUIRE_FALSE(oid::opl_non_empty(" "));
|
||
|
REQUIRE_FALSE(oid::opl_non_empty(" x"));
|
||
|
REQUIRE_FALSE(oid::opl_non_empty("\tx"));
|
||
|
REQUIRE_FALSE(oid::opl_non_empty(""));
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse OPL: skip section") {
|
||
|
std::string d{"abcd efgh"};
|
||
|
const char* skip1 = d.data() + 4;
|
||
|
const char* skip2 = d.data() + 9;
|
||
|
const char* s = d.data();
|
||
|
REQUIRE(oid::opl_skip_section(&s) == skip1);
|
||
|
REQUIRE(s == skip1);
|
||
|
++s;
|
||
|
REQUIRE(oid::opl_skip_section(&s) == skip2);
|
||
|
REQUIRE(s == skip2);
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse OPL: parse escaped") {
|
||
|
std::string result;
|
||
|
|
||
|
SECTION("Empty string") {
|
||
|
const char* s = "";
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
oid::opl_parse_escaped(&s, result);
|
||
|
}, "OPL error: eol");
|
||
|
}
|
||
|
|
||
|
SECTION("Illegal character for hex") {
|
||
|
const char* s = "x";
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
oid::opl_parse_escaped(&s, result);
|
||
|
}, "OPL error: not a hex char");
|
||
|
}
|
||
|
|
||
|
SECTION("Illegal character for hex after legal hex characters") {
|
||
|
const char* s = "0123x";
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
oid::opl_parse_escaped(&s, result);
|
||
|
}, "OPL error: not a hex char");
|
||
|
}
|
||
|
|
||
|
SECTION("Too long") {
|
||
|
const char* s = "123456780";
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
oid::opl_parse_escaped(&s, result);
|
||
|
}, "OPL error: hex escape too long");
|
||
|
}
|
||
|
|
||
|
SECTION("No data") {
|
||
|
const char* s = "%";
|
||
|
const char* e = s + std::strlen(s);
|
||
|
oid::opl_parse_escaped(&s, result);
|
||
|
REQUIRE(result.size() == 1);
|
||
|
REQUIRE(result[0] == '\0');
|
||
|
REQUIRE(s == e);
|
||
|
}
|
||
|
|
||
|
SECTION("One hex char") {
|
||
|
const char* s = "9%";
|
||
|
const char* e = s + std::strlen(s);
|
||
|
oid::opl_parse_escaped(&s, result);
|
||
|
REQUIRE(result.size() == 1);
|
||
|
REQUIRE(result == "\t");
|
||
|
REQUIRE(s == e);
|
||
|
}
|
||
|
|
||
|
SECTION("Two hex chars (lowercase)") {
|
||
|
const char* s = "3c%";
|
||
|
const char* e = s + std::strlen(s);
|
||
|
oid::opl_parse_escaped(&s, result);
|
||
|
REQUIRE(result.size() == 1);
|
||
|
REQUIRE(result == "<");
|
||
|
REQUIRE(s == e);
|
||
|
}
|
||
|
|
||
|
SECTION("Two hex char (uppercase)") {
|
||
|
const char* s = "3C%";
|
||
|
const char* e = s + std::strlen(s);
|
||
|
oid::opl_parse_escaped(&s, result);
|
||
|
REQUIRE(result.size() == 1);
|
||
|
REQUIRE(result == "<");
|
||
|
REQUIRE(s == e);
|
||
|
}
|
||
|
|
||
|
SECTION("Longer unicode characters") {
|
||
|
const char* s1 = "30dc%";
|
||
|
oid::opl_parse_escaped(&s1, result);
|
||
|
result.append("_");
|
||
|
const char* s2 = "1d11e%";
|
||
|
oid::opl_parse_escaped(&s2, result);
|
||
|
result.append("_");
|
||
|
const char* s3 = "1f6eb%";
|
||
|
oid::opl_parse_escaped(&s3, result);
|
||
|
REQUIRE(result == u8"\u30dc_\U0001d11e_\U0001f6eb");
|
||
|
}
|
||
|
|
||
|
SECTION("Data after %") {
|
||
|
const char* s = "5a%abc";
|
||
|
oid::opl_parse_escaped(&s, result);
|
||
|
REQUIRE(result.size() == 1);
|
||
|
REQUIRE(result == "Z");
|
||
|
REQUIRE(std::string{s} == "abc");
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse OPL: parse string") {
|
||
|
std::string result;
|
||
|
|
||
|
SECTION("empty string") {
|
||
|
const char* s = "";
|
||
|
const char* e = s + std::strlen(s);
|
||
|
oid::opl_parse_string(&s, result);
|
||
|
REQUIRE(result.size() == 0);
|
||
|
REQUIRE(result == "");
|
||
|
REQUIRE(s == e);
|
||
|
}
|
||
|
|
||
|
SECTION("normal string") {
|
||
|
const char* s = "foo";
|
||
|
const char* e = s + std::strlen(s);
|
||
|
oid::opl_parse_string(&s, result);
|
||
|
REQUIRE(result.size() == 3);
|
||
|
REQUIRE(result == "foo");
|
||
|
REQUIRE(s == e);
|
||
|
}
|
||
|
|
||
|
SECTION("string with space") {
|
||
|
const char* s = "foo bar";
|
||
|
const char* e = s + 3;
|
||
|
oid::opl_parse_string(&s, result);
|
||
|
REQUIRE(result.size() == 3);
|
||
|
REQUIRE(result == "foo");
|
||
|
REQUIRE(s == e);
|
||
|
}
|
||
|
|
||
|
SECTION("string with tab") {
|
||
|
const char* s = "foo\tbar";
|
||
|
const char* e = s + 3;
|
||
|
oid::opl_parse_string(&s, result);
|
||
|
REQUIRE(result.size() == 3);
|
||
|
REQUIRE(result == "foo");
|
||
|
REQUIRE(s == e);
|
||
|
}
|
||
|
|
||
|
SECTION("string with comma") {
|
||
|
const char* s = "foo,bar";
|
||
|
const char* e = s + 3;
|
||
|
oid::opl_parse_string(&s, result);
|
||
|
REQUIRE(result.size() == 3);
|
||
|
REQUIRE(result == "foo");
|
||
|
REQUIRE(s == e);
|
||
|
}
|
||
|
|
||
|
SECTION("string with equal sign") {
|
||
|
const char* s = "foo=bar";
|
||
|
const char* e = s + 3;
|
||
|
oid::opl_parse_string(&s, result);
|
||
|
REQUIRE(result.size() == 3);
|
||
|
REQUIRE(result == "foo");
|
||
|
REQUIRE(s == e);
|
||
|
}
|
||
|
|
||
|
SECTION("string with escaped characters") {
|
||
|
const char* s = "foo%3d%bar";
|
||
|
const char* e = s + std::strlen(s);
|
||
|
oid::opl_parse_string(&s, result);
|
||
|
REQUIRE(result.size() == 7);
|
||
|
REQUIRE(result == "foo=bar");
|
||
|
REQUIRE(s == e);
|
||
|
}
|
||
|
|
||
|
SECTION("string with escaped characters at end") {
|
||
|
const char* s = "foo%3d%";
|
||
|
const char* e = s + std::strlen(s);
|
||
|
oid::opl_parse_string(&s, result);
|
||
|
REQUIRE(result.size() == 4);
|
||
|
REQUIRE(result == "foo=");
|
||
|
REQUIRE(s == e);
|
||
|
}
|
||
|
|
||
|
SECTION("string with invalid escaping") {
|
||
|
const char* s = "foo%";
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
oid::opl_parse_string(&s, result);
|
||
|
}, "OPL error: eol");
|
||
|
}
|
||
|
|
||
|
SECTION("string with invalid escaped characters") {
|
||
|
const char* s = "foo%x%";
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
oid::opl_parse_string(&s, result);
|
||
|
}, "OPL error: not a hex char");
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
template <typename T = int64_t>
|
||
|
T test_parse_int(const char* s) {
|
||
|
auto r = oid::opl_parse_int<T>(&s);
|
||
|
REQUIRE(*s == 'x');
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse OPL: integer") {
|
||
|
REQUIRE(test_parse_int("0x") == 0);
|
||
|
REQUIRE(test_parse_int("-0x") == 0);
|
||
|
REQUIRE(test_parse_int("1x") == 1);
|
||
|
REQUIRE(test_parse_int("17x") == 17);
|
||
|
REQUIRE(test_parse_int("-1x") == -1);
|
||
|
REQUIRE(test_parse_int("1234567890123x") == 1234567890123);
|
||
|
REQUIRE(test_parse_int("-1234567890123x") == -1234567890123);
|
||
|
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
test_parse_int("");
|
||
|
}, "OPL error: expected integer");
|
||
|
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
test_parse_int("-x");
|
||
|
}, "OPL error: expected integer");
|
||
|
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
test_parse_int(" 1");
|
||
|
}, "OPL error: expected integer");
|
||
|
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
test_parse_int("x");
|
||
|
}, "OPL error: expected integer");
|
||
|
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
test_parse_int("99999999999999999999999x");
|
||
|
}, "OPL error: integer too long");
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse OPL: int32_t") {
|
||
|
REQUIRE(test_parse_int<int32_t>("0x") == 0);
|
||
|
REQUIRE(test_parse_int<int32_t>("123x") == 123);
|
||
|
REQUIRE(test_parse_int<int32_t>("-123x") == -123);
|
||
|
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
test_parse_int<int32_t>("12345678901x");
|
||
|
}, "OPL error: integer too long");
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
test_parse_int<int32_t>("-12345678901x");
|
||
|
}, "OPL error: integer too long");
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse OPL: uint32_t") {
|
||
|
REQUIRE(test_parse_int<uint32_t>("0x") == 0);
|
||
|
REQUIRE(test_parse_int<uint32_t>("123x") == 123);
|
||
|
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
test_parse_int<uint32_t>("-123x");
|
||
|
}, "OPL error: integer too long");
|
||
|
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
test_parse_int<uint32_t>("12345678901x");
|
||
|
}, "OPL error: integer too long");
|
||
|
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
test_parse_int<uint32_t>("-12345678901x");
|
||
|
}, "OPL error: integer too long");
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse OPL: visible flag") {
|
||
|
const char* data = "V";
|
||
|
const char* e = data + std::strlen(data);
|
||
|
REQUIRE(oid::opl_parse_visible(&data));
|
||
|
REQUIRE(e == data);
|
||
|
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse OPL: deleted flag") {
|
||
|
const char* data = "D";
|
||
|
const char* e = data + std::strlen(data);
|
||
|
REQUIRE_FALSE(oid::opl_parse_visible(&data));
|
||
|
REQUIRE(e == data);
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse OPL: invalid visible flag") {
|
||
|
const char* data = "x";
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
oid::opl_parse_visible(&data);
|
||
|
}, "OPL error: invalid visible flag");
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse OPL: timestamp (empty)") {
|
||
|
const char* data = "";
|
||
|
const char* e = data + std::strlen(data);
|
||
|
REQUIRE(oid::opl_parse_timestamp(&data) == osmium::Timestamp{});
|
||
|
REQUIRE(e == data);
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse OPL: timestamp (space)") {
|
||
|
const char* data = " ";
|
||
|
const char* e = data;
|
||
|
REQUIRE(oid::opl_parse_timestamp(&data) == osmium::Timestamp{});
|
||
|
REQUIRE(e == data);
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse OPL: timestamp (tab)") {
|
||
|
const char* data = "\t";
|
||
|
const char* e = data;
|
||
|
REQUIRE(oid::opl_parse_timestamp(&data) == osmium::Timestamp{});
|
||
|
REQUIRE(e == data);
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse OPL: timestamp (invalid)") {
|
||
|
const char* data = "abc";
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
oid::opl_parse_timestamp(&data);
|
||
|
}, "OPL error: can not parse timestamp");
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse OPL: timestamp (valid)") {
|
||
|
const char* data = "2016-03-04T17:28:03Z";
|
||
|
const char* e = data + std::strlen(data);
|
||
|
REQUIRE(oid::opl_parse_timestamp(&data) == osmium::Timestamp{"2016-03-04T17:28:03Z"});
|
||
|
REQUIRE(e == data);
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse OPL: valid timestamp with trailing data") {
|
||
|
const char* data = "2016-03-04T17:28:03Zxxx";
|
||
|
REQUIRE(oid::opl_parse_timestamp(&data) == osmium::Timestamp{"2016-03-04T17:28:03Z"});
|
||
|
REQUIRE(std::string{data} == "xxx");
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse OPL: tags") {
|
||
|
osmium::memory::Buffer buffer{1024};
|
||
|
|
||
|
SECTION("Empty") {
|
||
|
const char* data = "";
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
oid::opl_parse_tags(data, buffer);
|
||
|
}, "OPL error: expected '='");
|
||
|
}
|
||
|
|
||
|
SECTION("One tag") {
|
||
|
const char* data = "foo=bar";
|
||
|
oid::opl_parse_tags(data, buffer);
|
||
|
const auto& taglist = buffer.get<osmium::TagList>(0);
|
||
|
REQUIRE(taglist.size() == 1);
|
||
|
REQUIRE(std::string{taglist.begin()->key()} == "foo");
|
||
|
REQUIRE(std::string{taglist.begin()->value()} == "bar");
|
||
|
}
|
||
|
|
||
|
SECTION("Empty key and value are allowed") {
|
||
|
const char* data = "=";
|
||
|
oid::opl_parse_tags(data, buffer);
|
||
|
const auto& taglist = buffer.get<osmium::TagList>(0);
|
||
|
REQUIRE(taglist.size() == 1);
|
||
|
REQUIRE(std::string{taglist.begin()->key()} == "");
|
||
|
REQUIRE(std::string{taglist.begin()->value()} == "");
|
||
|
}
|
||
|
|
||
|
SECTION("Multiple tags") {
|
||
|
const char* data = "highway=residential,oneway=yes,maxspeed=30";
|
||
|
oid::opl_parse_tags(data, buffer);
|
||
|
const auto& taglist = buffer.get<osmium::TagList>(0);
|
||
|
REQUIRE(taglist.size() == 3);
|
||
|
auto it = taglist.cbegin();
|
||
|
REQUIRE(std::string{it->key()} == "highway");
|
||
|
REQUIRE(std::string{it->value()} == "residential");
|
||
|
++it;
|
||
|
REQUIRE(std::string{it->key()} == "oneway");
|
||
|
REQUIRE(std::string{it->value()} == "yes");
|
||
|
++it;
|
||
|
REQUIRE(std::string{it->key()} == "maxspeed");
|
||
|
REQUIRE(std::string{it->value()} == "30");
|
||
|
++it;
|
||
|
REQUIRE(it == taglist.cend());
|
||
|
}
|
||
|
|
||
|
SECTION("No equal signs") {
|
||
|
const char* data = "a";
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
oid::opl_parse_tags(data, buffer);
|
||
|
}, "OPL error: expected '='");
|
||
|
}
|
||
|
|
||
|
SECTION("Two equal signs") {
|
||
|
const char* data = "a=b=c";
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
oid::opl_parse_tags(data, buffer);
|
||
|
}, "OPL error: expected ','");
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse OPL: nodes") {
|
||
|
osmium::memory::Buffer buffer{1024};
|
||
|
|
||
|
SECTION("Empty") {
|
||
|
const char* const s = "";
|
||
|
oid::opl_parse_way_nodes(s, s + std::strlen(s), buffer);
|
||
|
REQUIRE(buffer.written() == 0);
|
||
|
}
|
||
|
|
||
|
SECTION("Invalid format, missing n") {
|
||
|
const char* const s = "xyz";
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
oid::opl_parse_way_nodes(s, s + std::strlen(s), buffer);
|
||
|
}, "OPL error: expected 'n'");
|
||
|
}
|
||
|
|
||
|
SECTION("Invalid format, missing ID") {
|
||
|
const char* const s = "nx";
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
oid::opl_parse_way_nodes(s, s + std::strlen(s), buffer);
|
||
|
}, "OPL error: expected integer");
|
||
|
}
|
||
|
|
||
|
SECTION("Valid format: one node") {
|
||
|
const char* const s = "n123";
|
||
|
oid::opl_parse_way_nodes(s, s + std::strlen(s), buffer);
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
const auto& wnl = buffer.get<osmium::WayNodeList>(0);
|
||
|
REQUIRE(wnl.size() == 1);
|
||
|
REQUIRE(wnl.begin()->ref() == 123);
|
||
|
}
|
||
|
|
||
|
SECTION("Valid format: two nodes") {
|
||
|
const char* const s = "n123,n456";
|
||
|
oid::opl_parse_way_nodes(s, s + std::strlen(s), buffer);
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
const auto& wnl = buffer.get<osmium::WayNodeList>(0);
|
||
|
REQUIRE(wnl.size() == 2);
|
||
|
auto it = wnl.begin();
|
||
|
REQUIRE(it->ref() == 123);
|
||
|
++it;
|
||
|
REQUIRE(it->ref() == 456);
|
||
|
++it;
|
||
|
REQUIRE(it == wnl.end());
|
||
|
}
|
||
|
|
||
|
SECTION("Trailing comma") {
|
||
|
const char* const s = "n123,n456,";
|
||
|
oid::opl_parse_way_nodes(s, s + std::strlen(s), buffer);
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
const auto& wnl = buffer.get<osmium::WayNodeList>(0);
|
||
|
REQUIRE(wnl.size() == 2);
|
||
|
auto it = wnl.begin();
|
||
|
REQUIRE(it->ref() == 123);
|
||
|
++it;
|
||
|
REQUIRE(it->ref() == 456);
|
||
|
++it;
|
||
|
REQUIRE(it == wnl.end());
|
||
|
}
|
||
|
|
||
|
SECTION("Way nodes with coordinates") {
|
||
|
const char* const s = "n123x1.2y3.4,n456x33y0.1";
|
||
|
oid::opl_parse_way_nodes(s, s + std::strlen(s), buffer);
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
const auto& wnl = buffer.get<osmium::WayNodeList>(0);
|
||
|
REQUIRE(wnl.size() == 2);
|
||
|
auto it = wnl.begin();
|
||
|
REQUIRE(it->ref() == 123);
|
||
|
const osmium::Location loc1{1.2, 3.4};
|
||
|
REQUIRE(it->location() == loc1);
|
||
|
++it;
|
||
|
REQUIRE(it->ref() == 456);
|
||
|
const osmium::Location loc2{33.0, 0.1};
|
||
|
REQUIRE(it->location() == loc2);
|
||
|
++it;
|
||
|
REQUIRE(it == wnl.end());
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse OPL: members") {
|
||
|
osmium::memory::Buffer buffer{1024};
|
||
|
|
||
|
SECTION("Empty") {
|
||
|
const char* const s = "";
|
||
|
oid::opl_parse_relation_members(s, s + std::strlen(s), buffer);
|
||
|
REQUIRE(buffer.written() == 0);
|
||
|
}
|
||
|
|
||
|
SECTION("Invalid: unknown object type") {
|
||
|
const char* const s = "x123@foo";
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
oid::opl_parse_relation_members(s, s + std::strlen(s), buffer);
|
||
|
}, "OPL error: unknown object type");
|
||
|
}
|
||
|
|
||
|
SECTION("Invalid: illegal ref") {
|
||
|
const char* const s = "wx";
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
oid::opl_parse_relation_members(s, s + std::strlen(s), buffer);
|
||
|
}, "OPL error: expected integer");
|
||
|
}
|
||
|
|
||
|
SECTION("Invalid: missing @") {
|
||
|
const char* const s = "n123foo";
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
oid::opl_parse_relation_members(s, s + std::strlen(s), buffer);
|
||
|
}, "OPL error: expected '@'");
|
||
|
}
|
||
|
|
||
|
SECTION("Valid format: one member") {
|
||
|
const char* const s = "n123@foo";
|
||
|
oid::opl_parse_relation_members(s, s + std::strlen(s), buffer);
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
const auto& rml = buffer.get<osmium::RelationMemberList>(0);
|
||
|
REQUIRE(rml.size() == 1);
|
||
|
auto it = rml.begin();
|
||
|
REQUIRE(it->type() == osmium::item_type::node);
|
||
|
REQUIRE(it->ref() == 123);
|
||
|
REQUIRE(std::string{it->role()} == "foo");
|
||
|
++it;
|
||
|
REQUIRE(it == rml.end());
|
||
|
}
|
||
|
|
||
|
SECTION("Valid format: one member without role") {
|
||
|
const char* const s = "n123@";
|
||
|
oid::opl_parse_relation_members(s, s + std::strlen(s), buffer);
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
const auto& rml = buffer.get<osmium::RelationMemberList>(0);
|
||
|
REQUIRE(rml.size() == 1);
|
||
|
auto it = rml.begin();
|
||
|
REQUIRE(it->type() == osmium::item_type::node);
|
||
|
REQUIRE(it->ref() == 123);
|
||
|
REQUIRE(std::string{it->role()} == "");
|
||
|
++it;
|
||
|
REQUIRE(it == rml.end());
|
||
|
}
|
||
|
|
||
|
SECTION("Valid format: three members") {
|
||
|
const char* const s = "n123@,w456@abc,r78@type";
|
||
|
oid::opl_parse_relation_members(s, s + std::strlen(s), buffer);
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
const auto& rml = buffer.get<osmium::RelationMemberList>(0);
|
||
|
REQUIRE(rml.size() == 3);
|
||
|
auto it = rml.begin();
|
||
|
REQUIRE(it->type() == osmium::item_type::node);
|
||
|
REQUIRE(it->ref() == 123);
|
||
|
REQUIRE(std::string{it->role()} == "");
|
||
|
++it;
|
||
|
REQUIRE(it->type() == osmium::item_type::way);
|
||
|
REQUIRE(it->ref() == 456);
|
||
|
REQUIRE(std::string{it->role()} == "abc");
|
||
|
++it;
|
||
|
REQUIRE(it->type() == osmium::item_type::relation);
|
||
|
REQUIRE(it->ref() == 78);
|
||
|
REQUIRE(std::string{it->role()} == "type");
|
||
|
++it;
|
||
|
REQUIRE(it == rml.end());
|
||
|
}
|
||
|
|
||
|
SECTION("Trailing comma") {
|
||
|
const char* const s = "n123@,w456@abc,r78@type,";
|
||
|
oid::opl_parse_relation_members(s, s + std::strlen(s), buffer);
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
const auto& rml = buffer.get<osmium::RelationMemberList>(0);
|
||
|
REQUIRE(rml.size() == 3);
|
||
|
auto it = rml.begin();
|
||
|
REQUIRE(it->type() == osmium::item_type::node);
|
||
|
REQUIRE(it->ref() == 123);
|
||
|
REQUIRE(std::string{it->role()} == "");
|
||
|
++it;
|
||
|
REQUIRE(it->type() == osmium::item_type::way);
|
||
|
REQUIRE(it->ref() == 456);
|
||
|
REQUIRE(std::string{it->role()} == "abc");
|
||
|
++it;
|
||
|
REQUIRE(it->type() == osmium::item_type::relation);
|
||
|
REQUIRE(it->ref() == 78);
|
||
|
REQUIRE(std::string{it->role()} == "type");
|
||
|
++it;
|
||
|
REQUIRE(it == rml.end());
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse node") {
|
||
|
osmium::memory::Buffer buffer{1024};
|
||
|
|
||
|
SECTION("Node with id only") {
|
||
|
const char* s = "17";
|
||
|
const char* e = s + std::strlen(s);
|
||
|
oid::opl_parse_node(&s, buffer);
|
||
|
REQUIRE(s == e);
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
const osmium::Node& node = buffer.get<osmium::Node>(0);
|
||
|
REQUIRE(node.id() == 17);
|
||
|
}
|
||
|
|
||
|
SECTION("Node with trailing space") {
|
||
|
const char* s = "17 ";
|
||
|
const char* e = s + std::strlen(s);
|
||
|
oid::opl_parse_node(&s, buffer);
|
||
|
REQUIRE(s == e);
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
const osmium::Node& node = buffer.get<osmium::Node>(0);
|
||
|
REQUIRE(node.id() == 17);
|
||
|
}
|
||
|
|
||
|
SECTION("Node with id and version") {
|
||
|
const char* s = "17 v23";
|
||
|
const char* e = s + std::strlen(s);
|
||
|
oid::opl_parse_node(&s, buffer);
|
||
|
REQUIRE(s == e);
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
const osmium::Node& node = buffer.get<osmium::Node>(0);
|
||
|
REQUIRE(node.id() == 17);
|
||
|
REQUIRE(node.version() == 23);
|
||
|
}
|
||
|
|
||
|
SECTION("Node with multiple spaces") {
|
||
|
const char* s = "17 v23";
|
||
|
const char* e = s + std::strlen(s);
|
||
|
oid::opl_parse_node(&s, buffer);
|
||
|
REQUIRE(s == e);
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
const osmium::Node& node = buffer.get<osmium::Node>(0);
|
||
|
REQUIRE(node.id() == 17);
|
||
|
REQUIRE(node.version() == 23);
|
||
|
}
|
||
|
|
||
|
SECTION("Node with tab instead of space") {
|
||
|
const char* s = "17\tv23";
|
||
|
const char* e = s + std::strlen(s);
|
||
|
oid::opl_parse_node(&s, buffer);
|
||
|
REQUIRE(s == e);
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
const osmium::Node& node = buffer.get<osmium::Node>(0);
|
||
|
REQUIRE(node.id() == 17);
|
||
|
REQUIRE(node.version() == 23);
|
||
|
}
|
||
|
|
||
|
SECTION("Full node (no tags)") {
|
||
|
const char* s = "125799 v6 dV c7711393 t2011-03-29T21:43:10Z i45445 uUScha T x8.7868047 y53.0749415";
|
||
|
const char* e = s + std::strlen(s);
|
||
|
oid::opl_parse_node(&s, buffer);
|
||
|
REQUIRE(s == e);
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
const osmium::Node& node = buffer.get<osmium::Node>(0);
|
||
|
REQUIRE(node.id() == 125799);
|
||
|
REQUIRE(node.version() == 6);
|
||
|
REQUIRE(node.visible());
|
||
|
REQUIRE(node.changeset() == 7711393);
|
||
|
REQUIRE(node.timestamp() == osmium::Timestamp{"2011-03-29T21:43:10Z"});
|
||
|
REQUIRE(node.uid() == 45445);
|
||
|
REQUIRE(std::string{node.user()} == "UScha");
|
||
|
osmium::Location loc{8.7868047, 53.0749415};
|
||
|
REQUIRE(node.location() == loc);
|
||
|
REQUIRE(node.tags().empty());
|
||
|
}
|
||
|
|
||
|
SECTION("Node with tags)") {
|
||
|
const char* s = "123 v1 c456 Thighway=residential,oneway=true,name=High%20%Street";
|
||
|
const char* e = s + std::strlen(s);
|
||
|
oid::opl_parse_node(&s, buffer);
|
||
|
REQUIRE(s == e);
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
const osmium::Node& node = buffer.get<osmium::Node>(0);
|
||
|
REQUIRE(node.id() == 123);
|
||
|
REQUIRE(node.version() == 1);
|
||
|
REQUIRE(node.changeset() == 456);
|
||
|
REQUIRE(node.tags().size() == 3);
|
||
|
|
||
|
auto it = node.tags().cbegin();
|
||
|
REQUIRE(std::string{it->key()} == "highway");
|
||
|
REQUIRE(std::string{it->value()} == "residential");
|
||
|
++it;
|
||
|
REQUIRE(std::string{it->key()} == "oneway");
|
||
|
REQUIRE(std::string{it->value()} == "true");
|
||
|
++it;
|
||
|
REQUIRE(std::string{it->key()} == "name");
|
||
|
REQUIRE(std::string{it->value()} == "High Street");
|
||
|
++it;
|
||
|
REQUIRE(it == node.tags().cend());
|
||
|
}
|
||
|
|
||
|
SECTION("Order does not matter") {
|
||
|
const char* s = "125799 c7711393 dV v6 i45445 uUScha T t2011-03-29T21:43:10Z y53.0749415 x8.7868047";
|
||
|
const char* e = s + std::strlen(s);
|
||
|
oid::opl_parse_node(&s, buffer);
|
||
|
REQUIRE(s == e);
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
const osmium::Node& node = buffer.get<osmium::Node>(0);
|
||
|
REQUIRE(node.id() == 125799);
|
||
|
REQUIRE(node.version() == 6);
|
||
|
REQUIRE(node.visible());
|
||
|
REQUIRE(node.changeset() == 7711393);
|
||
|
REQUIRE(node.timestamp() == osmium::Timestamp{"2011-03-29T21:43:10Z"});
|
||
|
REQUIRE(node.uid() == 45445);
|
||
|
REQUIRE(std::string{node.user()} == "UScha");
|
||
|
osmium::Location loc{8.7868047, 53.0749415};
|
||
|
REQUIRE(node.location() == loc);
|
||
|
REQUIRE(node.tags().empty());
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse way") {
|
||
|
|
||
|
osmium::memory::Buffer buffer{1024};
|
||
|
|
||
|
SECTION("Way with id only") {
|
||
|
const char* s = "17";
|
||
|
const char* e = s + std::strlen(s);
|
||
|
oid::opl_parse_way(&s, buffer);
|
||
|
REQUIRE(s == e);
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
const osmium::Way& way = buffer.get<osmium::Way>(0);
|
||
|
REQUIRE(way.id() == 17);
|
||
|
}
|
||
|
|
||
|
SECTION("Complete way") {
|
||
|
const char* s = "78216 v12 dV c35895909 t2015-12-11T22:01:57Z i7412 umjulius Tdestination=Interlaken;%20%Kandersteg;%20%Zweisimmen,highway=motorway_link,name=Thun%20%Süd,oneway=yes,ref=17,surface=asphalt Nn1011242,n2569390773,n2569390769,n255308687,n2569390761,n255308689,n255308691,n1407526499,n255308692,n3888362655,n255308693,n255308694,n255308695,n255308686";
|
||
|
const char* e = s + std::strlen(s);
|
||
|
oid::opl_parse_way(&s, buffer);
|
||
|
REQUIRE(s == e);
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
const osmium::Way& way = buffer.get<osmium::Way>(0);
|
||
|
REQUIRE(way.id() == 78216);
|
||
|
REQUIRE(way.version() == 12);
|
||
|
REQUIRE(way.visible());
|
||
|
REQUIRE(way.changeset() == 35895909);
|
||
|
REQUIRE(way.timestamp() == osmium::Timestamp{"2015-12-11T22:01:57Z"});
|
||
|
REQUIRE(way.uid() == 7412);
|
||
|
REQUIRE(std::string{way.user()} == "mjulius");
|
||
|
REQUIRE(way.tags().size() == 6);
|
||
|
|
||
|
auto it = way.tags().cbegin();
|
||
|
REQUIRE(std::string{it->key()} == "destination");
|
||
|
REQUIRE(std::string{it->value()} == "Interlaken; Kandersteg; Zweisimmen");
|
||
|
++it;
|
||
|
REQUIRE(std::string{it->key()} == "highway");
|
||
|
REQUIRE(std::string{it->value()} == "motorway_link");
|
||
|
++it;
|
||
|
REQUIRE(std::string{it->key()} == "name");
|
||
|
REQUIRE(std::string{it->value()} == "Thun Süd");
|
||
|
++it;
|
||
|
REQUIRE(std::string{it->key()} == "oneway");
|
||
|
REQUIRE(std::string{it->value()} == "yes");
|
||
|
++it;
|
||
|
REQUIRE(std::string{it->key()} == "ref");
|
||
|
REQUIRE(std::string{it->value()} == "17");
|
||
|
++it;
|
||
|
REQUIRE(std::string{it->key()} == "surface");
|
||
|
REQUIRE(std::string{it->value()} == "asphalt");
|
||
|
++it;
|
||
|
REQUIRE(it == way.tags().cend());
|
||
|
|
||
|
REQUIRE(way.nodes().size() == 14);
|
||
|
std::vector<osmium::object_id_type> ids = {
|
||
|
1011242, 2569390773, 2569390769, 255308687, 2569390761, 255308689,
|
||
|
255308691, 1407526499, 255308692, 3888362655, 255308693, 255308694,
|
||
|
255308695, 255308686
|
||
|
};
|
||
|
REQUIRE(std::equal(way.nodes().cbegin(), way.nodes().cend(), ids.cbegin()));
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse relation") {
|
||
|
|
||
|
osmium::memory::Buffer buffer{1024};
|
||
|
|
||
|
SECTION("Relation with id only") {
|
||
|
const char* s = "17";
|
||
|
const char* e = s + std::strlen(s);
|
||
|
oid::opl_parse_relation(&s, buffer);
|
||
|
REQUIRE(s == e);
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
const osmium::Relation& relation = buffer.get<osmium::Relation>(0);
|
||
|
REQUIRE(relation.id() == 17);
|
||
|
}
|
||
|
|
||
|
SECTION("Complete relation") {
|
||
|
const char* s = "1074 v45 dV c20048094 t2014-01-17T10:27:04Z i86566 uwisieb Ttype=multipolygon,landuse=forest Mw255722275@inner,w256126142@outer,w24402792@inner,w256950103@outer,w255722279@outer";
|
||
|
const char* e = s + std::strlen(s);
|
||
|
oid::opl_parse_relation(&s, buffer);
|
||
|
REQUIRE(s == e);
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
const osmium::Relation& relation = buffer.get<osmium::Relation>(0);
|
||
|
REQUIRE(relation.id() == 1074);
|
||
|
REQUIRE(relation.version() == 45);
|
||
|
REQUIRE(relation.visible());
|
||
|
REQUIRE(relation.changeset() == 20048094);
|
||
|
REQUIRE(relation.timestamp() == osmium::Timestamp{"2014-01-17T10:27:04Z"});
|
||
|
REQUIRE(relation.uid() == 86566);
|
||
|
REQUIRE(std::string{relation.user()} == "wisieb");
|
||
|
REQUIRE(relation.tags().size() == 2);
|
||
|
|
||
|
auto it = relation.tags().cbegin();
|
||
|
REQUIRE(std::string{it->key()} == "type");
|
||
|
REQUIRE(std::string{it->value()} == "multipolygon");
|
||
|
++it;
|
||
|
REQUIRE(std::string{it->key()} == "landuse");
|
||
|
REQUIRE(std::string{it->value()} == "forest");
|
||
|
++it;
|
||
|
REQUIRE(it == relation.tags().cend());
|
||
|
|
||
|
REQUIRE(relation.members().size() == 5);
|
||
|
auto mit = relation.members().cbegin();
|
||
|
REQUIRE(mit->type() == osmium::item_type::way);
|
||
|
REQUIRE(mit->ref() == 255722275);
|
||
|
REQUIRE(std::string{mit->role()} == "inner");
|
||
|
++mit;
|
||
|
REQUIRE(mit->type() == osmium::item_type::way);
|
||
|
REQUIRE(mit->ref() == 256126142);
|
||
|
REQUIRE(std::string{mit->role()} == "outer");
|
||
|
++mit;
|
||
|
++mit;
|
||
|
++mit;
|
||
|
++mit;
|
||
|
REQUIRE(mit == relation.members().cend());
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse changeset") {
|
||
|
|
||
|
osmium::memory::Buffer buffer{1024};
|
||
|
|
||
|
SECTION("Changeset with id only") {
|
||
|
const char* s = "17";
|
||
|
const char* e = s + std::strlen(s);
|
||
|
oid::opl_parse_changeset(&s, buffer);
|
||
|
REQUIRE(s == e);
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
const osmium::Changeset& changeset = buffer.get<osmium::Changeset>(0);
|
||
|
REQUIRE(changeset.id() == 17);
|
||
|
}
|
||
|
|
||
|
SECTION("Complete changeset") {
|
||
|
const char* s = "873494 k1 s2009-04-21T08:52:49Z e2009-04-21T09:52:49Z d0 i13093 uTiberiusNero x13.923302 y50.957069 X14.0337519 Y50.9824084 Tcreated_by=Potlatch%20%0.11";
|
||
|
const char* e = s + std::strlen(s);
|
||
|
oid::opl_parse_changeset(&s, buffer);
|
||
|
REQUIRE(s == e);
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
const osmium::Changeset& changeset = buffer.get<osmium::Changeset>(0);
|
||
|
REQUIRE(changeset.id() == 873494);
|
||
|
REQUIRE(changeset.created_at() == osmium::Timestamp{"2009-04-21T08:52:49Z"});
|
||
|
REQUIRE(changeset.closed_at() == osmium::Timestamp{"2009-04-21T09:52:49Z"});
|
||
|
REQUIRE(changeset.num_changes() == 1);
|
||
|
REQUIRE(changeset.num_comments() == 0);
|
||
|
REQUIRE(changeset.uid() == 13093);
|
||
|
REQUIRE(std::string{changeset.user()} == "TiberiusNero");
|
||
|
REQUIRE(changeset.tags().size() == 1);
|
||
|
|
||
|
auto it = changeset.tags().cbegin();
|
||
|
REQUIRE(std::string{it->key()} == "created_by");
|
||
|
REQUIRE(std::string{it->value()} == "Potlatch 0.11");
|
||
|
++it;
|
||
|
REQUIRE(it == changeset.tags().cend());
|
||
|
|
||
|
osmium::Box box{13.923302, 50.957069, 14.0337519, 50.9824084};
|
||
|
REQUIRE(box == changeset.bounds());
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse line") {
|
||
|
|
||
|
osmium::memory::Buffer buffer{1024};
|
||
|
|
||
|
SECTION("Empty line") {
|
||
|
const char* s = "";
|
||
|
REQUIRE_FALSE(oid::opl_parse_line(0, "", buffer));
|
||
|
REQUIRE(buffer.written() == 0);
|
||
|
}
|
||
|
|
||
|
SECTION("Comment line") {
|
||
|
REQUIRE_FALSE(oid::opl_parse_line(0, "# abc", buffer));
|
||
|
REQUIRE(buffer.written() == 0);
|
||
|
}
|
||
|
|
||
|
SECTION("Fail") {
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
oid::opl_parse_line(0, "X", buffer);
|
||
|
}, "OPL error: unknown type on line 0 column 0");
|
||
|
REQUIRE(buffer.written() == 0);
|
||
|
}
|
||
|
|
||
|
SECTION("New line at end not allowed") {
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
oid::opl_parse_line(0, "n12 v3\n", buffer);
|
||
|
}, "OPL error: expected space or tab character on line 0 column 6");
|
||
|
}
|
||
|
|
||
|
SECTION("Node, but not asking for nodes") {
|
||
|
REQUIRE_FALSE(oid::opl_parse_line(0, "n12 v1", buffer, osmium::osm_entity_bits::way));
|
||
|
REQUIRE(buffer.written() == 0);
|
||
|
}
|
||
|
|
||
|
SECTION("Node") {
|
||
|
REQUIRE(oid::opl_parse_line(0, "n12 v3", buffer));
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
auto& item = buffer.get<osmium::memory::Item>(0);
|
||
|
REQUIRE(item.type() == osmium::item_type::node);
|
||
|
}
|
||
|
|
||
|
SECTION("Way") {
|
||
|
REQUIRE(oid::opl_parse_line(0, "w12 v3", buffer));
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
auto& item = buffer.get<osmium::memory::Item>(0);
|
||
|
REQUIRE(item.type() == osmium::item_type::way);
|
||
|
}
|
||
|
|
||
|
SECTION("Relation") {
|
||
|
REQUIRE(oid::opl_parse_line(0, "r12 v3", buffer));
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
auto& item = buffer.get<osmium::memory::Item>(0);
|
||
|
REQUIRE(item.type() == osmium::item_type::relation);
|
||
|
}
|
||
|
|
||
|
SECTION("Changeset") {
|
||
|
REQUIRE(oid::opl_parse_line(0, "c12", buffer));
|
||
|
REQUIRE(buffer.written() > 0);
|
||
|
auto& item = buffer.get<osmium::memory::Item>(0);
|
||
|
REQUIRE(item.type() == osmium::item_type::changeset);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Get context for errors") {
|
||
|
|
||
|
osmium::memory::Buffer buffer{1024};
|
||
|
|
||
|
SECTION("Unknown object type") {
|
||
|
bool error = false;
|
||
|
try {
|
||
|
oid::opl_parse_line(0, "~~~", buffer);
|
||
|
} catch (const osmium::opl_error& e) {
|
||
|
error = true;
|
||
|
REQUIRE(e.line == 0);
|
||
|
REQUIRE(e.column == 0);
|
||
|
REQUIRE(std::string{e.data} == "~~~");
|
||
|
}
|
||
|
REQUIRE(error);
|
||
|
}
|
||
|
|
||
|
SECTION("Node id") {
|
||
|
bool error = false;
|
||
|
try {
|
||
|
oid::opl_parse_line(0, "n~~~", buffer);
|
||
|
} catch (const osmium::opl_error& e) {
|
||
|
error = true;
|
||
|
REQUIRE(e.line == 0);
|
||
|
REQUIRE(e.column == 1);
|
||
|
REQUIRE(std::string{e.data} == "~~~");
|
||
|
}
|
||
|
REQUIRE(error);
|
||
|
}
|
||
|
|
||
|
SECTION("Node expect space") {
|
||
|
bool error = false;
|
||
|
try {
|
||
|
oid::opl_parse_line(1, "n123~~~", buffer);
|
||
|
} catch (const osmium::opl_error& e) {
|
||
|
error = true;
|
||
|
REQUIRE(e.line == 1);
|
||
|
REQUIRE(e.column == 4);
|
||
|
REQUIRE(std::string{e.data} == "~~~");
|
||
|
}
|
||
|
REQUIRE(error);
|
||
|
}
|
||
|
|
||
|
SECTION("Node unknown attribute") {
|
||
|
bool error = false;
|
||
|
try {
|
||
|
oid::opl_parse_line(2, "n123 ~~~", buffer);
|
||
|
} catch (const osmium::opl_error& e) {
|
||
|
error = true;
|
||
|
REQUIRE(e.line == 2);
|
||
|
REQUIRE(e.column == 5);
|
||
|
REQUIRE(std::string{e.data} == "~~~");
|
||
|
}
|
||
|
REQUIRE(error);
|
||
|
}
|
||
|
|
||
|
SECTION("Node version not an int") {
|
||
|
bool error = false;
|
||
|
try {
|
||
|
oid::opl_parse_line(3, "n123 v~~~", buffer);
|
||
|
} catch (const osmium::opl_error& e) {
|
||
|
error = true;
|
||
|
REQUIRE(e.line == 3);
|
||
|
REQUIRE(e.column == 6);
|
||
|
REQUIRE(std::string{e.data} == "~~~");
|
||
|
}
|
||
|
REQUIRE(error);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
TEST_CASE("Parse line with external interface") {
|
||
|
|
||
|
osmium::memory::Buffer buffer{1024};
|
||
|
|
||
|
SECTION("Node") {
|
||
|
REQUIRE(osmium::opl_parse("n12 v3", buffer));
|
||
|
REQUIRE(buffer.committed() > 0);
|
||
|
REQUIRE(buffer.written() == buffer.committed());
|
||
|
const auto& item = buffer.get<osmium::memory::Item>(0);
|
||
|
REQUIRE(item.type() == osmium::item_type::node);
|
||
|
REQUIRE(static_cast<const osmium::Node&>(item).id() == 12);
|
||
|
}
|
||
|
|
||
|
SECTION("Empty line") {
|
||
|
REQUIRE_FALSE(osmium::opl_parse("", buffer));
|
||
|
REQUIRE(buffer.written() == 0);
|
||
|
REQUIRE(buffer.committed() == 0);
|
||
|
}
|
||
|
|
||
|
SECTION("Failure") {
|
||
|
REQUIRE_THROWS_WITH({
|
||
|
osmium::opl_parse("x", buffer);
|
||
|
}, "OPL error: unknown type on line 0 column 0");
|
||
|
REQUIRE(buffer.written() == 0);
|
||
|
REQUIRE(buffer.committed() == 0);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|