osrm-backend/third_party/vtzero/test/t/test_geometry.cpp

335 lines
14 KiB
C++

#include <test.hpp>
#include <vtzero/geometry.hpp>
#include <cstdint>
#include <limits>
#include <vector>
using container = std::vector<uint32_t>;
using iterator = container::const_iterator;
TEST_CASE("geometry_decoder") {
const container g = {};
vtzero::detail::geometry_decoder<iterator> decoder{g.cbegin(), g.cend(), g.size() / 2};
REQUIRE(decoder.count() == 0);
REQUIRE(decoder.done());
REQUIRE_FALSE(decoder.next_command(vtzero::detail::CommandId::MOVE_TO));
REQUIRE_THROWS_AS(decoder.next_point(), const assert_error&);
}
TEST_CASE("geometry_decoder with point") {
const container g = {9, 50, 34};
vtzero::detail::geometry_decoder<iterator> decoder{g.cbegin(), g.cend(), g.size() / 2};
REQUIRE(decoder.count() == 0);
REQUIRE_FALSE(decoder.done());
REQUIRE_THROWS_AS(decoder.next_point(), const assert_error&);
SECTION("trying to get LineTo command") {
REQUIRE_THROWS_AS(decoder.next_command(vtzero::detail::CommandId::LINE_TO), const vtzero::geometry_exception&);
}
SECTION("trying to get ClosePath command") {
REQUIRE_THROWS_WITH(decoder.next_command(vtzero::detail::CommandId::CLOSE_PATH), "expected command 7 but got 1");
}
SECTION("trying to get MoveTo command") {
REQUIRE(decoder.next_command(vtzero::detail::CommandId::MOVE_TO));
REQUIRE_THROWS_AS(decoder.next_command(vtzero::detail::CommandId::MOVE_TO), const assert_error&);
REQUIRE(decoder.count() == 1);
REQUIRE(decoder.next_point() == vtzero::point(25, 17));
REQUIRE(decoder.done());
REQUIRE_FALSE(decoder.next_command(vtzero::detail::CommandId::MOVE_TO));
}
}
TEST_CASE("geometry_decoder with incomplete point") {
container g = {9, 50, 34};
SECTION("half a point") {
g.pop_back();
}
SECTION("missing point") {
g.pop_back();
g.pop_back();
}
vtzero::detail::geometry_decoder<iterator> decoder{g.cbegin(), g.cend(), 100};
REQUIRE(decoder.count() == 0);
REQUIRE_FALSE(decoder.done());
REQUIRE(decoder.next_command(vtzero::detail::CommandId::MOVE_TO));
REQUIRE(decoder.count() == 1);
REQUIRE_THROWS_AS(decoder.next_point(), const vtzero::geometry_exception&);
}
TEST_CASE("geometry_decoder with multipoint") {
const container g = {17, 10, 14, 3, 9};
vtzero::detail::geometry_decoder<iterator> decoder{g.cbegin(), g.cend(), g.size() / 2};
REQUIRE(decoder.count() == 0);
REQUIRE_FALSE(decoder.done());
REQUIRE(decoder.next_command(vtzero::detail::CommandId::MOVE_TO));
REQUIRE(decoder.count() == 2);
REQUIRE(decoder.next_point() == vtzero::point(5, 7));
REQUIRE(decoder.count() == 1);
REQUIRE(decoder.next_point() == vtzero::point(3, 2));
REQUIRE(decoder.count() == 0);
REQUIRE(decoder.done());
REQUIRE_FALSE(decoder.next_command(vtzero::detail::CommandId::MOVE_TO));
}
TEST_CASE("geometry_decoder with linestring") {
const container g = {9, 4, 4, 18, 0, 16, 16, 0};
vtzero::detail::geometry_decoder<iterator> decoder{g.cbegin(), g.cend(), g.size() / 2};
REQUIRE(decoder.count() == 0);
REQUIRE_FALSE(decoder.done());
REQUIRE(decoder.next_command(vtzero::detail::CommandId::MOVE_TO));
REQUIRE(decoder.count() == 1);
REQUIRE(decoder.next_point() == vtzero::point(2, 2));
REQUIRE(decoder.next_command(vtzero::detail::CommandId::LINE_TO));
REQUIRE(decoder.count() == 2);
REQUIRE(decoder.next_point() == vtzero::point(2, 10));
REQUIRE(decoder.count() == 1);
REQUIRE(decoder.next_point() == vtzero::point(10, 10));
REQUIRE(decoder.count() == 0);
REQUIRE(decoder.done());
REQUIRE_FALSE(decoder.next_command(vtzero::detail::CommandId::MOVE_TO));
}
TEST_CASE("geometry_decoder with linestring with equal points") {
const container g = {9, 4, 4, 18, 0, 16, 0, 0};
vtzero::detail::geometry_decoder<iterator> decoder{g.cbegin(), g.cend(), g.size() / 2};
REQUIRE(decoder.count() == 0);
REQUIRE_FALSE(decoder.done());
REQUIRE(decoder.next_command(vtzero::detail::CommandId::MOVE_TO));
REQUIRE(decoder.count() == 1);
REQUIRE(decoder.next_point() == vtzero::point(2, 2));
REQUIRE(decoder.next_command(vtzero::detail::CommandId::LINE_TO));
REQUIRE(decoder.count() == 2);
REQUIRE(decoder.next_point() == vtzero::point(2, 10));
REQUIRE(decoder.count() == 1);
REQUIRE(decoder.next_point() == vtzero::point(2, 10));
REQUIRE(decoder.count() == 0);
REQUIRE(decoder.done());
}
TEST_CASE("geometry_decoder with multilinestring") {
const container g = {9, 4, 4, 18, 0, 16, 16, 0, 9, 17, 17, 10, 4, 8};
vtzero::detail::geometry_decoder<iterator> decoder{g.cbegin(), g.cend(), g.size() / 2};
REQUIRE(decoder.count() == 0);
REQUIRE_FALSE(decoder.done());
REQUIRE(decoder.next_command(vtzero::detail::CommandId::MOVE_TO));
REQUIRE(decoder.count() == 1);
REQUIRE(decoder.next_point() == vtzero::point(2, 2));
REQUIRE(decoder.next_command(vtzero::detail::CommandId::LINE_TO));
REQUIRE(decoder.count() == 2);
REQUIRE(decoder.next_point() == vtzero::point(2, 10));
REQUIRE(decoder.count() == 1);
REQUIRE(decoder.next_point() == vtzero::point(10, 10));
REQUIRE(decoder.count() == 0);
REQUIRE(decoder.next_command(vtzero::detail::CommandId::MOVE_TO));
REQUIRE(decoder.count() == 1);
REQUIRE(decoder.next_point() == vtzero::point(1, 1));
REQUIRE(decoder.count() == 0);
REQUIRE(decoder.next_command(vtzero::detail::CommandId::LINE_TO));
REQUIRE(decoder.count() == 1);
REQUIRE(decoder.next_point() == vtzero::point(3, 5));
REQUIRE(decoder.count() == 0);
REQUIRE(decoder.done());
REQUIRE_FALSE(decoder.next_command(vtzero::detail::CommandId::MOVE_TO));
}
TEST_CASE("geometry_decoder with polygon") {
const container g = {9, 6, 12, 18, 10, 12, 24, 44, 15};
vtzero::detail::geometry_decoder<iterator> decoder{g.cbegin(), g.cend(), g.size() / 2};
REQUIRE(decoder.count() == 0);
REQUIRE_FALSE(decoder.done());
REQUIRE(decoder.next_command(vtzero::detail::CommandId::MOVE_TO));
REQUIRE(decoder.count() == 1);
REQUIRE(decoder.next_point() == vtzero::point(3, 6));
REQUIRE(decoder.next_command(vtzero::detail::CommandId::LINE_TO));
REQUIRE(decoder.count() == 2);
REQUIRE(decoder.next_point() == vtzero::point(8, 12));
REQUIRE(decoder.count() == 1);
REQUIRE(decoder.next_point() == vtzero::point(20, 34));
REQUIRE(decoder.count() == 0);
REQUIRE(decoder.next_command(vtzero::detail::CommandId::CLOSE_PATH));
REQUIRE(decoder.count() == 0);
REQUIRE(decoder.done());
REQUIRE_FALSE(decoder.next_command(vtzero::detail::CommandId::MOVE_TO));
}
TEST_CASE("geometry_decoder with polygon with wrong ClosePath count 2") {
const container g = {9, 6, 12, 18, 10, 12, 24, 44, 23};
vtzero::detail::geometry_decoder<iterator> decoder{g.cbegin(), g.cend(), g.size() / 2};
REQUIRE(decoder.count() == 0);
REQUIRE_FALSE(decoder.done());
REQUIRE(decoder.next_command(vtzero::detail::CommandId::MOVE_TO));
REQUIRE(decoder.next_point() == vtzero::point(3, 6));
REQUIRE(decoder.next_command(vtzero::detail::CommandId::LINE_TO));
REQUIRE(decoder.next_point() == vtzero::point(8, 12));
REQUIRE(decoder.next_point() == vtzero::point(20, 34));
REQUIRE_THROWS_AS(decoder.next_command(vtzero::detail::CommandId::CLOSE_PATH), const vtzero::geometry_exception&);
REQUIRE_THROWS_WITH(decoder.next_command(vtzero::detail::CommandId::CLOSE_PATH), "ClosePath command count is not 1");
}
TEST_CASE("geometry_decoder with polygon with wrong ClosePath count 0") {
const container g = {9, 6, 12, 18, 10, 12, 24, 44, 7};
vtzero::detail::geometry_decoder<iterator> decoder{g.cbegin(), g.cend(), g.size() / 2};
REQUIRE(decoder.count() == 0);
REQUIRE_FALSE(decoder.done());
REQUIRE(decoder.next_command(vtzero::detail::CommandId::MOVE_TO));
REQUIRE(decoder.next_point() == vtzero::point(3, 6));
REQUIRE(decoder.next_command(vtzero::detail::CommandId::LINE_TO));
REQUIRE(decoder.next_point() == vtzero::point(8, 12));
REQUIRE(decoder.next_point() == vtzero::point(20, 34));
REQUIRE_THROWS_AS(decoder.next_command(vtzero::detail::CommandId::CLOSE_PATH), const vtzero::geometry_exception&);
REQUIRE_THROWS_WITH(decoder.next_command(vtzero::detail::CommandId::CLOSE_PATH), "ClosePath command count is not 1");
}
TEST_CASE("geometry_decoder with multipolygon") {
const container g = {9, 0, 0, 26, 20, 0, 0, 20, 19, 0, 15, 9, 22, 2, 26, 18,
0, 0, 18, 17, 0, 15, 9, 4, 13, 26, 0, 8, 8, 0, 0, 7, 15};
vtzero::detail::geometry_decoder<iterator> decoder{g.cbegin(), g.cend(), g.size() / 2};
REQUIRE(decoder.count() == 0);
REQUIRE_FALSE(decoder.done());
REQUIRE(decoder.next_command(vtzero::detail::CommandId::MOVE_TO));
REQUIRE(decoder.count() == 1);
REQUIRE(decoder.next_point() == vtzero::point(0, 0));
REQUIRE(decoder.next_command(vtzero::detail::CommandId::LINE_TO));
REQUIRE(decoder.count() == 3);
REQUIRE(decoder.next_point() == vtzero::point(10, 0));
REQUIRE(decoder.count() == 2);
REQUIRE(decoder.next_point() == vtzero::point(10, 10));
REQUIRE(decoder.count() == 1);
REQUIRE(decoder.next_point() == vtzero::point(0, 10));
REQUIRE(decoder.count() == 0);
REQUIRE(decoder.next_command(vtzero::detail::CommandId::CLOSE_PATH));
REQUIRE(decoder.count() == 0);
REQUIRE(decoder.next_command(vtzero::detail::CommandId::MOVE_TO));
REQUIRE(decoder.count() == 1);
REQUIRE(decoder.next_point() == vtzero::point(11, 11));
REQUIRE(decoder.next_command(vtzero::detail::CommandId::LINE_TO));
REQUIRE(decoder.count() == 3);
REQUIRE(decoder.next_point() == vtzero::point(20, 11));
REQUIRE(decoder.count() == 2);
REQUIRE(decoder.next_point() == vtzero::point(20, 20));
REQUIRE(decoder.count() == 1);
REQUIRE(decoder.next_point() == vtzero::point(11, 20));
REQUIRE(decoder.count() == 0);
REQUIRE(decoder.next_command(vtzero::detail::CommandId::CLOSE_PATH));
REQUIRE(decoder.count() == 0);
REQUIRE(decoder.next_command(vtzero::detail::CommandId::MOVE_TO));
REQUIRE(decoder.count() == 1);
REQUIRE(decoder.next_point() == vtzero::point(13, 13));
REQUIRE(decoder.next_command(vtzero::detail::CommandId::LINE_TO));
REQUIRE(decoder.count() == 3);
REQUIRE(decoder.next_point() == vtzero::point(13, 17));
REQUIRE(decoder.count() == 2);
REQUIRE(decoder.next_point() == vtzero::point(17, 17));
REQUIRE(decoder.count() == 1);
REQUIRE(decoder.next_point() == vtzero::point(17, 13));
REQUIRE(decoder.count() == 0);
REQUIRE(decoder.next_command(vtzero::detail::CommandId::CLOSE_PATH));
REQUIRE(decoder.count() == 0);
REQUIRE(decoder.done());
REQUIRE_FALSE(decoder.next_command(vtzero::detail::CommandId::MOVE_TO));
}
TEST_CASE("geometry_decoder decoding linestring with int32 overflow in x coordinate") {
const container g = {vtzero::detail::command_move_to(1),
protozero::encode_zigzag32(std::numeric_limits<int32_t>::max()),
protozero::encode_zigzag32(0),
vtzero::detail::command_line_to(1),
protozero::encode_zigzag32(1),
protozero::encode_zigzag32(1)
};
vtzero::detail::geometry_decoder<iterator> decoder{g.cbegin(), g.cend(), g.size() / 2};
REQUIRE(decoder.count() == 0);
REQUIRE_FALSE(decoder.done());
REQUIRE(decoder.next_command(vtzero::detail::CommandId::MOVE_TO));
REQUIRE(decoder.count() == 1);
REQUIRE(decoder.next_point() == vtzero::point(std::numeric_limits<int32_t>::max(), 0));
REQUIRE(decoder.next_command(vtzero::detail::CommandId::LINE_TO));
REQUIRE(decoder.count() == 1);
REQUIRE(decoder.next_point() == vtzero::point(std::numeric_limits<int32_t>::min(), 1));
}
TEST_CASE("geometry_decoder decoding linestring with int32 overflow in y coordinate") {
const container g = {vtzero::detail::command_move_to(1),
protozero::encode_zigzag32(0),
protozero::encode_zigzag32(std::numeric_limits<int32_t>::min()),
vtzero::detail::command_line_to(1),
protozero::encode_zigzag32(-1),
protozero::encode_zigzag32(-1)
};
vtzero::detail::geometry_decoder<iterator> decoder{g.cbegin(), g.cend(), g.size() / 2};
REQUIRE(decoder.count() == 0);
REQUIRE_FALSE(decoder.done());
REQUIRE(decoder.next_command(vtzero::detail::CommandId::MOVE_TO));
REQUIRE(decoder.count() == 1);
REQUIRE(decoder.next_point() == vtzero::point(0, std::numeric_limits<int32_t>::min()));
REQUIRE(decoder.next_command(vtzero::detail::CommandId::LINE_TO));
REQUIRE(decoder.count() == 1);
REQUIRE(decoder.next_point() == vtzero::point(-1, std::numeric_limits<int32_t>::max()));
}
TEST_CASE("geometry_decoder with multipoint with a huge count") {
const uint32_t huge_value = (1ul << 29u) - 1;
const container g = {vtzero::detail::command_move_to(huge_value), 10, 10};
vtzero::detail::geometry_decoder<iterator> decoder{g.cbegin(), g.cend(), g.size() / 2};
REQUIRE(decoder.count() == 0);
REQUIRE_FALSE(decoder.done());
REQUIRE_THROWS_AS(decoder.next_command(vtzero::detail::CommandId::MOVE_TO), const vtzero::geometry_exception&);
}
TEST_CASE("geometry_decoder with multipoint with not enough points") {
const container g = {vtzero::detail::command_move_to(2), 10};
vtzero::detail::geometry_decoder<iterator> decoder{g.cbegin(), g.cend(), 1};
REQUIRE(decoder.count() == 0);
REQUIRE_FALSE(decoder.done());
REQUIRE_THROWS_AS(decoder.next_command(vtzero::detail::CommandId::MOVE_TO), const vtzero::geometry_exception&);
}