osm2pgsql/tests/test-wkb.cpp

235 lines
6.9 KiB
C++

/**
* SPDX-License-Identifier: GPL-2.0-or-later
*
* This file is part of osm2pgsql (https://osm2pgsql.org/).
*
* Copyright (C) 2006-2024 by the osm2pgsql developer community.
* For a full list of authors see the git log.
*/
#include <catch.hpp>
#include "geom.hpp"
#include "wkb.hpp"
TEST_CASE("wkb: nullgeom", "[NoDB]")
{
geom::geometry_t const geom{};
REQUIRE(geom.is_null());
auto const wkb = geom_to_ewkb(geom);
REQUIRE(wkb.empty());
auto const result = ewkb_to_geom(wkb);
REQUIRE(result.is_null());
}
TEST_CASE("wkb: point", "[NoDB]")
{
geom::geometry_t const geom{geom::point_t{3.14, 2.17}, 42};
auto const result = ewkb_to_geom(geom_to_ewkb(geom));
REQUIRE(result.is_point());
REQUIRE(result.srid() == 42);
REQUIRE(result == geom);
}
TEST_CASE("wkb: linestring", "[NoDB]")
{
geom::geometry_t const geom{
geom::linestring_t{{1.2, 2.3}, {3.4, 4.5}, {5.6, 6.7}}, 43};
auto const result = ewkb_to_geom(geom_to_ewkb(geom));
REQUIRE(result.is_linestring());
REQUIRE(result.srid() == 43);
REQUIRE(result == geom);
}
TEST_CASE("wkb: polygon without inner ring", "[NoDB]")
{
geom::geometry_t const geom{
geom::polygon_t{geom::ring_t{
{0.0, 0.0}, {1.0, 0.0}, {1.0, 1.0}, {0.0, 1.0}, {0.0, 0.0}}},
44};
auto const result = ewkb_to_geom(geom_to_ewkb(geom));
REQUIRE(result.is_polygon());
REQUIRE(result.srid() == 44);
REQUIRE(result == geom);
}
TEST_CASE("wkb: polygon with inner rings", "[NoDB]")
{
geom::geometry_t geom{
geom::polygon_t{geom::ring_t{
{0.0, 0.0}, {3.0, 0.0}, {3.0, 3.0}, {0.0, 3.0}, {0.0, 0.0}}},
45};
geom.get<geom::polygon_t>().add_inner_ring(geom::ring_t{
{1.0, 1.0}, {2.0, 1.0}, {2.0, 2.0}, {1.0, 2.0}, {1.0, 1.0}});
auto const result = ewkb_to_geom(geom_to_ewkb(geom));
REQUIRE(result.is_polygon());
REQUIRE(result.srid() == 45);
REQUIRE(result == geom);
}
TEST_CASE("wkb: point as multipoint", "[NoDB]")
{
geom::geometry_t const geom{geom::point_t{1.2, 2.3}, 47};
auto const result = ewkb_to_geom(geom_to_ewkb(geom, true));
REQUIRE(result.is_multipoint());
REQUIRE(result.srid() == 47);
auto const &rmp = result.get<geom::multipoint_t>();
REQUIRE(rmp.num_geometries() == 1);
REQUIRE(rmp[0] == geom.get<geom::point_t>());
}
TEST_CASE("wkb: multipoint", "[NoDB]")
{
geom::geometry_t geom{geom::multipoint_t{}, 46};
auto &mp = geom.get<geom::multipoint_t>();
mp.add_geometry(geom::point_t{{1.2, 2.3}});
mp.add_geometry(geom::point_t{{7.0, 7.0}});
auto const result = ewkb_to_geom(geom_to_ewkb(geom));
REQUIRE(result.is_multipoint());
REQUIRE(result.srid() == 46);
REQUIRE(result == geom);
}
TEST_CASE("wkb: linestring as multilinestring", "[NoDB]")
{
geom::geometry_t const geom{
geom::linestring_t{{1.2, 2.3}, {3.4, 4.5}, {5.6, 6.7}}, 43};
auto const result = ewkb_to_geom(geom_to_ewkb(geom, true));
REQUIRE(result.is_multilinestring());
REQUIRE(result.srid() == 43);
auto const &rml = result.get<geom::multilinestring_t>();
REQUIRE(rml.num_geometries() == 1);
REQUIRE(rml[0] == geom.get<geom::linestring_t>());
}
TEST_CASE("wkb: multilinestring", "[NoDB]")
{
geom::geometry_t geom{geom::multilinestring_t{}, 46};
auto &ml = geom.get<geom::multilinestring_t>();
ml.add_geometry(geom::linestring_t{{1.2, 2.3}, {3.4, 4.5}, {5.6, 6.7}});
ml.add_geometry(geom::linestring_t{{7.0, 7.0}, {8.0, 7.0}, {8.0, 8.0}});
auto const result = ewkb_to_geom(geom_to_ewkb(geom));
REQUIRE(result.is_multilinestring());
REQUIRE(result.srid() == 46);
REQUIRE(result == geom);
}
TEST_CASE("wkb: polygon as multipolygon", "[NoDB]")
{
geom::geometry_t const geom{
geom::polygon_t{geom::ring_t{
{0.0, 0.0}, {1.0, 0.0}, {1.0, 1.0}, {0.0, 1.0}, {0.0, 0.0}}},
44};
auto const result = ewkb_to_geom(geom_to_ewkb(geom, true));
REQUIRE(result.is_multipolygon());
REQUIRE(result.srid() == 44);
auto const &rmp = result.get<geom::multipolygon_t>();
REQUIRE(rmp.num_geometries() == 1);
REQUIRE(rmp[0] == geom.get<geom::polygon_t>());
}
TEST_CASE("wkb: multipolygon", "[NoDB]")
{
geom::geometry_t geom{geom::multipolygon_t{}, 47};
auto &mp = geom.get<geom::multipolygon_t>();
{
auto &p0 = mp.add_geometry(geom::polygon_t{geom::ring_t{
{0.0, 0.0}, {3.0, 0.0}, {3.0, 3.0}, {0.0, 3.0}, {0.0, 0.0}}});
p0.add_inner_ring(geom::ring_t{
{1.0, 1.0}, {2.0, 1.0}, {2.0, 2.0}, {1.0, 2.0}, {1.0, 1.0}});
}
mp.add_geometry(geom::polygon_t{geom::ring_t{
{4.0, 4.0}, {5.0, 4.0}, {5.0, 5.0}, {4.0, 5.0}, {4.0, 4.0}}});
auto const result = ewkb_to_geom(geom_to_ewkb(geom));
REQUIRE(result.is_multipolygon());
REQUIRE(result.srid() == 47);
REQUIRE(result == geom);
}
TEST_CASE("wkb: geometrycollection", "[NoDB]")
{
geom::geometry_t geom1{geom::point_t{1.0, 2.0}};
geom::geometry_t geom2{geom::linestring_t{{1.2, 2.3}, {3.4, 4.5}}};
geom::geometry_t geom3{geom::multipolygon_t{}};
geom3.get<geom::multipolygon_t>().add_geometry(geom::polygon_t{geom::ring_t{
{4.0, 4.0}, {5.0, 4.0}, {5.0, 5.0}, {4.0, 5.0}, {4.0, 4.0}}});
geom::geometry_t geom{geom::collection_t{}, 49};
auto &c = geom.get<geom::collection_t>();
c.add_geometry(std::move(geom1));
c.add_geometry(std::move(geom2));
c.add_geometry(std::move(geom3));
auto const result = ewkb_to_geom(geom_to_ewkb(geom));
REQUIRE(result.is_collection());
REQUIRE(result.srid() == 49);
REQUIRE(result == geom);
}
TEST_CASE("wkb: invalid", "[NoDB]") { REQUIRE_THROWS(ewkb_to_geom("INVALID")); }
TEST_CASE("wkb hex decode of valid and invalid hex characters")
{
REQUIRE(decode_hex_char('0') == 0);
REQUIRE(decode_hex_char('9') == 9);
REQUIRE(decode_hex_char('a') == 0x0a);
REQUIRE(decode_hex_char('f') == 0x0f);
REQUIRE(decode_hex_char('A') == 0x0a);
REQUIRE(decode_hex_char('F') == 0x0f);
REQUIRE(decode_hex_char('#') == 0);
REQUIRE(decode_hex_char('@') == 0);
REQUIRE(decode_hex_char('g') == 0);
REQUIRE(decode_hex_char('G') == 0);
REQUIRE(decode_hex_char(0x7f) == 0);
}
TEST_CASE("wkb hex decode of valid hex string")
{
std::string const hex{"0001020F1099FF"};
std::string const data = {0x00,
0x01,
0x02,
0x0f,
0x10,
static_cast<char>(0x99),
static_cast<char>(0xff)};
auto const result = decode_hex(hex);
REQUIRE(result.size() == hex.size() / 2);
REQUIRE(result == data);
}
TEST_CASE("wkb hex decode of empty string is okay")
{
std::string const hex{};
REQUIRE(decode_hex(hex).empty());
}
TEST_CASE("wkb hex decode of string with odd number of characters fails")
{
REQUIRE_THROWS(decode_hex("a"));
REQUIRE_THROWS(decode_hex("abc"));
REQUIRE_THROWS(decode_hex("00000"));
}