Merge commit '6bee8866de99a602039feef463c22c972f0f86aa' as 'third_party/vtzero'
This commit is contained in:
+81
@@ -0,0 +1,81 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
#
|
||||
# CMake config
|
||||
#
|
||||
# vtzero tests
|
||||
#
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
if(Boost_FOUND)
|
||||
message(STATUS "Boost library found: enable testing with boost::variant")
|
||||
add_definitions(-DVTZERO_TEST_WITH_VARIANT)
|
||||
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
|
||||
else()
|
||||
message(STATUS "Boost library not found: disable testing with boost::variant")
|
||||
endif()
|
||||
|
||||
include_directories(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/catch")
|
||||
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
|
||||
set(TEST_SOURCES builder
|
||||
builder_linestring
|
||||
builder_point
|
||||
builder_polygon
|
||||
exceptions
|
||||
feature
|
||||
geometry
|
||||
geometry_linestring
|
||||
geometry_point
|
||||
geometry_polygon
|
||||
index
|
||||
layer
|
||||
output
|
||||
point
|
||||
property_map
|
||||
property_value
|
||||
types
|
||||
vector_tile)
|
||||
|
||||
string(REGEX REPLACE "([^;]+)" "t/test_\\1.cpp" _test_sources "${TEST_SOURCES}")
|
||||
|
||||
add_executable(unit-tests test_main.cpp ${_test_sources})
|
||||
|
||||
add_executable(fixture-tests test_main.cpp fixture_tests.cpp)
|
||||
|
||||
add_test(NAME unit-tests
|
||||
COMMAND unit-tests
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
set(_fixtures ${MVT_FIXTURES}/fixtures)
|
||||
if(EXISTS ${_fixtures})
|
||||
message(STATUS "Found test fixtures. Enabled mvt fixture tests.")
|
||||
add_test(NAME fixture-tests
|
||||
COMMAND fixture-tests)
|
||||
|
||||
set_tests_properties(fixture-tests PROPERTIES
|
||||
ENVIRONMENT "FIXTURES_DIR=${_fixtures}")
|
||||
|
||||
if(NOT WIN32)
|
||||
set(_real_world_dir ${MVT_FIXTURES}/real-world)
|
||||
file(GLOB real_world ${_real_world_dir}/bangkok/*
|
||||
${_real_world_dir}/chicago/*
|
||||
${_real_world_dir}/nepal/*
|
||||
${_real_world_dir}/norway/*
|
||||
${_real_world_dir}/sanfrancisco/*
|
||||
${_real_world_dir}/uruguay/*)
|
||||
|
||||
if(NOT "${real_world}" STREQUAL "")
|
||||
execute_process(COMMAND cat ${real_world}
|
||||
OUTPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/real-world-all.mvt)
|
||||
|
||||
add_test(NAME vtzero-show-real-world
|
||||
COMMAND vtzero-show ${CMAKE_BINARY_DIR}/test/real-world-all.mvt)
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "Disabled mvt fixture tests, because fixtures not found.\n Install them by calling 'git submodule update --init' in ${CMAKE_SOURCE_DIR}.")
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
+11678
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1003
File diff suppressed because it is too large
Load Diff
+37
@@ -0,0 +1,37 @@
|
||||
#ifndef TEST_HPP
|
||||
#define TEST_HPP
|
||||
|
||||
#include <catch.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
// Define vtzero_assert() to throw this error. This allows the tests to
|
||||
// check that the assert fails.
|
||||
struct assert_error : public std::runtime_error {
|
||||
explicit assert_error(const char* what_arg) : std::runtime_error(what_arg) {
|
||||
}
|
||||
};
|
||||
|
||||
#define vtzero_assert(x) if (!(x)) { throw assert_error{#x}; }
|
||||
|
||||
#define vtzero_assert_in_noexcept_function(x) if (!(x)) { got_an_assert = true; }
|
||||
|
||||
extern bool got_an_assert;
|
||||
|
||||
#define REQUIRE_ASSERT(x) x; REQUIRE(got_an_assert); got_an_assert = false;
|
||||
|
||||
#include <vtzero/output.hpp>
|
||||
|
||||
std::string load_test_tile();
|
||||
|
||||
struct mypoint {
|
||||
int64_t p1;
|
||||
int64_t p2;
|
||||
};
|
||||
|
||||
inline vtzero::point create_vtzero_point(mypoint p) noexcept {
|
||||
return {static_cast<int32_t>(p.p1),
|
||||
static_cast<int32_t>(p.p2)};
|
||||
}
|
||||
|
||||
#endif // TEST_HPP
|
||||
+1
Submodule third_party/vtzero/test/mvt-fixtures added at 6ff9cefd59
+408
@@ -0,0 +1,408 @@
|
||||
|
||||
#include <test.hpp>
|
||||
|
||||
#include <vtzero/builder.hpp>
|
||||
#include <vtzero/index.hpp>
|
||||
#include <vtzero/output.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
template <typename T>
|
||||
struct movable_not_copyable {
|
||||
constexpr static bool value = !std::is_copy_constructible<T>::value &&
|
||||
!std::is_copy_assignable<T>::value &&
|
||||
std::is_nothrow_move_constructible<T>::value &&
|
||||
std::is_nothrow_move_assignable<T>::value;
|
||||
};
|
||||
|
||||
static_assert(movable_not_copyable<vtzero::tile_builder>::value, "tile_builder should be nothrow movable, but not copyable");
|
||||
static_assert(movable_not_copyable<vtzero::point_feature_builder>::value, "point_feature_builder should be nothrow movable, but not copyable");
|
||||
static_assert(movable_not_copyable<vtzero::linestring_feature_builder>::value, "linestring_feature_builder should be nothrow movable, but not copyable");
|
||||
static_assert(movable_not_copyable<vtzero::polygon_feature_builder>::value, "polygon_feature_builder should be nothrow movable, but not copyable");
|
||||
static_assert(movable_not_copyable<vtzero::geometry_feature_builder>::value, "geometry_feature_builder should be nothrow movable, but not copyable");
|
||||
|
||||
TEST_CASE("Create tile from existing layers") {
|
||||
const auto buffer = load_test_tile();
|
||||
vtzero::vector_tile tile{buffer};
|
||||
|
||||
vtzero::tile_builder tbuilder;
|
||||
|
||||
SECTION("add_existing_layer(layer)") {
|
||||
while (auto layer = tile.next_layer()) {
|
||||
tbuilder.add_existing_layer(layer);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("add_existing_layer(data_view)") {
|
||||
while (auto layer = tile.next_layer()) {
|
||||
tbuilder.add_existing_layer(layer.data());
|
||||
}
|
||||
}
|
||||
|
||||
const std::string data = tbuilder.serialize();
|
||||
|
||||
REQUIRE(data == buffer);
|
||||
}
|
||||
|
||||
TEST_CASE("Create layer based on existing layer") {
|
||||
const auto buffer = load_test_tile();
|
||||
vtzero::vector_tile tile{buffer};
|
||||
const auto layer = tile.get_layer_by_name("place_label");
|
||||
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, layer};
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
fbuilder.set_id(42);
|
||||
fbuilder.add_point(10, 20);
|
||||
fbuilder.commit();
|
||||
|
||||
const std::string data = tbuilder.serialize();
|
||||
vtzero::vector_tile new_tile{data};
|
||||
const auto new_layer = new_tile.next_layer();
|
||||
REQUIRE(std::string(new_layer.name()) == "place_label");
|
||||
REQUIRE(new_layer.version() == 1);
|
||||
REQUIRE(new_layer.extent() == 4096);
|
||||
}
|
||||
|
||||
TEST_CASE("Create layer and add keys/values") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "name"};
|
||||
|
||||
const auto ki1 = lbuilder.add_key_without_dup_check("key1");
|
||||
const auto ki2 = lbuilder.add_key("key2");
|
||||
const auto ki3 = lbuilder.add_key("key1");
|
||||
|
||||
REQUIRE(ki1 != ki2);
|
||||
REQUIRE(ki1 == ki3);
|
||||
|
||||
const auto vi1 = lbuilder.add_value_without_dup_check(vtzero::encoded_property_value{"value1"});
|
||||
vtzero::encoded_property_value value2{"value2"};
|
||||
const auto vi2 = lbuilder.add_value_without_dup_check(vtzero::property_value{value2.data()});
|
||||
|
||||
const auto vi3 = lbuilder.add_value(vtzero::encoded_property_value{"value1"});
|
||||
const auto vi4 = lbuilder.add_value(vtzero::encoded_property_value{19});
|
||||
const auto vi5 = lbuilder.add_value(vtzero::encoded_property_value{19.0});
|
||||
const auto vi6 = lbuilder.add_value(vtzero::encoded_property_value{22});
|
||||
vtzero::encoded_property_value nineteen{19};
|
||||
const auto vi7 = lbuilder.add_value(vtzero::property_value{nineteen.data()});
|
||||
|
||||
REQUIRE(vi1 != vi2);
|
||||
REQUIRE(vi1 == vi3);
|
||||
REQUIRE(vi1 != vi4);
|
||||
REQUIRE(vi1 != vi5);
|
||||
REQUIRE(vi1 != vi6);
|
||||
REQUIRE(vi4 != vi5);
|
||||
REQUIRE(vi4 != vi6);
|
||||
REQUIRE(vi4 == vi7);
|
||||
}
|
||||
|
||||
TEST_CASE("Committing a feature succeeds after a geometry was added") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
|
||||
{ // explicit commit after geometry
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
fbuilder.set_id(1);
|
||||
fbuilder.add_point(10, 10);
|
||||
fbuilder.commit();
|
||||
}
|
||||
|
||||
{ // explicit commit after properties
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
fbuilder.set_id(2);
|
||||
fbuilder.add_point(10, 10);
|
||||
fbuilder.add_property("foo", vtzero::encoded_property_value{"bar"});
|
||||
fbuilder.commit();
|
||||
}
|
||||
|
||||
{ // extra commits or rollbacks are okay but no other calls
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
fbuilder.set_id(3);
|
||||
fbuilder.add_point(10, 10);
|
||||
fbuilder.add_property("foo", vtzero::encoded_property_value{"bar"});
|
||||
fbuilder.commit();
|
||||
|
||||
SECTION("superfluous commit()") {
|
||||
fbuilder.commit();
|
||||
}
|
||||
SECTION("superfluous rollback()") {
|
||||
fbuilder.rollback();
|
||||
}
|
||||
|
||||
REQUIRE_THROWS_AS(fbuilder.set_id(10), const assert_error&);
|
||||
REQUIRE_THROWS_AS(fbuilder.add_point(20, 20), const assert_error&);
|
||||
REQUIRE_THROWS_AS(fbuilder.add_property("x", "y"), const assert_error&);
|
||||
}
|
||||
|
||||
const std::string data = tbuilder.serialize();
|
||||
|
||||
vtzero::vector_tile tile{data};
|
||||
auto layer = tile.next_layer();
|
||||
|
||||
uint64_t n = 1;
|
||||
while (auto feature = layer.next_feature()) {
|
||||
REQUIRE(feature.id() == n++);
|
||||
}
|
||||
|
||||
REQUIRE(n == 4);
|
||||
}
|
||||
|
||||
TEST_CASE("Committing a feature fails with assert if no geometry was added") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
|
||||
SECTION("explicit immediate commit") {
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
REQUIRE_THROWS_AS(fbuilder.commit(), const assert_error&);
|
||||
}
|
||||
|
||||
SECTION("explicit commit after setting id") {
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
fbuilder.set_id(2);
|
||||
REQUIRE_THROWS_AS(fbuilder.commit(), const assert_error&);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Rollback feature") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
|
||||
{
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
fbuilder.set_id(1);
|
||||
fbuilder.add_point(10, 10);
|
||||
fbuilder.commit();
|
||||
}
|
||||
|
||||
{ // immediate rollback
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
fbuilder.set_id(2);
|
||||
fbuilder.rollback();
|
||||
}
|
||||
|
||||
{ // rollback after setting id
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
fbuilder.set_id(3);
|
||||
fbuilder.rollback();
|
||||
}
|
||||
|
||||
{ // rollback after geometry
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
fbuilder.set_id(4);
|
||||
fbuilder.add_point(20, 20);
|
||||
fbuilder.rollback();
|
||||
}
|
||||
|
||||
{ // rollback after properties
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
fbuilder.set_id(5);
|
||||
fbuilder.add_point(20, 20);
|
||||
fbuilder.add_property("foo", vtzero::encoded_property_value{"bar"});
|
||||
fbuilder.rollback();
|
||||
}
|
||||
|
||||
{ // implicit rollback after geometry
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
fbuilder.set_id(6);
|
||||
fbuilder.add_point(10, 10);
|
||||
}
|
||||
|
||||
{ // implicit rollback after properties
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
fbuilder.set_id(7);
|
||||
fbuilder.add_point(10, 10);
|
||||
fbuilder.add_property("foo", vtzero::encoded_property_value{"bar"});
|
||||
}
|
||||
|
||||
{
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
fbuilder.set_id(8);
|
||||
fbuilder.add_point(30, 30);
|
||||
fbuilder.commit();
|
||||
}
|
||||
|
||||
const std::string data = tbuilder.serialize();
|
||||
|
||||
vtzero::vector_tile tile{data};
|
||||
auto layer = tile.next_layer();
|
||||
|
||||
auto feature = layer.next_feature();
|
||||
REQUIRE(feature.id() == 1);
|
||||
|
||||
feature = layer.next_feature();
|
||||
REQUIRE(feature.id() == 8);
|
||||
|
||||
feature = layer.next_feature();
|
||||
REQUIRE_FALSE(feature);
|
||||
}
|
||||
|
||||
static bool vector_tile_equal(const std::string& t1, const std::string& t2) {
|
||||
vtzero::vector_tile vt1{t1};
|
||||
vtzero::vector_tile vt2{t2};
|
||||
|
||||
for (auto l1 = vt1.next_layer(), l2 = vt2.next_layer();
|
||||
l1 && l2;
|
||||
l1 = vt1.next_layer(), l2 = vt2.next_layer()) {
|
||||
if (l1.empty()) {
|
||||
l1 = vt1.next_layer();
|
||||
if (!l1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (l2.empty()) {
|
||||
l2 = vt2.next_layer();
|
||||
if (!l2) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!l1 ||
|
||||
!l2 ||
|
||||
l1.version() != l2.version() ||
|
||||
l1.extent() != l2.extent() ||
|
||||
l1.num_features() != l2.num_features() ||
|
||||
l1.name() != l2.name()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto f1 = l1.next_feature(), f2 = l2.next_feature();
|
||||
f1 && f2;
|
||||
f1 = l1.next_feature(), f2 = l2.next_feature()) {
|
||||
if (f1.id() != f2.id() ||
|
||||
f1.geometry_type() != f2.geometry_type() ||
|
||||
f1.num_properties() != f2.num_properties() ||
|
||||
f1.geometry().data() != f2.geometry().data()) {
|
||||
return false;
|
||||
}
|
||||
for (auto p1 = f1.next_property(), p2 = f2.next_property();
|
||||
p1 && p2;
|
||||
p1 = f1.next_property(), p2 = f2.next_property()) {
|
||||
if (p1.key() != p2.key() || p1.value() != p2.value()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST_CASE("Copy tile") {
|
||||
const auto buffer = load_test_tile();
|
||||
vtzero::vector_tile tile{buffer};
|
||||
|
||||
vtzero::tile_builder tbuilder;
|
||||
|
||||
while (auto layer = tile.next_layer()) {
|
||||
vtzero::layer_builder lbuilder{tbuilder, layer};
|
||||
while (auto feature = layer.next_feature()) {
|
||||
lbuilder.add_feature(feature);
|
||||
}
|
||||
}
|
||||
|
||||
const std::string data = tbuilder.serialize();
|
||||
REQUIRE(vector_tile_equal(buffer, data));
|
||||
}
|
||||
|
||||
TEST_CASE("Copy tile using geometry_feature_builder") {
|
||||
const auto buffer = load_test_tile();
|
||||
vtzero::vector_tile tile{buffer};
|
||||
|
||||
vtzero::tile_builder tbuilder;
|
||||
|
||||
while (auto layer = tile.next_layer()) {
|
||||
vtzero::layer_builder lbuilder{tbuilder, layer};
|
||||
while (auto feature = layer.next_feature()) {
|
||||
vtzero::geometry_feature_builder fbuilder{lbuilder};
|
||||
fbuilder.set_id(feature.id());
|
||||
fbuilder.set_geometry(feature.geometry());
|
||||
while (auto property = feature.next_property()) {
|
||||
fbuilder.add_property(property.key(), property.value());
|
||||
}
|
||||
fbuilder.commit();
|
||||
}
|
||||
}
|
||||
|
||||
const std::string data = tbuilder.serialize();
|
||||
REQUIRE(vector_tile_equal(buffer, data));
|
||||
}
|
||||
|
||||
TEST_CASE("Copy only point geometries using geometry_feature_builder") {
|
||||
const auto buffer = load_test_tile();
|
||||
vtzero::vector_tile tile{buffer};
|
||||
|
||||
vtzero::tile_builder tbuilder;
|
||||
|
||||
int n = 0;
|
||||
while (auto layer = tile.next_layer()) {
|
||||
vtzero::layer_builder lbuilder{tbuilder, layer};
|
||||
while (auto feature = layer.next_feature()) {
|
||||
vtzero::geometry_feature_builder fbuilder{lbuilder};
|
||||
fbuilder.set_id(feature.id());
|
||||
if (feature.geometry().type() == vtzero::GeomType::POINT) {
|
||||
fbuilder.set_geometry(feature.geometry());
|
||||
while (auto property = feature.next_property()) {
|
||||
fbuilder.add_property(property.key(), property.value());
|
||||
}
|
||||
fbuilder.commit();
|
||||
++n;
|
||||
} else {
|
||||
fbuilder.rollback();
|
||||
}
|
||||
}
|
||||
}
|
||||
REQUIRE(n == 17);
|
||||
|
||||
const std::string data = tbuilder.serialize();
|
||||
|
||||
n = 0;
|
||||
vtzero::vector_tile result_tile{data};
|
||||
while (auto layer = result_tile.next_layer()) {
|
||||
while (auto feature = layer.next_feature()) {
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
REQUIRE(n == 17);
|
||||
}
|
||||
|
||||
TEST_CASE("Build point feature from container with too many points") {
|
||||
|
||||
// fake container pretending to contain too many points
|
||||
struct test_container {
|
||||
|
||||
std::size_t size() const noexcept {
|
||||
return 1ul << 29u;
|
||||
}
|
||||
|
||||
vtzero::point* begin() const noexcept {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
vtzero::point* end() const noexcept {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
|
||||
fbuilder.set_id(1);
|
||||
|
||||
test_container tc;
|
||||
REQUIRE_THROWS_AS(fbuilder.add_points_from_container(tc), const vtzero::geometry_exception&);
|
||||
}
|
||||
|
||||
TEST_CASE("Moving a feature builder is allowed") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
|
||||
auto fbuilder2 = std::move(fbuilder);
|
||||
vtzero::point_feature_builder fbuilder3{std::move(fbuilder2)};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,312 @@
|
||||
|
||||
#include <test.hpp>
|
||||
|
||||
#include <vtzero/builder.hpp>
|
||||
#include <vtzero/geometry.hpp>
|
||||
#include <vtzero/index.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
using ls_type = std::vector<std::vector<vtzero::point>>;
|
||||
|
||||
struct linestring_handler {
|
||||
|
||||
ls_type data;
|
||||
|
||||
void linestring_begin(uint32_t count) {
|
||||
data.emplace_back();
|
||||
data.back().reserve(count);
|
||||
}
|
||||
|
||||
void linestring_point(const vtzero::point point) {
|
||||
data.back().push_back(point);
|
||||
}
|
||||
|
||||
void linestring_end() const noexcept {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
static void test_linestring_builder(bool with_id, bool with_prop) {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
|
||||
{
|
||||
vtzero::linestring_feature_builder fbuilder{lbuilder};
|
||||
|
||||
if (with_id) {
|
||||
fbuilder.set_id(17);
|
||||
}
|
||||
|
||||
fbuilder.add_linestring(3);
|
||||
fbuilder.set_point(10, 20);
|
||||
fbuilder.set_point(vtzero::point{20, 30});
|
||||
fbuilder.set_point(mypoint{30, 40});
|
||||
|
||||
if (with_prop) {
|
||||
fbuilder.add_property("foo", "bar");
|
||||
}
|
||||
|
||||
fbuilder.commit();
|
||||
}
|
||||
|
||||
const std::string data = tbuilder.serialize();
|
||||
|
||||
vtzero::vector_tile tile{data};
|
||||
|
||||
auto layer = tile.next_layer();
|
||||
REQUIRE(layer.name() == "test");
|
||||
REQUIRE(layer.version() == 2);
|
||||
REQUIRE(layer.extent() == 4096);
|
||||
REQUIRE(layer.num_features() == 1);
|
||||
|
||||
const auto feature = layer.next_feature();
|
||||
REQUIRE(feature.id() == (with_id ? 17 : 0));
|
||||
|
||||
linestring_handler handler;
|
||||
vtzero::decode_linestring_geometry(feature.geometry(), handler);
|
||||
|
||||
const ls_type result = {{{10, 20}, {20, 30}, {30, 40}}};
|
||||
REQUIRE(handler.data == result);
|
||||
}
|
||||
|
||||
TEST_CASE("linestring builder without id/without properties") {
|
||||
test_linestring_builder(false, false);
|
||||
}
|
||||
|
||||
TEST_CASE("linestring builder without id/with properties") {
|
||||
test_linestring_builder(false, true);
|
||||
}
|
||||
|
||||
TEST_CASE("linestring builder with id/without properties") {
|
||||
test_linestring_builder(true, false);
|
||||
}
|
||||
|
||||
TEST_CASE("linestring builder with id/with properties") {
|
||||
test_linestring_builder(true, true);
|
||||
}
|
||||
|
||||
TEST_CASE("Calling add_linestring() with bad values throws assert") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::linestring_feature_builder fbuilder{lbuilder};
|
||||
|
||||
SECTION("0") {
|
||||
REQUIRE_THROWS_AS(fbuilder.add_linestring(0), const assert_error&);
|
||||
}
|
||||
SECTION("1") {
|
||||
REQUIRE_THROWS_AS(fbuilder.add_linestring(1), const assert_error&);
|
||||
}
|
||||
SECTION("2^29") {
|
||||
REQUIRE_THROWS_AS(fbuilder.add_linestring(1ul << 29u), const assert_error&);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_multilinestring_builder(bool with_id, bool with_prop) {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::linestring_feature_builder fbuilder{lbuilder};
|
||||
|
||||
if (with_id) {
|
||||
fbuilder.set_id(17);
|
||||
}
|
||||
|
||||
fbuilder.add_linestring(3);
|
||||
fbuilder.set_point(10, 20);
|
||||
fbuilder.set_point(vtzero::point{20, 30});
|
||||
fbuilder.set_point(mypoint{30, 40});
|
||||
|
||||
fbuilder.add_linestring(2);
|
||||
fbuilder.set_point(1, 2);
|
||||
fbuilder.set_point(2, 1);
|
||||
|
||||
if (with_prop) {
|
||||
fbuilder.add_property("foo", vtzero::encoded_property_value{"bar"});
|
||||
}
|
||||
|
||||
fbuilder.commit();
|
||||
|
||||
const std::string data = tbuilder.serialize();
|
||||
|
||||
vtzero::vector_tile tile{data};
|
||||
|
||||
auto layer = tile.next_layer();
|
||||
REQUIRE(layer.name() == "test");
|
||||
REQUIRE(layer.version() == 2);
|
||||
REQUIRE(layer.extent() == 4096);
|
||||
REQUIRE(layer.num_features() == 1);
|
||||
|
||||
const auto feature = layer.next_feature();
|
||||
REQUIRE(feature.id() == (with_id ? 17 : 0));
|
||||
|
||||
linestring_handler handler;
|
||||
vtzero::decode_linestring_geometry(feature.geometry(), handler);
|
||||
|
||||
const ls_type result = {{{10, 20}, {20, 30}, {30, 40}}, {{1, 2}, {2, 1}}};
|
||||
REQUIRE(handler.data == result);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("Multilinestring builder without id/without properties") {
|
||||
test_multilinestring_builder(false, false);
|
||||
}
|
||||
|
||||
TEST_CASE("Multilinestring builder without id/with properties") {
|
||||
test_multilinestring_builder(false, true);
|
||||
}
|
||||
|
||||
TEST_CASE("Multilinestring builder with id/without properties") {
|
||||
test_multilinestring_builder(true, false);
|
||||
}
|
||||
|
||||
TEST_CASE("Multilinestring builder with id/with properties") {
|
||||
test_multilinestring_builder(true, true);
|
||||
}
|
||||
|
||||
TEST_CASE("Calling add_linestring() twice throws assert") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::linestring_feature_builder fbuilder{lbuilder};
|
||||
|
||||
fbuilder.add_linestring(3);
|
||||
REQUIRE_ASSERT(fbuilder.add_linestring(2));
|
||||
}
|
||||
|
||||
TEST_CASE("Calling linestring_feature_builder::set_point() throws assert") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::linestring_feature_builder fbuilder{lbuilder};
|
||||
|
||||
REQUIRE_THROWS_AS(fbuilder.set_point(10, 10), const assert_error&);
|
||||
}
|
||||
|
||||
TEST_CASE("Calling linestring_feature_builder::set_point() with same point throws") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::linestring_feature_builder fbuilder{lbuilder};
|
||||
|
||||
fbuilder.add_linestring(2);
|
||||
fbuilder.set_point(10, 10);
|
||||
REQUIRE_THROWS_AS(fbuilder.set_point(10, 10), const vtzero::geometry_exception&);
|
||||
}
|
||||
|
||||
TEST_CASE("Calling linestring_feature_builder::set_point() too often throws assert") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::linestring_feature_builder fbuilder{lbuilder};
|
||||
|
||||
fbuilder.add_linestring(2);
|
||||
fbuilder.set_point(10, 20);
|
||||
fbuilder.set_point(20, 20);
|
||||
REQUIRE_THROWS_AS(fbuilder.set_point(30, 20), const assert_error&);
|
||||
}
|
||||
|
||||
TEST_CASE("Add linestring from container") {
|
||||
const ls_type points = {{{10, 20}, {20, 30}, {30, 40}}};
|
||||
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
|
||||
{
|
||||
vtzero::linestring_feature_builder fbuilder{lbuilder};
|
||||
|
||||
#if 0
|
||||
SECTION("using iterators") {
|
||||
fbuilder.add_linestring(points[0].cbegin(), points[0].cend());
|
||||
}
|
||||
|
||||
SECTION("using iterators and size") {
|
||||
fbuilder.add_linestring(points[0].cbegin(), points[0].cend(), static_cast<uint32_t>(points[0].size()));
|
||||
}
|
||||
#endif
|
||||
|
||||
SECTION("using container directly") {
|
||||
fbuilder.add_linestring_from_container(points[0]);
|
||||
}
|
||||
|
||||
fbuilder.commit();
|
||||
}
|
||||
|
||||
const std::string data = tbuilder.serialize();
|
||||
|
||||
vtzero::vector_tile tile{data};
|
||||
|
||||
auto layer = tile.next_layer();
|
||||
REQUIRE(layer);
|
||||
REQUIRE(layer.name() == "test");
|
||||
REQUIRE(layer.version() == 2);
|
||||
REQUIRE(layer.extent() == 4096);
|
||||
REQUIRE(layer.num_features() == 1);
|
||||
|
||||
const auto feature = layer.next_feature();
|
||||
|
||||
linestring_handler handler;
|
||||
vtzero::decode_linestring_geometry(feature.geometry(), handler);
|
||||
|
||||
REQUIRE(handler.data == points);
|
||||
}
|
||||
|
||||
#if 0
|
||||
TEST_CASE("Add linestring from iterator with wrong count throws assert") {
|
||||
const std::vector<vtzero::point> points = {{10, 20}, {20, 30}, {30, 40}};
|
||||
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::linestring_feature_builder fbuilder{lbuilder};
|
||||
|
||||
REQUIRE_THROWS_AS(fbuilder.add_linestring(points.cbegin(),
|
||||
points.cend(),
|
||||
static_cast<uint32_t>(points.size() + 1)), const assert_error&);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_CASE("Adding several linestrings with feature rollback in the middle") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
|
||||
{
|
||||
vtzero::linestring_feature_builder fbuilder{lbuilder};
|
||||
fbuilder.set_id(1);
|
||||
fbuilder.add_linestring(2);
|
||||
fbuilder.set_point(10, 10);
|
||||
fbuilder.set_point(20, 20);
|
||||
fbuilder.commit();
|
||||
}
|
||||
|
||||
try {
|
||||
vtzero::linestring_feature_builder fbuilder{lbuilder};
|
||||
fbuilder.set_id(2);
|
||||
fbuilder.add_linestring(2);
|
||||
fbuilder.set_point(10, 10);
|
||||
fbuilder.set_point(10, 10);
|
||||
fbuilder.commit();
|
||||
} catch (vtzero::geometry_exception&) {
|
||||
}
|
||||
|
||||
{
|
||||
vtzero::linestring_feature_builder fbuilder{lbuilder};
|
||||
fbuilder.set_id(3);
|
||||
fbuilder.add_linestring(2);
|
||||
fbuilder.set_point(10, 20);
|
||||
fbuilder.set_point(20, 10);
|
||||
fbuilder.commit();
|
||||
}
|
||||
|
||||
const std::string data = tbuilder.serialize();
|
||||
|
||||
vtzero::vector_tile tile{data};
|
||||
|
||||
auto layer = tile.next_layer();
|
||||
REQUIRE(layer);
|
||||
REQUIRE(layer.name() == "test");
|
||||
REQUIRE(layer.num_features() == 2);
|
||||
|
||||
auto feature = layer.next_feature();
|
||||
REQUIRE(feature.id() == 1);
|
||||
feature = layer.next_feature();
|
||||
REQUIRE(feature.id() == 3);
|
||||
}
|
||||
|
||||
+279
@@ -0,0 +1,279 @@
|
||||
|
||||
#include <test.hpp>
|
||||
|
||||
#include <vtzero/builder.hpp>
|
||||
#include <vtzero/geometry.hpp>
|
||||
#include <vtzero/index.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
struct point_handler {
|
||||
|
||||
std::vector<vtzero::point> data;
|
||||
|
||||
void points_begin(uint32_t count) {
|
||||
data.reserve(count);
|
||||
}
|
||||
|
||||
void points_point(const vtzero::point point) {
|
||||
data.push_back(point);
|
||||
}
|
||||
|
||||
void points_end() const noexcept {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
static void test_point_builder(bool with_id, bool with_prop) {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
|
||||
{
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
|
||||
if (with_id) {
|
||||
fbuilder.set_id(17);
|
||||
}
|
||||
|
||||
SECTION("add point using coordinates / property using key/value") {
|
||||
fbuilder.add_point(10, 20);
|
||||
if (with_prop) {
|
||||
fbuilder.add_property("foo", vtzero::encoded_property_value{"bar"});
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("add point using vtzero::point / property using key/value") {
|
||||
fbuilder.add_point(vtzero::point{10, 20});
|
||||
if (with_prop) {
|
||||
fbuilder.add_property("foo", vtzero::encoded_property_value{22});
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("add point using mypoint / property using property") {
|
||||
vtzero::encoded_property_value pv{3.5};
|
||||
vtzero::property p{"foo", vtzero::property_value{pv.data()}};
|
||||
fbuilder.add_point(mypoint{10, 20});
|
||||
if (with_prop) {
|
||||
fbuilder.add_property(p);
|
||||
}
|
||||
}
|
||||
|
||||
fbuilder.commit();
|
||||
}
|
||||
|
||||
const std::string data = tbuilder.serialize();
|
||||
|
||||
vtzero::vector_tile tile{data};
|
||||
|
||||
auto layer = tile.next_layer();
|
||||
REQUIRE(layer.name() == "test");
|
||||
REQUIRE(layer.version() == 2);
|
||||
REQUIRE(layer.extent() == 4096);
|
||||
REQUIRE(layer.num_features() == 1);
|
||||
|
||||
const auto feature = layer.next_feature();
|
||||
REQUIRE(feature.id() == (with_id ? 17 : 0));
|
||||
|
||||
point_handler handler;
|
||||
vtzero::decode_point_geometry(feature.geometry(), handler);
|
||||
|
||||
const std::vector<vtzero::point> result = {{10, 20}};
|
||||
REQUIRE(handler.data == result);
|
||||
}
|
||||
|
||||
TEST_CASE("Point builder without id/without properties") {
|
||||
test_point_builder(false, false);
|
||||
}
|
||||
|
||||
TEST_CASE("Point builder without id/with properties") {
|
||||
test_point_builder(false, true);
|
||||
}
|
||||
|
||||
TEST_CASE("Point builder with id/without properties") {
|
||||
test_point_builder(true, false);
|
||||
}
|
||||
|
||||
TEST_CASE("Point builder with id/with properties") {
|
||||
test_point_builder(true, true);
|
||||
}
|
||||
|
||||
TEST_CASE("Calling add_points() with bad values throws assert") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
|
||||
SECTION("0") {
|
||||
REQUIRE_THROWS_AS(fbuilder.add_points(0), const assert_error&);
|
||||
}
|
||||
SECTION("2^29") {
|
||||
REQUIRE_THROWS_AS(fbuilder.add_points(1ul << 29u), const assert_error&);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_multipoint_builder(bool with_id, bool with_prop) {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
|
||||
if (with_id) {
|
||||
fbuilder.set_id(17);
|
||||
}
|
||||
|
||||
fbuilder.add_points(3);
|
||||
fbuilder.set_point(10, 20);
|
||||
fbuilder.set_point(vtzero::point{20, 30});
|
||||
fbuilder.set_point(mypoint{30, 40});
|
||||
|
||||
if (with_prop) {
|
||||
fbuilder.add_property("foo", vtzero::encoded_property_value{"bar"});
|
||||
}
|
||||
|
||||
fbuilder.commit();
|
||||
|
||||
const std::string data = tbuilder.serialize();
|
||||
|
||||
vtzero::vector_tile tile{data};
|
||||
|
||||
auto layer = tile.next_layer();
|
||||
REQUIRE(layer.name() == "test");
|
||||
REQUIRE(layer.version() == 2);
|
||||
REQUIRE(layer.extent() == 4096);
|
||||
REQUIRE(layer.num_features() == 1);
|
||||
|
||||
const auto feature = layer.next_feature();
|
||||
REQUIRE(feature.id() == (with_id ? 17 : 0));
|
||||
|
||||
point_handler handler;
|
||||
vtzero::decode_point_geometry(feature.geometry(), handler);
|
||||
|
||||
const std::vector<vtzero::point> result = {{10, 20}, {20, 30}, {30, 40}};
|
||||
REQUIRE(handler.data == result);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("Multipoint builder without id/without properties") {
|
||||
test_multipoint_builder(false, false);
|
||||
}
|
||||
|
||||
TEST_CASE("Multipoint builder without id/with properties") {
|
||||
test_multipoint_builder(false, true);
|
||||
}
|
||||
|
||||
TEST_CASE("Multipoint builder with id/without properties") {
|
||||
test_multipoint_builder(true, false);
|
||||
}
|
||||
|
||||
TEST_CASE("Multipoint builder with id/with properties") {
|
||||
test_multipoint_builder(true, true);
|
||||
}
|
||||
|
||||
TEST_CASE("Calling add_point() and then other geometry functions throws assert") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
|
||||
fbuilder.add_point(10, 20);
|
||||
|
||||
SECTION("add_point()") {
|
||||
REQUIRE_THROWS_AS(fbuilder.add_point(10, 20), const assert_error&);
|
||||
}
|
||||
SECTION("add_points()") {
|
||||
REQUIRE_THROWS_AS(fbuilder.add_points(2), const assert_error&);
|
||||
}
|
||||
SECTION("set_point()") {
|
||||
REQUIRE_THROWS_AS(fbuilder.set_point(10, 10), const assert_error&);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Calling point_feature_builder::set_point() throws assert") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
|
||||
REQUIRE_THROWS_AS(fbuilder.set_point(10, 10), const assert_error&);
|
||||
}
|
||||
|
||||
TEST_CASE("Calling add_points() and then other geometry functions throws assert") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
|
||||
fbuilder.add_points(2);
|
||||
|
||||
SECTION("add_point()") {
|
||||
REQUIRE_THROWS_AS(fbuilder.add_point(10, 20), const assert_error&);
|
||||
}
|
||||
SECTION("add_points()") {
|
||||
REQUIRE_THROWS_AS(fbuilder.add_points(2), const assert_error&);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Calling point_feature_builder::set_point() too often throws assert") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
|
||||
fbuilder.add_points(2);
|
||||
fbuilder.set_point(10, 20);
|
||||
fbuilder.set_point(20, 20);
|
||||
REQUIRE_THROWS_AS(fbuilder.set_point(30, 20), const assert_error&);
|
||||
}
|
||||
|
||||
TEST_CASE("Add points from container") {
|
||||
const std::vector<vtzero::point> points = {{10, 20}, {20, 30}, {30, 40}};
|
||||
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
|
||||
{
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
|
||||
/* SECTION("using iterators") {
|
||||
fbuilder.add_points(points.cbegin(), points.cend());
|
||||
}
|
||||
|
||||
SECTION("using iterators and size") {
|
||||
fbuilder.add_points(points.cbegin(), points.cend(), static_cast<uint32_t>(points.size()));
|
||||
}*/
|
||||
|
||||
SECTION("using container directly") {
|
||||
fbuilder.add_points_from_container(points);
|
||||
}
|
||||
|
||||
fbuilder.commit();
|
||||
}
|
||||
|
||||
const std::string data = tbuilder.serialize();
|
||||
|
||||
vtzero::vector_tile tile{data};
|
||||
|
||||
auto layer = tile.next_layer();
|
||||
REQUIRE(layer);
|
||||
REQUIRE(layer.name() == "test");
|
||||
REQUIRE(layer.version() == 2);
|
||||
REQUIRE(layer.extent() == 4096);
|
||||
REQUIRE(layer.num_features() == 1);
|
||||
|
||||
const auto feature = layer.next_feature();
|
||||
|
||||
point_handler handler;
|
||||
vtzero::decode_point_geometry(feature.geometry(), handler);
|
||||
|
||||
REQUIRE(handler.data == points);
|
||||
}
|
||||
/*
|
||||
TEST_CASE("Add points from iterator with wrong count throws assert") {
|
||||
const std::vector<vtzero::point> points = {{10, 20}, {20, 30}, {30, 40}};
|
||||
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
|
||||
REQUIRE_THROWS_AS(fbuilder.add_points(points.cbegin(),
|
||||
points.cend(),
|
||||
static_cast<uint32_t>(points.size() + 1)), const assert_error&);
|
||||
}*/
|
||||
|
||||
+307
@@ -0,0 +1,307 @@
|
||||
|
||||
#include <test.hpp>
|
||||
|
||||
#include <vtzero/builder.hpp>
|
||||
#include <vtzero/geometry.hpp>
|
||||
#include <vtzero/index.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
using polygon_type = std::vector<std::vector<vtzero::point>>;
|
||||
|
||||
struct polygon_handler {
|
||||
|
||||
polygon_type data;
|
||||
|
||||
void ring_begin(uint32_t count) {
|
||||
data.emplace_back();
|
||||
data.back().reserve(count);
|
||||
}
|
||||
|
||||
void ring_point(const vtzero::point point) {
|
||||
data.back().push_back(point);
|
||||
}
|
||||
|
||||
void ring_end(vtzero::ring_type /* type */) const noexcept {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
static void test_polygon_builder(bool with_id, bool with_prop) {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
|
||||
{
|
||||
vtzero::polygon_feature_builder fbuilder{lbuilder};
|
||||
|
||||
if (with_id) {
|
||||
fbuilder.set_id(17);
|
||||
}
|
||||
|
||||
fbuilder.add_ring(4);
|
||||
fbuilder.set_point(10, 20);
|
||||
fbuilder.set_point(vtzero::point{20, 30});
|
||||
fbuilder.set_point(mypoint{30, 40});
|
||||
fbuilder.set_point(10, 20);
|
||||
|
||||
if (with_prop) {
|
||||
fbuilder.add_property("foo", "bar");
|
||||
}
|
||||
|
||||
fbuilder.commit();
|
||||
}
|
||||
|
||||
const std::string data = tbuilder.serialize();
|
||||
|
||||
vtzero::vector_tile tile{data};
|
||||
|
||||
auto layer = tile.next_layer();
|
||||
REQUIRE(layer.name() == "test");
|
||||
REQUIRE(layer.version() == 2);
|
||||
REQUIRE(layer.extent() == 4096);
|
||||
REQUIRE(layer.num_features() == 1);
|
||||
|
||||
const auto feature = layer.next_feature();
|
||||
REQUIRE(feature.id() == (with_id ? 17 : 0));
|
||||
|
||||
polygon_handler handler;
|
||||
vtzero::decode_polygon_geometry(feature.geometry(), handler);
|
||||
|
||||
const polygon_type result = {{{10, 20}, {20, 30}, {30, 40}, {10, 20}}};
|
||||
REQUIRE(handler.data == result);
|
||||
}
|
||||
|
||||
TEST_CASE("polygon builder without id/without properties") {
|
||||
test_polygon_builder(false, false);
|
||||
}
|
||||
|
||||
TEST_CASE("polygon builder without id/with properties") {
|
||||
test_polygon_builder(false, true);
|
||||
}
|
||||
|
||||
TEST_CASE("polygon builder with id/without properties") {
|
||||
test_polygon_builder(true, false);
|
||||
}
|
||||
|
||||
TEST_CASE("polygon builder with id/with properties") {
|
||||
test_polygon_builder(true, true);
|
||||
}
|
||||
|
||||
TEST_CASE("Calling add_ring() with bad values throws assert") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::polygon_feature_builder fbuilder{lbuilder};
|
||||
|
||||
SECTION("0") {
|
||||
REQUIRE_THROWS_AS(fbuilder.add_ring(0), const assert_error&);
|
||||
}
|
||||
SECTION("1") {
|
||||
REQUIRE_THROWS_AS(fbuilder.add_ring(1), const assert_error&);
|
||||
}
|
||||
SECTION("2") {
|
||||
REQUIRE_THROWS_AS(fbuilder.add_ring(2), const assert_error&);
|
||||
}
|
||||
SECTION("3") {
|
||||
REQUIRE_THROWS_AS(fbuilder.add_ring(3), const assert_error&);
|
||||
}
|
||||
SECTION("2^29") {
|
||||
REQUIRE_THROWS_AS(fbuilder.add_ring(1ul << 29u), const assert_error&);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_multipolygon_builder(bool with_id, bool with_prop) {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::polygon_feature_builder fbuilder{lbuilder};
|
||||
|
||||
if (with_id) {
|
||||
fbuilder.set_id(17);
|
||||
}
|
||||
|
||||
fbuilder.add_ring(4);
|
||||
fbuilder.set_point(10, 20);
|
||||
fbuilder.set_point(vtzero::point{20, 30});
|
||||
fbuilder.set_point(mypoint{30, 40});
|
||||
fbuilder.set_point(10, 20);
|
||||
|
||||
fbuilder.add_ring(5);
|
||||
fbuilder.set_point(1, 1);
|
||||
fbuilder.set_point(2, 1);
|
||||
fbuilder.set_point(2, 2);
|
||||
fbuilder.set_point(1, 2);
|
||||
|
||||
if (with_id) {
|
||||
fbuilder.set_point(1, 1);
|
||||
} else {
|
||||
fbuilder.close_ring();
|
||||
}
|
||||
|
||||
if (with_prop) {
|
||||
fbuilder.add_property("foo", vtzero::encoded_property_value{"bar"});
|
||||
}
|
||||
|
||||
fbuilder.commit();
|
||||
|
||||
const std::string data = tbuilder.serialize();
|
||||
|
||||
vtzero::vector_tile tile{data};
|
||||
|
||||
auto layer = tile.next_layer();
|
||||
REQUIRE(layer.name() == "test");
|
||||
REQUIRE(layer.version() == 2);
|
||||
REQUIRE(layer.extent() == 4096);
|
||||
REQUIRE(layer.num_features() == 1);
|
||||
|
||||
const auto feature = layer.next_feature();
|
||||
REQUIRE(feature.id() == (with_id ? 17 : 0));
|
||||
|
||||
polygon_handler handler;
|
||||
vtzero::decode_polygon_geometry(feature.geometry(), handler);
|
||||
|
||||
const polygon_type result = {{{10, 20}, {20, 30}, {30, 40}, {10, 20}},
|
||||
{{1, 1}, {2, 1}, {2, 2}, {1, 2}, {1, 1}}};
|
||||
REQUIRE(handler.data == result);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("Multipolygon builder without id/without properties") {
|
||||
test_multipolygon_builder(false, false);
|
||||
}
|
||||
|
||||
TEST_CASE("Multipolygon builder without id/with properties") {
|
||||
test_multipolygon_builder(false, true);
|
||||
}
|
||||
|
||||
TEST_CASE("Multipolygon builder with id/without properties") {
|
||||
test_multipolygon_builder(true, false);
|
||||
}
|
||||
|
||||
TEST_CASE("Multipolygon builder with id/with properties") {
|
||||
test_multipolygon_builder(true, true);
|
||||
}
|
||||
|
||||
TEST_CASE("Calling add_ring() twice throws assert") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::polygon_feature_builder fbuilder{lbuilder};
|
||||
|
||||
fbuilder.add_ring(4);
|
||||
REQUIRE_ASSERT(fbuilder.add_ring(4));
|
||||
}
|
||||
|
||||
TEST_CASE("Calling polygon_feature_builder::set_point()/close_ring() throws assert") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::polygon_feature_builder fbuilder{lbuilder};
|
||||
|
||||
SECTION("set_point") {
|
||||
REQUIRE_THROWS_AS(fbuilder.set_point(10, 10), const assert_error&);
|
||||
}
|
||||
SECTION("close_ring") {
|
||||
REQUIRE_THROWS_AS(fbuilder.close_ring(), const assert_error&);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Calling polygon_feature_builder::set_point()/close_ring() too often throws assert") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::polygon_feature_builder fbuilder{lbuilder};
|
||||
|
||||
fbuilder.add_ring(4);
|
||||
fbuilder.set_point(10, 20);
|
||||
fbuilder.set_point(20, 20);
|
||||
fbuilder.set_point(30, 20);
|
||||
fbuilder.set_point(10, 20);
|
||||
|
||||
SECTION("set_point") {
|
||||
REQUIRE_THROWS_AS(fbuilder.set_point(50, 20), const assert_error&);
|
||||
}
|
||||
SECTION("close_ring") {
|
||||
REQUIRE_THROWS_AS(fbuilder.close_ring(), const assert_error&);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Calling polygon_feature_builder::set_point() with same point throws") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::polygon_feature_builder fbuilder{lbuilder};
|
||||
|
||||
fbuilder.add_ring(4);
|
||||
fbuilder.set_point(10, 10);
|
||||
REQUIRE_THROWS_AS(fbuilder.set_point(10, 10), const vtzero::geometry_exception&);
|
||||
}
|
||||
|
||||
TEST_CASE("Calling polygon_feature_builder::set_point() creating unclosed ring throws") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::polygon_feature_builder fbuilder{lbuilder};
|
||||
|
||||
fbuilder.add_ring(4);
|
||||
fbuilder.set_point(10, 10);
|
||||
fbuilder.set_point(10, 20);
|
||||
fbuilder.set_point(20, 20);
|
||||
REQUIRE_THROWS_AS(fbuilder.set_point(20, 30), const vtzero::geometry_exception&);
|
||||
}
|
||||
|
||||
TEST_CASE("Add polygon from container") {
|
||||
const polygon_type points = {{{10, 20}, {20, 30}, {30, 40}, {10, 20}}};
|
||||
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
|
||||
{
|
||||
vtzero::polygon_feature_builder fbuilder{lbuilder};
|
||||
|
||||
#if 0
|
||||
SECTION("using iterators") {
|
||||
fbuilder.add_ring(points[0].cbegin(), points[0].cend());
|
||||
}
|
||||
|
||||
SECTION("using iterators and size") {
|
||||
fbuilder.add_ring(points[0].cbegin(), points[0].cend(), static_cast<uint32_t>(points[0].size()));
|
||||
}
|
||||
#endif
|
||||
|
||||
SECTION("using container directly") {
|
||||
fbuilder.add_ring_from_container(points[0]);
|
||||
}
|
||||
|
||||
fbuilder.commit();
|
||||
}
|
||||
|
||||
const std::string data = tbuilder.serialize();
|
||||
|
||||
vtzero::vector_tile tile{data};
|
||||
|
||||
auto layer = tile.next_layer();
|
||||
REQUIRE(layer);
|
||||
REQUIRE(layer.name() == "test");
|
||||
REQUIRE(layer.version() == 2);
|
||||
REQUIRE(layer.extent() == 4096);
|
||||
REQUIRE(layer.num_features() == 1);
|
||||
|
||||
const auto feature = layer.next_feature();
|
||||
|
||||
polygon_handler handler;
|
||||
vtzero::decode_polygon_geometry(feature.geometry(), handler);
|
||||
|
||||
REQUIRE(handler.data == points);
|
||||
}
|
||||
|
||||
#if 0
|
||||
TEST_CASE("Add polygon from iterator with wrong count throws assert") {
|
||||
const std::vector<vtzero::point> points = {{10, 20}, {20, 30}, {30, 40}, {10, 20}};
|
||||
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::polygon_feature_builder fbuilder{lbuilder};
|
||||
|
||||
REQUIRE_THROWS_AS(fbuilder.add_ring(points.cbegin(),
|
||||
points.cend(),
|
||||
static_cast<uint32_t>(points.size() + 1)), const assert_error&);
|
||||
}
|
||||
#endif
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
|
||||
#include <test.hpp>
|
||||
|
||||
#include <vtzero/exception.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
TEST_CASE("construct format_exception with const char*") {
|
||||
vtzero::format_exception e{"broken"};
|
||||
REQUIRE(std::string{e.what()} == "broken");
|
||||
}
|
||||
|
||||
TEST_CASE("construct format_exception with const std::string") {
|
||||
vtzero::format_exception e{std::string{"broken"}};
|
||||
REQUIRE(std::string{e.what()} == "broken");
|
||||
}
|
||||
|
||||
TEST_CASE("construct geometry_exception with const char*") {
|
||||
vtzero::geometry_exception e{"broken"};
|
||||
REQUIRE(std::string{e.what()} == "broken");
|
||||
}
|
||||
|
||||
TEST_CASE("construct geometry_exception with std::string") {
|
||||
vtzero::geometry_exception e{std::string{"broken"}};
|
||||
REQUIRE(std::string{e.what()} == "broken");
|
||||
}
|
||||
|
||||
TEST_CASE("construct type_exception") {
|
||||
vtzero::type_exception e;
|
||||
REQUIRE(std::string{e.what()} == "wrong property value type");
|
||||
}
|
||||
|
||||
TEST_CASE("construct version_exception") {
|
||||
vtzero::version_exception e{42};
|
||||
REQUIRE(std::string{e.what()} == "unknown vector tile version: 42");
|
||||
}
|
||||
|
||||
TEST_CASE("construct out_of_range_exception") {
|
||||
vtzero::out_of_range_exception e{99};
|
||||
REQUIRE(std::string{e.what()} == "index out of range: 99");
|
||||
}
|
||||
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
|
||||
#include <test.hpp>
|
||||
|
||||
#include <vtzero/feature.hpp>
|
||||
#include <vtzero/layer.hpp>
|
||||
#include <vtzero/vector_tile.hpp>
|
||||
|
||||
TEST_CASE("default constructed feature") {
|
||||
vtzero::feature feature{};
|
||||
|
||||
REQUIRE_FALSE(feature.valid());
|
||||
REQUIRE_FALSE(feature);
|
||||
REQUIRE(feature.id() == 0);
|
||||
REQUIRE_FALSE(feature.has_id());
|
||||
REQUIRE(feature.geometry_type() == vtzero::GeomType::UNKNOWN);
|
||||
REQUIRE_ASSERT(feature.geometry());
|
||||
REQUIRE(feature.empty());
|
||||
REQUIRE(feature.num_properties() == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("read a feature") {
|
||||
const auto data = load_test_tile();
|
||||
vtzero::vector_tile tile{data};
|
||||
|
||||
auto layer = tile.get_layer_by_name("bridge");
|
||||
REQUIRE(layer.valid());
|
||||
|
||||
auto feature = layer.next_feature();
|
||||
REQUIRE(feature.valid());
|
||||
REQUIRE(feature);
|
||||
REQUIRE(feature.id() == 0);
|
||||
REQUIRE(feature.has_id());
|
||||
REQUIRE(feature.geometry_type() == vtzero::GeomType::LINESTRING);
|
||||
REQUIRE_FALSE(feature.empty());
|
||||
REQUIRE(feature.num_properties() == 4);
|
||||
}
|
||||
|
||||
TEST_CASE("iterate over all properties of a feature") {
|
||||
const auto data = load_test_tile();
|
||||
vtzero::vector_tile tile{data};
|
||||
auto layer = tile.get_layer_by_name("bridge");
|
||||
auto feature = layer.next_feature();
|
||||
|
||||
int count = 0;
|
||||
SECTION("external iterator") {
|
||||
while (auto p = feature.next_property()) {
|
||||
++count;
|
||||
if (p.key() == "type") {
|
||||
REQUIRE(p.value().type() == vtzero::property_value_type::string_value);
|
||||
REQUIRE(p.value().string_value() == "primary");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("internal iterator") {
|
||||
feature.for_each_property([&count](const vtzero::property& p) {
|
||||
++count;
|
||||
if (p.key() == "type") {
|
||||
REQUIRE(p.value().type() == vtzero::property_value_type::string_value);
|
||||
REQUIRE(p.value().string_value() == "primary");
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
REQUIRE(count == 4);
|
||||
}
|
||||
|
||||
TEST_CASE("iterate over some properties of a feature") {
|
||||
const auto data = load_test_tile();
|
||||
vtzero::vector_tile tile{data};
|
||||
auto layer = tile.get_layer_by_name("bridge");
|
||||
REQUIRE(layer.valid());
|
||||
|
||||
auto feature = layer.next_feature();
|
||||
REQUIRE(feature.valid());
|
||||
|
||||
int count = 0;
|
||||
SECTION("external iterator") {
|
||||
while (auto p = feature.next_property()) {
|
||||
++count;
|
||||
if (p.key() == "oneway") {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("internal iterator") {
|
||||
feature.for_each_property([&count](const vtzero::property& p) {
|
||||
++count;
|
||||
return p.key() != "oneway";
|
||||
});
|
||||
}
|
||||
|
||||
REQUIRE(count == 2);
|
||||
}
|
||||
|
||||
+334
@@ -0,0 +1,334 @@
|
||||
|
||||
#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&);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
|
||||
#include <test.hpp>
|
||||
|
||||
#include <vtzero/geometry.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
using container = std::vector<uint32_t>;
|
||||
using iterator = container::const_iterator;
|
||||
|
||||
class dummy_geom_handler {
|
||||
|
||||
int value = 0;
|
||||
|
||||
public:
|
||||
|
||||
void linestring_begin(const uint32_t /*count*/) noexcept {
|
||||
++value;
|
||||
}
|
||||
|
||||
void linestring_point(const vtzero::point /*point*/) noexcept {
|
||||
value += 100;
|
||||
}
|
||||
|
||||
void linestring_end() noexcept {
|
||||
value += 10000;
|
||||
}
|
||||
|
||||
int result() const noexcept {
|
||||
return value;
|
||||
}
|
||||
|
||||
}; // class dummy_geom_handler
|
||||
|
||||
TEST_CASE("Calling decode_linestring_geometry() with empty input") {
|
||||
const container g;
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
dummy_geom_handler handler;
|
||||
decoder.decode_linestring(dummy_geom_handler{});
|
||||
REQUIRE(handler.result() == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_linestring_geometry() with a valid linestring") {
|
||||
const container g = {9, 4, 4, 18, 0, 16, 16, 0};
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
REQUIRE(decoder.decode_linestring(dummy_geom_handler{}) == 10301);
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_linestring_geometry() with a valid multilinestring") {
|
||||
const container g = {9, 4, 4, 18, 0, 16, 16, 0, 9, 17, 17, 10, 4, 8};
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
dummy_geom_handler handler;
|
||||
decoder.decode_linestring(handler);
|
||||
REQUIRE(handler.result() == 20502);
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_linestring_geometry() with a point geometry fails") {
|
||||
const container g = {9, 50, 34}; // this is a point geometry
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
SECTION("check exception type") {
|
||||
REQUIRE_THROWS_AS(decoder.decode_linestring(dummy_geom_handler{}),
|
||||
const vtzero::geometry_exception&);
|
||||
}
|
||||
SECTION("check exception message") {
|
||||
REQUIRE_THROWS_WITH(decoder.decode_linestring(dummy_geom_handler{}),
|
||||
"expected LineTo command (spec 4.3.4.3)");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_linestring_geometry() with a polygon geometry fails") {
|
||||
const container g = {9, 6, 12, 18, 10, 12, 24, 44, 15}; // this is a polygon geometry
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
SECTION("check exception type") {
|
||||
REQUIRE_THROWS_AS(decoder.decode_linestring(dummy_geom_handler{}),
|
||||
const vtzero::geometry_exception&);
|
||||
}
|
||||
SECTION("check exception message") {
|
||||
REQUIRE_THROWS_WITH(decoder.decode_linestring(dummy_geom_handler{}),
|
||||
"expected command 1 but got 7");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_linestring_geometry() with something other than MoveTo command") {
|
||||
const container g = {vtzero::detail::command_line_to(3)};
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
SECTION("check exception type") {
|
||||
REQUIRE_THROWS_AS(decoder.decode_linestring(dummy_geom_handler{}),
|
||||
const vtzero::geometry_exception&);
|
||||
}
|
||||
SECTION("check exception message") {
|
||||
REQUIRE_THROWS_WITH(decoder.decode_linestring(dummy_geom_handler{}),
|
||||
"expected command 1 but got 2");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_linestring_geometry() with a count of 0") {
|
||||
const container g = {vtzero::detail::command_move_to(0)};
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
SECTION("check exception type") {
|
||||
REQUIRE_THROWS_AS(decoder.decode_linestring(dummy_geom_handler{}),
|
||||
const vtzero::geometry_exception&);
|
||||
}
|
||||
SECTION("check exception message") {
|
||||
REQUIRE_THROWS_WITH(decoder.decode_linestring(dummy_geom_handler{}),
|
||||
"MoveTo command count is not 1 (spec 4.3.4.3)");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_linestring_geometry() with a count of 2") {
|
||||
const container g = {vtzero::detail::command_move_to(2), 10, 20, 20, 10};
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
SECTION("check exception type") {
|
||||
REQUIRE_THROWS_AS(decoder.decode_linestring(dummy_geom_handler{}),
|
||||
const vtzero::geometry_exception&);
|
||||
}
|
||||
SECTION("check exception message") {
|
||||
REQUIRE_THROWS_WITH(decoder.decode_linestring(dummy_geom_handler{}),
|
||||
"MoveTo command count is not 1 (spec 4.3.4.3)");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_linestring_geometry() with 2nd command not a LineTo") {
|
||||
const container g = {vtzero::detail::command_move_to(1), 3, 4,
|
||||
vtzero::detail::command_move_to(1)};
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
SECTION("check exception type") {
|
||||
REQUIRE_THROWS_AS(decoder.decode_linestring(dummy_geom_handler{}),
|
||||
const vtzero::geometry_exception&);
|
||||
}
|
||||
SECTION("check exception message") {
|
||||
REQUIRE_THROWS_WITH(decoder.decode_linestring(dummy_geom_handler{}),
|
||||
"expected command 2 but got 1");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_linestring_geometry() with LineTo and 0 count") {
|
||||
const container g = {vtzero::detail::command_move_to(1), 3, 4,
|
||||
vtzero::detail::command_line_to(0)};
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
SECTION("check exception type") {
|
||||
REQUIRE_THROWS_AS(decoder.decode_linestring(dummy_geom_handler{}),
|
||||
const vtzero::geometry_exception&);
|
||||
}
|
||||
SECTION("check exception message") {
|
||||
REQUIRE_THROWS_WITH(decoder.decode_linestring(dummy_geom_handler{}),
|
||||
"LineTo command count is zero (spec 4.3.4.3)");
|
||||
}
|
||||
}
|
||||
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
|
||||
#include <test.hpp>
|
||||
|
||||
#include <vtzero/geometry.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
using container = std::vector<uint32_t>;
|
||||
using iterator = container::const_iterator;
|
||||
|
||||
class dummy_geom_handler {
|
||||
|
||||
int value = 0;
|
||||
|
||||
public:
|
||||
|
||||
void points_begin(const uint32_t /*count*/) noexcept {
|
||||
++value;
|
||||
}
|
||||
|
||||
void points_point(const vtzero::point /*point*/) noexcept {
|
||||
value += 100;
|
||||
}
|
||||
|
||||
void points_end() noexcept {
|
||||
value += 10000;
|
||||
}
|
||||
|
||||
int result() const noexcept {
|
||||
return value;
|
||||
}
|
||||
|
||||
}; // class dummy_geom_handler
|
||||
|
||||
TEST_CASE("Calling decode_point() with empty input") {
|
||||
const container g;
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
SECTION("check exception type") {
|
||||
REQUIRE_THROWS_AS(decoder.decode_point(dummy_geom_handler{}),
|
||||
const vtzero::geometry_exception&);
|
||||
}
|
||||
SECTION("check exception message") {
|
||||
REQUIRE_THROWS_WITH(decoder.decode_point(dummy_geom_handler{}),
|
||||
"expected MoveTo command (spec 4.3.4.2)");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_point() with a valid point") {
|
||||
const container g = {9, 50, 34};
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
dummy_geom_handler handler;
|
||||
decoder.decode_point(handler);
|
||||
REQUIRE(handler.result() == 10101);
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_point() with a valid multipoint") {
|
||||
const container g = {17, 10, 14, 3, 9};
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
REQUIRE(decoder.decode_point(dummy_geom_handler{}) == 10201);
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_point() with a linestring geometry fails") {
|
||||
const container g = {9, 4, 4, 18, 0, 16, 16, 0}; // this is a linestring geometry
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
SECTION("check exception type") {
|
||||
REQUIRE_THROWS_AS(decoder.decode_point(dummy_geom_handler{}),
|
||||
const vtzero::geometry_exception&);
|
||||
}
|
||||
SECTION("check exception message") {
|
||||
REQUIRE_THROWS_WITH(decoder.decode_point(dummy_geom_handler{}),
|
||||
"additional data after end of geometry (spec 4.3.4.2)");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_point() with a polygon geometry fails") {
|
||||
const container g = {9, 6, 12, 18, 10, 12, 24, 44, 15}; // this is a polygon geometry
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
SECTION("check exception type") {
|
||||
REQUIRE_THROWS_AS(decoder.decode_point(dummy_geom_handler{}),
|
||||
const vtzero::geometry_exception&);
|
||||
}
|
||||
SECTION("check exception message") {
|
||||
REQUIRE_THROWS_WITH(decoder.decode_point(dummy_geom_handler{}),
|
||||
"additional data after end of geometry (spec 4.3.4.2)");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_point() with something other than MoveTo command") {
|
||||
const container g = {vtzero::detail::command_line_to(3)};
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
SECTION("check exception type") {
|
||||
REQUIRE_THROWS_AS(decoder.decode_point(dummy_geom_handler{}),
|
||||
const vtzero::geometry_exception&);
|
||||
}
|
||||
SECTION("check exception message") {
|
||||
REQUIRE_THROWS_WITH(decoder.decode_point(dummy_geom_handler{}),
|
||||
"expected command 1 but got 2");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_point() with a count of 0") {
|
||||
const container g = {vtzero::detail::command_move_to(0)};
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
SECTION("check exception type") {
|
||||
REQUIRE_THROWS_AS(decoder.decode_point(dummy_geom_handler{}),
|
||||
const vtzero::geometry_exception&);
|
||||
}
|
||||
SECTION("check exception message") {
|
||||
REQUIRE_THROWS_WITH(decoder.decode_point(dummy_geom_handler{}),
|
||||
"MoveTo command count is zero (spec 4.3.4.2)");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_point() with more data then expected") {
|
||||
const container g = {9, 50, 34, 9};
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
SECTION("check exception type") {
|
||||
REQUIRE_THROWS_AS(decoder.decode_point(dummy_geom_handler{}),
|
||||
const vtzero::geometry_exception&);
|
||||
}
|
||||
SECTION("check exception message") {
|
||||
REQUIRE_THROWS_WITH(decoder.decode_point(dummy_geom_handler{}),
|
||||
"additional data after end of geometry (spec 4.3.4.2)");
|
||||
}
|
||||
}
|
||||
|
||||
+204
@@ -0,0 +1,204 @@
|
||||
|
||||
#include <test.hpp>
|
||||
|
||||
#include <vtzero/geometry.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
using container = std::vector<uint32_t>;
|
||||
using iterator = container::const_iterator;
|
||||
|
||||
class dummy_geom_handler {
|
||||
|
||||
int value = 0;
|
||||
|
||||
public:
|
||||
|
||||
void ring_begin(const uint32_t /*count*/) noexcept {
|
||||
++value;
|
||||
}
|
||||
|
||||
void ring_point(const vtzero::point /*point*/) noexcept {
|
||||
value += 100;
|
||||
}
|
||||
|
||||
void ring_end(vtzero::ring_type /*is_outer*/) noexcept {
|
||||
value += 10000;
|
||||
}
|
||||
|
||||
int result() const noexcept {
|
||||
return value;
|
||||
}
|
||||
|
||||
}; // class dummy_geom_handler
|
||||
|
||||
TEST_CASE("Calling decode_polygon_geometry() with empty input") {
|
||||
const container g;
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
dummy_geom_handler handler;
|
||||
decoder.decode_polygon(dummy_geom_handler{});
|
||||
REQUIRE(handler.result() == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_polygon_geometry() with a valid polygon") {
|
||||
const container g = {9, 6, 12, 18, 10, 12, 24, 44, 15};
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
REQUIRE(decoder.decode_polygon(dummy_geom_handler{}) == 10401);
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_polygon_geometry() with a duplicate end point") {
|
||||
const container g = {9, 6, 12, 26, 10, 12, 24, 44, 33, 55, 15};
|
||||
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
dummy_geom_handler handler;
|
||||
decoder.decode_polygon(handler);
|
||||
REQUIRE(handler.result() == 10501);
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_polygon_geometry() with a valid 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<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
dummy_geom_handler handler;
|
||||
decoder.decode_polygon(handler);
|
||||
REQUIRE(handler.result() == 31503);
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_polygon_geometry() with a point geometry fails") {
|
||||
const container g = {9, 50, 34}; // this is a point geometry
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
SECTION("check exception type") {
|
||||
REQUIRE_THROWS_AS(decoder.decode_polygon(dummy_geom_handler{}),
|
||||
const vtzero::geometry_exception&);
|
||||
}
|
||||
SECTION("check exception message") {
|
||||
REQUIRE_THROWS_WITH(decoder.decode_polygon(dummy_geom_handler{}),
|
||||
"expected LineTo command (spec 4.3.4.4)");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_polygon_geometry() with a linestring geometry fails") {
|
||||
const container g = {9, 4, 4, 18, 0, 16, 16, 0}; // this is a linestring geometry
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
SECTION("check exception type") {
|
||||
REQUIRE_THROWS_AS(decoder.decode_polygon(dummy_geom_handler{}),
|
||||
const vtzero::geometry_exception&);
|
||||
}
|
||||
SECTION("check exception message") {
|
||||
REQUIRE_THROWS_WITH(decoder.decode_polygon(dummy_geom_handler{}),
|
||||
"expected ClosePath command (4.3.4.4)");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_polygon_geometry() with something other than MoveTo command") {
|
||||
const container g = {vtzero::detail::command_line_to(3)};
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
SECTION("check exception type") {
|
||||
REQUIRE_THROWS_AS(decoder.decode_polygon(dummy_geom_handler{}),
|
||||
const vtzero::geometry_exception&);
|
||||
}
|
||||
SECTION("check exception message") {
|
||||
REQUIRE_THROWS_WITH(decoder.decode_polygon(dummy_geom_handler{}),
|
||||
"expected command 1 but got 2");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_polygon_geometry() with a count of 0") {
|
||||
const container g = {vtzero::detail::command_move_to(0)};
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
SECTION("check exception type") {
|
||||
REQUIRE_THROWS_AS(decoder.decode_polygon(dummy_geom_handler{}),
|
||||
const vtzero::geometry_exception&);
|
||||
}
|
||||
SECTION("check exception message") {
|
||||
REQUIRE_THROWS_WITH(decoder.decode_polygon(dummy_geom_handler{}),
|
||||
"MoveTo command count is not 1 (spec 4.3.4.4)");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_polygon_geometry() with a count of 2") {
|
||||
const container g = {vtzero::detail::command_move_to(2), 1, 2, 3, 4};
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
SECTION("check exception type") {
|
||||
REQUIRE_THROWS_AS(decoder.decode_polygon(dummy_geom_handler{}),
|
||||
const vtzero::geometry_exception&);
|
||||
}
|
||||
SECTION("check exception message") {
|
||||
REQUIRE_THROWS_WITH(decoder.decode_polygon(dummy_geom_handler{}),
|
||||
"MoveTo command count is not 1 (spec 4.3.4.4)");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_polygon_geometry() with 2nd command not a LineTo") {
|
||||
const container g = {vtzero::detail::command_move_to(1), 3, 4,
|
||||
vtzero::detail::command_move_to(1)};
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
SECTION("check exception type") {
|
||||
REQUIRE_THROWS_AS(decoder.decode_polygon(dummy_geom_handler{}),
|
||||
const vtzero::geometry_exception&);
|
||||
}
|
||||
SECTION("check exception message") {
|
||||
REQUIRE_THROWS_WITH(decoder.decode_polygon(dummy_geom_handler{}),
|
||||
"expected command 2 but got 1");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_polygon_geometry() with LineTo and 0 count") {
|
||||
const container g = {vtzero::detail::command_move_to(1), 3, 4,
|
||||
vtzero::detail::command_line_to(0),
|
||||
vtzero::detail::command_close_path()};
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
dummy_geom_handler handler;
|
||||
decoder.decode_polygon(handler);
|
||||
REQUIRE(handler.result() == 10201);
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_polygon_geometry() with LineTo and 1 count") {
|
||||
const container g = {vtzero::detail::command_move_to(1), 3, 4,
|
||||
vtzero::detail::command_line_to(1), 5, 6,
|
||||
vtzero::detail::command_close_path()};
|
||||
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
dummy_geom_handler handler;
|
||||
decoder.decode_polygon(handler);
|
||||
REQUIRE(handler.result() == 10301);
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_polygon_geometry() with 3nd command not a ClosePath") {
|
||||
const container g = {vtzero::detail::command_move_to(1), 3, 4,
|
||||
vtzero::detail::command_line_to(2), 4, 5, 6, 7,
|
||||
vtzero::detail::command_line_to(0)};
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
|
||||
SECTION("check exception type") {
|
||||
REQUIRE_THROWS_AS(decoder.decode_polygon(dummy_geom_handler{}),
|
||||
const vtzero::geometry_exception&);
|
||||
}
|
||||
SECTION("check exception message") {
|
||||
REQUIRE_THROWS_WITH(decoder.decode_polygon(dummy_geom_handler{}),
|
||||
"expected command 7 but got 2");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Calling decode_polygon_geometry() on polygon with zero area") {
|
||||
const container g = {vtzero::detail::command_move_to(1), 0, 0,
|
||||
vtzero::detail::command_line_to(3), 2, 0, 0, 4, 2, 0,
|
||||
vtzero::detail::command_close_path()};
|
||||
|
||||
vtzero::detail::geometry_decoder<container::const_iterator> decoder{g.begin(), g.end(), g.size() / 2};
|
||||
dummy_geom_handler handler;
|
||||
decoder.decode_polygon(handler);
|
||||
REQUIRE(handler.result() == 10501);
|
||||
}
|
||||
|
||||
+343
@@ -0,0 +1,343 @@
|
||||
|
||||
#include <test.hpp>
|
||||
|
||||
#include <vtzero/builder.hpp>
|
||||
#include <vtzero/index.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
TEST_CASE("add keys to layer using key index built into layer") {
|
||||
static constexpr const int max_keys = 100;
|
||||
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
|
||||
for (int n = 0; n < max_keys; ++n) {
|
||||
const auto key = std::to_string(n);
|
||||
const auto idx = lbuilder.add_key(key);
|
||||
REQUIRE(n == idx.value());
|
||||
}
|
||||
|
||||
for (int n = 0; n < max_keys; n += 2) {
|
||||
const auto key = std::to_string(n);
|
||||
const auto idx = lbuilder.add_key(key);
|
||||
REQUIRE(n == idx.value());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("add values to layer using value index built into layer") {
|
||||
static constexpr const int max_values = 100;
|
||||
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
|
||||
for (int n = 0; n < max_values; ++n) {
|
||||
const auto value = std::to_string(n);
|
||||
const auto idx = lbuilder.add_value(vtzero::encoded_property_value{value});
|
||||
REQUIRE(n == idx.value());
|
||||
}
|
||||
|
||||
for (int n = 0; n < max_values; n += 2) {
|
||||
const auto value = std::to_string(n);
|
||||
const auto idx = lbuilder.add_value(vtzero::encoded_property_value{value});
|
||||
REQUIRE(n == idx.value());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TIndex>
|
||||
static void test_key_index() {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
TIndex index{lbuilder};
|
||||
|
||||
const auto i1 = index({"foo"});
|
||||
const auto i2 = index({"bar"});
|
||||
const auto i3 = index({"baz"});
|
||||
const auto i4 = index({"foo"});
|
||||
const auto i5 = index({"foo"});
|
||||
const auto i6 = index({""});
|
||||
const auto i7 = index({"bar"});
|
||||
|
||||
REQUIRE(i1 != i2);
|
||||
REQUIRE(i1 != i3);
|
||||
REQUIRE(i1 == i4);
|
||||
REQUIRE(i1 == i5);
|
||||
REQUIRE(i1 != i6);
|
||||
REQUIRE(i1 != i7);
|
||||
REQUIRE(i2 != i3);
|
||||
REQUIRE(i2 != i4);
|
||||
REQUIRE(i2 != i5);
|
||||
REQUIRE(i2 != i6);
|
||||
REQUIRE(i2 == i7);
|
||||
REQUIRE(i3 != i4);
|
||||
REQUIRE(i3 != i5);
|
||||
REQUIRE(i3 != i6);
|
||||
REQUIRE(i3 != i7);
|
||||
REQUIRE(i4 == i5);
|
||||
REQUIRE(i4 != i6);
|
||||
REQUIRE(i4 != i7);
|
||||
REQUIRE(i5 != i6);
|
||||
REQUIRE(i5 != i7);
|
||||
REQUIRE(i6 != i7);
|
||||
}
|
||||
|
||||
TEST_CASE("key index based on std::unordered_map") {
|
||||
test_key_index<vtzero::key_index<std::unordered_map>>();
|
||||
}
|
||||
|
||||
TEST_CASE("key index based on std::map") {
|
||||
test_key_index<vtzero::key_index<std::map>>();
|
||||
}
|
||||
|
||||
template <typename TIndex>
|
||||
static void test_value_index_internal() {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
TIndex index{lbuilder};
|
||||
|
||||
const auto i1 = index(vtzero::encoded_property_value{"foo"});
|
||||
const auto i2 = index(vtzero::encoded_property_value{"bar"});
|
||||
const auto i3 = index(vtzero::encoded_property_value{88});
|
||||
const auto i4 = index(vtzero::encoded_property_value{"foo"});
|
||||
const auto i5 = index(vtzero::encoded_property_value{77});
|
||||
const auto i6 = index(vtzero::encoded_property_value{1.5});
|
||||
const auto i7 = index(vtzero::encoded_property_value{"bar"});
|
||||
|
||||
REQUIRE(i1 != i2);
|
||||
REQUIRE(i1 != i3);
|
||||
REQUIRE(i1 == i4);
|
||||
REQUIRE(i1 != i5);
|
||||
REQUIRE(i1 != i6);
|
||||
REQUIRE(i1 != i7);
|
||||
|
||||
REQUIRE(i2 != i3);
|
||||
REQUIRE(i2 != i4);
|
||||
REQUIRE(i2 != i5);
|
||||
REQUIRE(i2 != i6);
|
||||
REQUIRE(i2 == i7);
|
||||
|
||||
REQUIRE(i3 != i4);
|
||||
REQUIRE(i3 != i5);
|
||||
REQUIRE(i3 != i6);
|
||||
REQUIRE(i3 != i7);
|
||||
|
||||
REQUIRE(i4 != i5);
|
||||
REQUIRE(i4 != i6);
|
||||
REQUIRE(i4 != i7);
|
||||
|
||||
REQUIRE(i5 != i6);
|
||||
REQUIRE(i5 != i7);
|
||||
|
||||
REQUIRE(i6 != i7);
|
||||
}
|
||||
|
||||
TEST_CASE("internal value index based on std::unordered_map") {
|
||||
test_value_index_internal<vtzero::value_index_internal<std::unordered_map>>();
|
||||
}
|
||||
|
||||
TEST_CASE("internal value index based on std::map") {
|
||||
test_value_index_internal<vtzero::value_index_internal<std::map>>();
|
||||
}
|
||||
|
||||
TEST_CASE("external value index") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
|
||||
vtzero::value_index<vtzero::string_value_type, std::string, std::map> string_index{lbuilder};
|
||||
vtzero::value_index<vtzero::int_value_type, int, std::unordered_map> int_index{lbuilder};
|
||||
vtzero::value_index<vtzero::sint_value_type, int, std::unordered_map> sint_index{lbuilder};
|
||||
|
||||
const auto i1 = string_index("foo");
|
||||
const auto i2 = string_index("bar");
|
||||
const auto i3 = int_index(6);
|
||||
const auto i4 = sint_index(6);
|
||||
const auto i5 = string_index(std::string{"foo"});
|
||||
const auto i6 = int_index(6);
|
||||
const auto i7 = sint_index(2);
|
||||
const auto i8 = sint_index(5);
|
||||
const auto i9 = sint_index(6);
|
||||
|
||||
REQUIRE(i1 != i2);
|
||||
REQUIRE(i1 != i3);
|
||||
REQUIRE(i1 != i4);
|
||||
REQUIRE(i1 == i5);
|
||||
REQUIRE(i1 != i6);
|
||||
REQUIRE(i1 != i7);
|
||||
REQUIRE(i1 != i7);
|
||||
REQUIRE(i1 != i9);
|
||||
|
||||
REQUIRE(i2 != i3);
|
||||
REQUIRE(i2 != i4);
|
||||
REQUIRE(i2 != i5);
|
||||
REQUIRE(i2 != i6);
|
||||
REQUIRE(i2 != i7);
|
||||
REQUIRE(i2 != i8);
|
||||
REQUIRE(i2 != i9);
|
||||
|
||||
REQUIRE(i3 != i4);
|
||||
REQUIRE(i3 != i5);
|
||||
REQUIRE(i3 == i6);
|
||||
REQUIRE(i3 != i7);
|
||||
REQUIRE(i3 != i8);
|
||||
REQUIRE(i3 != i9);
|
||||
|
||||
REQUIRE(i4 != i5);
|
||||
REQUIRE(i4 != i6);
|
||||
REQUIRE(i4 != i7);
|
||||
REQUIRE(i4 != i8);
|
||||
REQUIRE(i4 == i9);
|
||||
|
||||
REQUIRE(i5 != i6);
|
||||
REQUIRE(i5 != i7);
|
||||
REQUIRE(i5 != i8);
|
||||
REQUIRE(i5 != i9);
|
||||
|
||||
REQUIRE(i6 != i7);
|
||||
REQUIRE(i6 != i8);
|
||||
REQUIRE(i6 != i9);
|
||||
|
||||
REQUIRE(i7 != i8);
|
||||
REQUIRE(i7 != i9);
|
||||
|
||||
REQUIRE(i8 != i9);
|
||||
}
|
||||
|
||||
TEST_CASE("bool value index") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::value_index_bool index{lbuilder};
|
||||
|
||||
const auto i1 = index(false);
|
||||
const auto i2 = index(true);
|
||||
const auto i3 = index(true);
|
||||
const auto i4 = index(false);
|
||||
|
||||
REQUIRE(i1 != i2);
|
||||
REQUIRE(i1 != i3);
|
||||
REQUIRE(i1 == i4);
|
||||
|
||||
REQUIRE(i2 == i3);
|
||||
REQUIRE(i2 != i4);
|
||||
|
||||
REQUIRE(i3 != i4);
|
||||
}
|
||||
|
||||
TEST_CASE("small unsigned int value index") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
vtzero::value_index_small_uint index{lbuilder};
|
||||
|
||||
const auto i1 = index(12);
|
||||
const auto i2 = index(4);
|
||||
const auto i3 = index(0);
|
||||
const auto i4 = index(100);
|
||||
const auto i5 = index(4);
|
||||
const auto i6 = index(12);
|
||||
|
||||
REQUIRE(i1 != i2);
|
||||
REQUIRE(i1 != i3);
|
||||
REQUIRE(i1 != i4);
|
||||
REQUIRE(i1 != i5);
|
||||
REQUIRE(i1 == i6);
|
||||
|
||||
REQUIRE(i2 != i3);
|
||||
REQUIRE(i2 != i4);
|
||||
REQUIRE(i2 == i5);
|
||||
REQUIRE(i2 != i6);
|
||||
|
||||
REQUIRE(i3 != i4);
|
||||
REQUIRE(i3 != i5);
|
||||
REQUIRE(i3 != i6);
|
||||
|
||||
REQUIRE(i4 != i5);
|
||||
REQUIRE(i4 != i6);
|
||||
|
||||
REQUIRE(i5 != i6);
|
||||
}
|
||||
|
||||
TEST_CASE("add features using a key index") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
fbuilder.set_id(7);
|
||||
fbuilder.add_point(10, 20);
|
||||
|
||||
SECTION("no index") {
|
||||
fbuilder.add_property("some_key", 12);
|
||||
}
|
||||
|
||||
SECTION("key index using unordered_map") {
|
||||
vtzero::key_index<std::unordered_map> index{lbuilder};
|
||||
fbuilder.add_property(index("some_key"), 12);
|
||||
}
|
||||
|
||||
SECTION("key index using map") {
|
||||
vtzero::key_index<std::map> index{lbuilder};
|
||||
fbuilder.add_property(index("some_key"), 12);
|
||||
}
|
||||
|
||||
fbuilder.commit();
|
||||
|
||||
const std::string data = tbuilder.serialize();
|
||||
|
||||
// ============
|
||||
|
||||
vtzero::vector_tile tile{data};
|
||||
|
||||
REQUIRE(tile.count_layers() == 1);
|
||||
auto layer = tile.next_layer();
|
||||
REQUIRE(layer.num_features() == 1);
|
||||
auto feature = layer.next_feature();
|
||||
REQUIRE(feature.id() == 7);
|
||||
const auto property = feature.next_property();
|
||||
REQUIRE(property.value().int_value() == 12);
|
||||
}
|
||||
|
||||
TEST_CASE("add features using a value index") {
|
||||
vtzero::tile_builder tbuilder;
|
||||
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
||||
const auto key = lbuilder.add_key("some_key");
|
||||
|
||||
vtzero::point_feature_builder fbuilder{lbuilder};
|
||||
fbuilder.set_id(17);
|
||||
fbuilder.add_point(10, 20);
|
||||
|
||||
SECTION("no index") {
|
||||
fbuilder.add_property(key, vtzero::sint_value_type{12});
|
||||
}
|
||||
|
||||
SECTION("external value index using unordered_map") {
|
||||
vtzero::value_index<vtzero::sint_value_type, int, std::unordered_map> index{lbuilder};
|
||||
fbuilder.add_property(key, index(12));
|
||||
}
|
||||
|
||||
SECTION("external value index using map") {
|
||||
vtzero::value_index<vtzero::sint_value_type, int, std::map> index{lbuilder};
|
||||
fbuilder.add_property(key, index(12));
|
||||
}
|
||||
|
||||
SECTION("property_value_type index") {
|
||||
vtzero::value_index_internal<std::unordered_map> index{lbuilder};
|
||||
fbuilder.add_property(key, index(vtzero::encoded_property_value{vtzero::sint_value_type{12}}));
|
||||
}
|
||||
|
||||
fbuilder.commit();
|
||||
|
||||
const std::string data = tbuilder.serialize();
|
||||
|
||||
// ============
|
||||
|
||||
vtzero::vector_tile tile{data};
|
||||
|
||||
REQUIRE(tile.count_layers() == 1);
|
||||
auto layer = tile.next_layer();
|
||||
REQUIRE(layer.num_features() == 1);
|
||||
auto feature = layer.next_feature();
|
||||
REQUIRE(feature.id() == 17);
|
||||
const auto property = feature.next_property();
|
||||
REQUIRE(property.value().sint_value() == 12);
|
||||
}
|
||||
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
|
||||
#include <test.hpp>
|
||||
|
||||
#include <vtzero/layer.hpp>
|
||||
#include <vtzero/vector_tile.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
TEST_CASE("default constructed layer") {
|
||||
vtzero::layer layer{};
|
||||
REQUIRE_FALSE(layer.valid());
|
||||
REQUIRE_FALSE(layer);
|
||||
|
||||
REQUIRE(layer.data() == vtzero::data_view{});
|
||||
REQUIRE_ASSERT(layer.version());
|
||||
REQUIRE_ASSERT(layer.extent());
|
||||
REQUIRE_ASSERT(layer.name());
|
||||
|
||||
REQUIRE(layer.empty());
|
||||
REQUIRE(layer.num_features() == 0);
|
||||
|
||||
REQUIRE_THROWS_AS(layer.key_table(), const assert_error&);
|
||||
REQUIRE_THROWS_AS(layer.value_table(), const assert_error&);
|
||||
|
||||
REQUIRE_THROWS_AS(layer.key(0), const assert_error&);
|
||||
REQUIRE_THROWS_AS(layer.value(0), const assert_error&);
|
||||
|
||||
REQUIRE_THROWS_AS(layer.get_feature_by_id(0), const assert_error&);
|
||||
REQUIRE_THROWS_AS(layer.next_feature(), const assert_error&);
|
||||
REQUIRE_ASSERT(layer.reset_feature());
|
||||
}
|
||||
|
||||
TEST_CASE("read a layer") {
|
||||
const auto data = load_test_tile();
|
||||
vtzero::vector_tile tile{data};
|
||||
|
||||
auto layer = tile.get_layer_by_name("bridge");
|
||||
REQUIRE(layer.valid());
|
||||
REQUIRE(layer);
|
||||
|
||||
REQUIRE(layer.version() == 1);
|
||||
REQUIRE(layer.extent() == 4096);
|
||||
REQUIRE(layer.name() == "bridge");
|
||||
|
||||
REQUIRE_FALSE(layer.empty());
|
||||
REQUIRE(layer.num_features() == 2);
|
||||
|
||||
const auto& kt = layer.key_table();
|
||||
REQUIRE(kt.size() == 4);
|
||||
REQUIRE(kt[0] == "class");
|
||||
|
||||
const auto& vt = layer.value_table();
|
||||
REQUIRE(vt.size() == 4);
|
||||
REQUIRE(vt[0].type() == vtzero::property_value_type::string_value);
|
||||
REQUIRE(vt[0].string_value() == "main");
|
||||
REQUIRE(vt[1].type() == vtzero::property_value_type::int_value);
|
||||
REQUIRE(vt[1].int_value() == 0);
|
||||
|
||||
REQUIRE(layer.key(0) == "class");
|
||||
REQUIRE(layer.key(1) == "oneway");
|
||||
REQUIRE(layer.key(2) == "osm_id");
|
||||
REQUIRE(layer.key(3) == "type");
|
||||
REQUIRE_THROWS_AS(layer.key(4), const vtzero::out_of_range_exception&);
|
||||
|
||||
REQUIRE(layer.value(0).string_value() == "main");
|
||||
REQUIRE(layer.value(1).int_value() == 0);
|
||||
REQUIRE(layer.value(2).string_value() == "primary");
|
||||
REQUIRE(layer.value(3).string_value() == "tertiary");
|
||||
REQUIRE_THROWS_AS(layer.value(4), const vtzero::out_of_range_exception&);
|
||||
}
|
||||
|
||||
TEST_CASE("access features in a layer by id") {
|
||||
const auto data = load_test_tile();
|
||||
vtzero::vector_tile tile{data};
|
||||
|
||||
auto layer = tile.get_layer_by_name("building");
|
||||
REQUIRE(layer);
|
||||
|
||||
REQUIRE(layer.num_features() == 937);
|
||||
|
||||
const auto feature = layer.get_feature_by_id(122);
|
||||
REQUIRE(feature.id() == 122);
|
||||
REQUIRE(feature.num_properties() == 0);
|
||||
REQUIRE(feature.geometry_type() == vtzero::GeomType::POLYGON);
|
||||
REQUIRE(feature.geometry().type() == vtzero::GeomType::POLYGON);
|
||||
REQUIRE_FALSE(feature.geometry().data().empty());
|
||||
|
||||
REQUIRE_FALSE(layer.get_feature_by_id(844));
|
||||
REQUIRE_FALSE(layer.get_feature_by_id(999999));
|
||||
}
|
||||
|
||||
TEST_CASE("iterate over all features in a layer") {
|
||||
const auto data = load_test_tile();
|
||||
vtzero::vector_tile tile{data};
|
||||
|
||||
auto layer = tile.get_layer_by_name("building");
|
||||
REQUIRE(layer);
|
||||
|
||||
std::size_t count = 0;
|
||||
|
||||
SECTION("external iterator") {
|
||||
while (auto feature = layer.next_feature()) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("internal iterator") {
|
||||
const bool done = layer.for_each_feature([&count](const vtzero::feature& /*feature*/) noexcept {
|
||||
++count;
|
||||
return true;
|
||||
});
|
||||
REQUIRE(done);
|
||||
}
|
||||
|
||||
REQUIRE(count == 937);
|
||||
}
|
||||
|
||||
TEST_CASE("iterate over some features in a layer") {
|
||||
const auto data = load_test_tile();
|
||||
vtzero::vector_tile tile{data};
|
||||
|
||||
auto layer = tile.get_layer_by_name("building");
|
||||
REQUIRE(layer);
|
||||
|
||||
uint64_t id_sum = 0;
|
||||
|
||||
SECTION("external iterator") {
|
||||
while (auto feature = layer.next_feature()) {
|
||||
if (feature.id() == 10) {
|
||||
break;
|
||||
}
|
||||
id_sum += feature.id();
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("internal iterator") {
|
||||
const bool done = layer.for_each_feature([&id_sum](const vtzero::feature& feature) noexcept {
|
||||
if (feature.id() == 10) {
|
||||
return false;
|
||||
}
|
||||
id_sum += feature.id();
|
||||
return true;
|
||||
});
|
||||
REQUIRE_FALSE(done);
|
||||
}
|
||||
|
||||
const uint64_t expected = (10 - 1) * 10 / 2;
|
||||
REQUIRE(id_sum == expected);
|
||||
|
||||
layer.reset_feature();
|
||||
auto feature = layer.next_feature();
|
||||
REQUIRE(feature);
|
||||
REQUIRE(feature.id() == 1);
|
||||
}
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
|
||||
#include <test.hpp>
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
template <typename T>
|
||||
std::string get_output(T v) {
|
||||
std::stringstream ss;
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
TEST_CASE("output GeomType") {
|
||||
REQUIRE(get_output(vtzero::GeomType::UNKNOWN) == "unknown");
|
||||
REQUIRE(get_output(vtzero::GeomType::POINT) == "point");
|
||||
REQUIRE(get_output(vtzero::GeomType::LINESTRING) == "linestring");
|
||||
REQUIRE(get_output(vtzero::GeomType::POLYGON) == "polygon");
|
||||
}
|
||||
|
||||
TEST_CASE("output property_value_type") {
|
||||
REQUIRE(get_output(vtzero::property_value_type::sint_value) == "sint");
|
||||
}
|
||||
|
||||
TEST_CASE("output index_value") {
|
||||
REQUIRE(get_output(vtzero::index_value{}) == "invalid");
|
||||
REQUIRE(get_output(vtzero::index_value{5}) == "5");
|
||||
}
|
||||
|
||||
TEST_CASE("output index_value_pair") {
|
||||
const auto in = vtzero::index_value{};
|
||||
const auto v2 = vtzero::index_value{2};
|
||||
const auto v5 = vtzero::index_value{5};
|
||||
REQUIRE(get_output(vtzero::index_value_pair{in, v2}) == "invalid");
|
||||
REQUIRE(get_output(vtzero::index_value_pair{v2, v5}) == "[2,5]");
|
||||
}
|
||||
|
||||
TEST_CASE("output point") {
|
||||
REQUIRE(get_output(vtzero::point{}) == "(0,0)");
|
||||
REQUIRE(get_output(vtzero::point{4, 7}) == "(4,7)");
|
||||
}
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
|
||||
#include <test.hpp>
|
||||
|
||||
#include <vtzero/geometry.hpp>
|
||||
|
||||
TEST_CASE("default constructed point") {
|
||||
vtzero::point p{};
|
||||
|
||||
REQUIRE(p.x == 0);
|
||||
REQUIRE(p.y == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("point") {
|
||||
vtzero::point p1{4, 5};
|
||||
vtzero::point p2{5, 4};
|
||||
vtzero::point p3{4, 5};
|
||||
|
||||
REQUIRE(p1.x == 4);
|
||||
REQUIRE(p1.y == 5);
|
||||
|
||||
REQUIRE_FALSE(p1 == p2);
|
||||
REQUIRE(p1 != p2);
|
||||
REQUIRE(p1 == p3);
|
||||
}
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
|
||||
#include <test.hpp>
|
||||
|
||||
#include <vtzero/builder.hpp>
|
||||
|
||||
#ifdef VTZERO_TEST_WITH_VARIANT
|
||||
# include <boost/variant.hpp>
|
||||
using variant_type = boost::variant<std::string, float, double, int64_t, uint64_t, bool>;
|
||||
#endif
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
TEST_CASE("property map") {
|
||||
vtzero::tile_builder tile;
|
||||
vtzero::layer_builder layer_points{tile, "points"};
|
||||
{
|
||||
vtzero::point_feature_builder fbuilder{layer_points};
|
||||
fbuilder.set_id(1);
|
||||
fbuilder.add_points(1);
|
||||
fbuilder.set_point(10, 10);
|
||||
fbuilder.add_property("foo", "bar");
|
||||
fbuilder.add_property("x", "y");
|
||||
fbuilder.add_property("abc", "def");
|
||||
fbuilder.commit();
|
||||
}
|
||||
|
||||
std::string data = tile.serialize();
|
||||
|
||||
vtzero::vector_tile vt{data};
|
||||
REQUIRE(vt.count_layers() == 1);
|
||||
auto layer = vt.next_layer();
|
||||
REQUIRE(layer.valid());
|
||||
REQUIRE(layer.num_features() == 1);
|
||||
|
||||
const auto feature = layer.next_feature();
|
||||
REQUIRE(feature.valid());
|
||||
REQUIRE(feature.num_properties() == 3);
|
||||
|
||||
#ifdef VTZERO_TEST_WITH_VARIANT
|
||||
SECTION("std::map") {
|
||||
using prop_map_type = std::map<std::string, variant_type>;
|
||||
auto map = vtzero::create_properties_map<prop_map_type>(feature);
|
||||
|
||||
REQUIRE(map.size() == 3);
|
||||
REQUIRE(boost::get<std::string>(map["foo"]) == "bar");
|
||||
REQUIRE(boost::get<std::string>(map["x"]) == "y");
|
||||
REQUIRE(boost::get<std::string>(map["abc"]) == "def");
|
||||
}
|
||||
SECTION("std::unordered_map") {
|
||||
using prop_map_type = std::unordered_map<std::string, variant_type>;
|
||||
auto map = vtzero::create_properties_map<prop_map_type>(feature);
|
||||
|
||||
REQUIRE(map.size() == 3);
|
||||
REQUIRE(boost::get<std::string>(map["foo"]) == "bar");
|
||||
REQUIRE(boost::get<std::string>(map["x"]) == "y");
|
||||
REQUIRE(boost::get<std::string>(map["abc"]) == "def");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
+407
@@ -0,0 +1,407 @@
|
||||
|
||||
#include <test.hpp>
|
||||
|
||||
#include <vtzero/encoded_property_value.hpp>
|
||||
#include <vtzero/property.hpp>
|
||||
#include <vtzero/property_value.hpp>
|
||||
#include <vtzero/types.hpp>
|
||||
|
||||
#ifdef VTZERO_TEST_WITH_VARIANT
|
||||
# include <boost/variant.hpp>
|
||||
using variant_type = boost::variant<std::string, float, double, int64_t, uint64_t, bool>;
|
||||
|
||||
struct variant_mapping : vtzero::property_value_mapping {
|
||||
using float_type = int64_t;
|
||||
using double_type = int64_t;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
struct visitor_test_void {
|
||||
|
||||
int x = 0;
|
||||
|
||||
template <typename T>
|
||||
void operator()(T /*value*/) {
|
||||
x = 1;
|
||||
}
|
||||
|
||||
void operator()(vtzero::data_view /*value*/) {
|
||||
x = 2;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct visitor_test_int {
|
||||
|
||||
template <typename T>
|
||||
int operator()(T /*value*/) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int operator()(vtzero::data_view /*value*/) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct visitor_test_to_string {
|
||||
|
||||
template <typename T>
|
||||
std::string operator()(T value) {
|
||||
return std::to_string(value);
|
||||
}
|
||||
|
||||
std::string operator()(vtzero::data_view value) {
|
||||
return std::string{value.data(), value.size()};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct string_conv {
|
||||
|
||||
std::string s;
|
||||
|
||||
template <typename T>
|
||||
explicit string_conv(T value) :
|
||||
s(std::to_string(value)) {
|
||||
}
|
||||
|
||||
explicit operator std::string() {
|
||||
return s;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct string_mapping : vtzero::property_value_mapping {
|
||||
using string_type = std::string;
|
||||
using float_type = string_conv;
|
||||
using double_type = string_conv;
|
||||
using int_type = string_conv;
|
||||
using uint_type = string_conv;
|
||||
using bool_type = string_conv;
|
||||
};
|
||||
|
||||
TEST_CASE("default constructed property_value") {
|
||||
vtzero::property_value pv;
|
||||
REQUIRE_FALSE(pv.valid());
|
||||
REQUIRE(pv.data().data() == nullptr);
|
||||
|
||||
REQUIRE(pv == vtzero::property_value{});
|
||||
REQUIRE_FALSE(pv != vtzero::property_value{});
|
||||
}
|
||||
|
||||
TEST_CASE("empty property_value") {
|
||||
char x[1] = {0};
|
||||
vtzero::data_view dv{x, 0};
|
||||
vtzero::property_value pv{dv};
|
||||
REQUIRE(pv.valid());
|
||||
REQUIRE_THROWS_AS(pv.type(), const vtzero::format_exception&);
|
||||
}
|
||||
|
||||
TEST_CASE("string value") {
|
||||
vtzero::encoded_property_value epv{"foo"};
|
||||
vtzero::property_value pv{epv.data()};
|
||||
REQUIRE(pv.string_value() == "foo");
|
||||
|
||||
visitor_test_void vt;
|
||||
vtzero::apply_visitor(vt, pv);
|
||||
REQUIRE(vt.x == 2);
|
||||
|
||||
const auto result = vtzero::apply_visitor(visitor_test_int{}, pv);
|
||||
REQUIRE(result == 2);
|
||||
|
||||
const auto str = vtzero::apply_visitor(visitor_test_to_string{}, pv);
|
||||
REQUIRE(str == "foo");
|
||||
|
||||
const std::string cs = vtzero::convert_property_value<std::string, string_mapping>(pv);
|
||||
REQUIRE(cs == "foo");
|
||||
|
||||
#ifdef VTZERO_TEST_WITH_VARIANT
|
||||
const auto vari = vtzero::convert_property_value<variant_type>(pv);
|
||||
REQUIRE(boost::get<std::string>(vari) == "foo");
|
||||
const auto conv = vtzero::convert_property_value<variant_type, variant_mapping>(pv);
|
||||
REQUIRE(boost::get<std::string>(conv) == "foo");
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_CASE("float value") {
|
||||
vtzero::encoded_property_value epv{1.2f};
|
||||
vtzero::property_value pv{epv.data()};
|
||||
REQUIRE(pv.float_value() == Approx(1.2));
|
||||
|
||||
visitor_test_void vt;
|
||||
vtzero::apply_visitor(vt, pv);
|
||||
REQUIRE(vt.x == 1);
|
||||
|
||||
const auto result = vtzero::apply_visitor(visitor_test_int{}, pv);
|
||||
REQUIRE(result == 1);
|
||||
|
||||
const std::string cs = vtzero::convert_property_value<std::string, string_mapping>(pv);
|
||||
REQUIRE(cs == "1.200000");
|
||||
|
||||
#ifdef VTZERO_TEST_WITH_VARIANT
|
||||
const auto vari = vtzero::convert_property_value<variant_type>(pv);
|
||||
REQUIRE(boost::get<float>(vari) == Approx(1.2));
|
||||
const auto conv = vtzero::convert_property_value<variant_type, variant_mapping>(pv);
|
||||
REQUIRE(boost::get<int64_t>(conv) == 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_CASE("double value") {
|
||||
vtzero::encoded_property_value epv{3.4};
|
||||
vtzero::property_value pv{epv.data()};
|
||||
REQUIRE(pv.double_value() == Approx(3.4));
|
||||
|
||||
const auto result = vtzero::apply_visitor(visitor_test_int{}, pv);
|
||||
REQUIRE(result == 1);
|
||||
|
||||
const std::string cs = vtzero::convert_property_value<std::string, string_mapping>(pv);
|
||||
REQUIRE(cs == "3.400000");
|
||||
}
|
||||
|
||||
TEST_CASE("int value") {
|
||||
vtzero::encoded_property_value epv{vtzero::int_value_type{42}};
|
||||
vtzero::property_value pv{epv.data()};
|
||||
REQUIRE(pv.int_value() == 42);
|
||||
|
||||
const auto str = vtzero::apply_visitor(visitor_test_to_string{}, pv);
|
||||
REQUIRE(str == "42");
|
||||
|
||||
const std::string cs = vtzero::convert_property_value<std::string, string_mapping>(pv);
|
||||
REQUIRE(cs == "42");
|
||||
}
|
||||
|
||||
TEST_CASE("uint value") {
|
||||
vtzero::encoded_property_value epv{vtzero::uint_value_type{99}};
|
||||
vtzero::property_value pv{epv.data()};
|
||||
REQUIRE(pv.uint_value() == 99);
|
||||
|
||||
const auto str = vtzero::apply_visitor(visitor_test_to_string{}, pv);
|
||||
REQUIRE(str == "99");
|
||||
|
||||
const std::string cs = vtzero::convert_property_value<std::string, string_mapping>(pv);
|
||||
REQUIRE(cs == "99");
|
||||
}
|
||||
|
||||
TEST_CASE("sint value") {
|
||||
vtzero::encoded_property_value epv{vtzero::sint_value_type{42}};
|
||||
vtzero::property_value pv{epv.data()};
|
||||
REQUIRE(pv.sint_value() == 42);
|
||||
|
||||
const auto str = vtzero::apply_visitor(visitor_test_to_string{}, pv);
|
||||
REQUIRE(str == "42");
|
||||
|
||||
const std::string cs = vtzero::convert_property_value<std::string, string_mapping>(pv);
|
||||
REQUIRE(cs == "42");
|
||||
}
|
||||
|
||||
TEST_CASE("bool value") {
|
||||
vtzero::encoded_property_value epv{true};
|
||||
vtzero::property_value pv{epv.data()};
|
||||
REQUIRE(pv.bool_value());
|
||||
|
||||
const auto str = vtzero::apply_visitor(visitor_test_to_string{}, pv);
|
||||
REQUIRE(str == "1");
|
||||
|
||||
const std::string cs = vtzero::convert_property_value<std::string, string_mapping>(pv);
|
||||
REQUIRE(cs == "1");
|
||||
}
|
||||
|
||||
TEST_CASE("property and property_value equality comparisons") {
|
||||
vtzero::encoded_property_value t{true};
|
||||
vtzero::encoded_property_value f{false};
|
||||
vtzero::encoded_property_value v1{vtzero::int_value_type{1}};
|
||||
vtzero::encoded_property_value vs{"foo"};
|
||||
|
||||
REQUIRE(t == t);
|
||||
REQUIRE_FALSE(t != t);
|
||||
REQUIRE_FALSE(t == f);
|
||||
REQUIRE_FALSE(t == v1);
|
||||
REQUIRE_FALSE(t == vs);
|
||||
|
||||
using pv = vtzero::property_value;
|
||||
REQUIRE(pv{t.data()} == pv{t.data()});
|
||||
REQUIRE_FALSE(pv{t.data()} != pv{t.data()});
|
||||
REQUIRE_FALSE(pv{t.data()} == pv{f.data()});
|
||||
REQUIRE_FALSE(pv{t.data()} == pv{v1.data()});
|
||||
REQUIRE_FALSE(pv{t.data()} == pv{vs.data()});
|
||||
}
|
||||
|
||||
TEST_CASE("property and property_value ordering") {
|
||||
using pv = vtzero::property_value;
|
||||
|
||||
vtzero::encoded_property_value t{true};
|
||||
vtzero::encoded_property_value f{false};
|
||||
|
||||
REQUIRE_FALSE(t < f);
|
||||
REQUIRE_FALSE(t <= f);
|
||||
REQUIRE(t > f);
|
||||
REQUIRE(t >= f);
|
||||
|
||||
REQUIRE_FALSE(pv{t.data()} < pv{f.data()});
|
||||
REQUIRE_FALSE(pv{t.data()} <= pv{f.data()});
|
||||
REQUIRE(pv{t.data()} > pv{f.data()});
|
||||
REQUIRE(pv{t.data()} >= pv{f.data()});
|
||||
|
||||
vtzero::encoded_property_value v1{vtzero::int_value_type{22}};
|
||||
vtzero::encoded_property_value v2{vtzero::int_value_type{17}};
|
||||
|
||||
REQUIRE_FALSE(v1 < v2);
|
||||
REQUIRE_FALSE(v1 <= v2);
|
||||
REQUIRE(v1 > v2);
|
||||
REQUIRE(v1 >= v2);
|
||||
|
||||
REQUIRE_FALSE(pv{v1.data()} < pv{v2.data()});
|
||||
REQUIRE_FALSE(pv{v1.data()} <= pv{v2.data()});
|
||||
REQUIRE(pv{v1.data()} > pv{v2.data()});
|
||||
REQUIRE(pv{v1.data()} >= pv{v2.data()});
|
||||
|
||||
vtzero::encoded_property_value vsf{"foo"};
|
||||
vtzero::encoded_property_value vsb{"bar"};
|
||||
vtzero::encoded_property_value vsx{"foobar"};
|
||||
|
||||
REQUIRE_FALSE(vsf < vsb);
|
||||
REQUIRE_FALSE(vsf <= vsb);
|
||||
REQUIRE(vsf > vsb);
|
||||
REQUIRE(vsf >= vsb);
|
||||
|
||||
REQUIRE_FALSE(pv{vsf.data()} < pv{vsb.data()});
|
||||
REQUIRE_FALSE(pv{vsf.data()} <= pv{vsb.data()});
|
||||
REQUIRE(pv{vsf.data()} > pv{vsb.data()});
|
||||
REQUIRE(pv{vsf.data()} >= pv{vsb.data()});
|
||||
|
||||
REQUIRE(vsf < vsx);
|
||||
REQUIRE(vsf <= vsx);
|
||||
REQUIRE_FALSE(vsf > vsx);
|
||||
REQUIRE_FALSE(vsf >= vsx);
|
||||
|
||||
REQUIRE(pv{vsf.data()} < pv{vsx.data()});
|
||||
REQUIRE(pv{vsf.data()} <= pv{vsx.data()});
|
||||
REQUIRE_FALSE(pv{vsf.data()} > pv{vsx.data()});
|
||||
REQUIRE_FALSE(pv{vsf.data()} >= pv{vsx.data()});
|
||||
}
|
||||
|
||||
TEST_CASE("default constructed property") {
|
||||
vtzero::property p;
|
||||
REQUIRE_FALSE(p.valid());
|
||||
REQUIRE_FALSE(p);
|
||||
REQUIRE(p.key().data() == nullptr);
|
||||
REQUIRE(p.value().data().data() == nullptr);
|
||||
}
|
||||
|
||||
TEST_CASE("valid property") {
|
||||
vtzero::data_view k{"key"};
|
||||
vtzero::encoded_property_value epv{"value"};
|
||||
vtzero::property_value pv{epv.data()};
|
||||
|
||||
vtzero::property p{k, pv};
|
||||
REQUIRE(p.key() == "key");
|
||||
REQUIRE(p.value().string_value() == "value");
|
||||
}
|
||||
|
||||
TEST_CASE("create encoded property values from different string types") {
|
||||
const std::string v{"value"};
|
||||
|
||||
vtzero::encoded_property_value epv1{vtzero::string_value_type{"value"}};
|
||||
vtzero::encoded_property_value epv2{"value"};
|
||||
vtzero::encoded_property_value epv3{v};
|
||||
vtzero::encoded_property_value epv4{vtzero::data_view{v}};
|
||||
vtzero::encoded_property_value epv5{"valuexxxxxxxxx", 5};
|
||||
|
||||
REQUIRE(epv1 == epv2);
|
||||
REQUIRE(epv1 == epv3);
|
||||
REQUIRE(epv1 == epv4);
|
||||
REQUIRE(epv1 == epv5);
|
||||
}
|
||||
|
||||
TEST_CASE("create encoded property values from different floating point types") {
|
||||
vtzero::encoded_property_value f1{vtzero::float_value_type{3.2f}};
|
||||
vtzero::encoded_property_value f2{3.2f};
|
||||
vtzero::encoded_property_value d1{vtzero::double_value_type{3.2}};
|
||||
vtzero::encoded_property_value d2{3.2};
|
||||
|
||||
REQUIRE(f1 == f2);
|
||||
REQUIRE(d1 == d2);
|
||||
|
||||
vtzero::property_value pvf{f1.data()};
|
||||
vtzero::property_value pvd{d1.data()};
|
||||
|
||||
REQUIRE(pvf.float_value() == Approx(pvd.double_value()));
|
||||
}
|
||||
|
||||
TEST_CASE("create encoded property values from different integer types") {
|
||||
vtzero::encoded_property_value i1{vtzero::int_value_type{7}};
|
||||
vtzero::encoded_property_value i2{int64_t(7)};
|
||||
vtzero::encoded_property_value i3{int32_t(7)};
|
||||
vtzero::encoded_property_value i4{int16_t(7)};
|
||||
vtzero::encoded_property_value u1{vtzero::uint_value_type{7}};
|
||||
vtzero::encoded_property_value u2{uint64_t(7)};
|
||||
vtzero::encoded_property_value u3{uint32_t(7)};
|
||||
vtzero::encoded_property_value u4{uint16_t(7)};
|
||||
vtzero::encoded_property_value s1{vtzero::sint_value_type{7}};
|
||||
|
||||
REQUIRE(i1 == i2);
|
||||
REQUIRE(i1 == i3);
|
||||
REQUIRE(i1 == i4);
|
||||
REQUIRE(u1 == u2);
|
||||
REQUIRE(u1 == u3);
|
||||
REQUIRE(u1 == u4);
|
||||
|
||||
REQUIRE_FALSE(i1 == u1);
|
||||
REQUIRE_FALSE(i1 == s1);
|
||||
REQUIRE_FALSE(u1 == s1);
|
||||
|
||||
REQUIRE(i1.hash() == i2.hash());
|
||||
REQUIRE(u1.hash() == u2.hash());
|
||||
|
||||
vtzero::property_value pvi{i1.data()};
|
||||
vtzero::property_value pvu{u1.data()};
|
||||
vtzero::property_value pvs{s1.data()};
|
||||
|
||||
REQUIRE(pvi.int_value() == pvu.uint_value());
|
||||
REQUIRE(pvi.int_value() == pvs.sint_value());
|
||||
}
|
||||
|
||||
TEST_CASE("create encoded property values from different bool types") {
|
||||
vtzero::encoded_property_value b1{vtzero::bool_value_type{true}};
|
||||
vtzero::encoded_property_value b2{true};
|
||||
|
||||
REQUIRE(b1 == b2);
|
||||
REQUIRE(b1.hash() == b2.hash());
|
||||
}
|
||||
|
||||
TEST_CASE("property equality comparison operator") {
|
||||
std::string k = "key";
|
||||
|
||||
vtzero::encoded_property_value epv1{"value"};
|
||||
vtzero::encoded_property_value epv2{"another value"};
|
||||
vtzero::property_value pv1{epv1.data()};
|
||||
vtzero::property_value pv2{epv2.data()};
|
||||
|
||||
vtzero::property p1{k, pv1};
|
||||
vtzero::property p2{k, pv1};
|
||||
vtzero::property p3{k, pv2};
|
||||
REQUIRE(p1 == p2);
|
||||
REQUIRE_FALSE(p1 == p3);
|
||||
}
|
||||
|
||||
TEST_CASE("property inequality comparison operator") {
|
||||
std::string k1 = "key";
|
||||
std::string k2 = "another_key";
|
||||
|
||||
vtzero::encoded_property_value epv1{"value"};
|
||||
vtzero::encoded_property_value epv2{"another value"};
|
||||
vtzero::property_value pv1{epv1.data()};
|
||||
vtzero::property_value pv2{epv2.data()};
|
||||
|
||||
vtzero::property p1{k1, pv1};
|
||||
vtzero::property p2{k1, pv1};
|
||||
vtzero::property p3{k1, pv2};
|
||||
vtzero::property p4{k2, pv2};
|
||||
REQUIRE_FALSE(p1 != p2);
|
||||
REQUIRE(p1 != p3);
|
||||
REQUIRE(p3 != p4);
|
||||
}
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
|
||||
#include <test.hpp>
|
||||
|
||||
#include <vtzero/types.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
TEST_CASE("default constructed string_value_type") {
|
||||
vtzero::string_value_type v;
|
||||
REQUIRE(v.value.data() == nullptr);
|
||||
}
|
||||
|
||||
TEST_CASE("string_value_type with value") {
|
||||
vtzero::string_value_type v{"foo"};
|
||||
REQUIRE(v.value.data()[0] == 'f');
|
||||
REQUIRE(v.value.size() == 3);
|
||||
}
|
||||
|
||||
TEST_CASE("default constructed float_value_type") {
|
||||
vtzero::float_value_type v;
|
||||
REQUIRE(v.value == Approx(0.0));
|
||||
}
|
||||
|
||||
TEST_CASE("float_value_type with value") {
|
||||
float x = 2.7f;
|
||||
vtzero::float_value_type v{x};
|
||||
REQUIRE(v.value == Approx(x));
|
||||
}
|
||||
|
||||
TEST_CASE("default constructed double_value_type") {
|
||||
vtzero::double_value_type v;
|
||||
REQUIRE(v.value == Approx(0.0));
|
||||
}
|
||||
|
||||
TEST_CASE("double_value_type with value") {
|
||||
double x = 2.7;
|
||||
vtzero::double_value_type v{x};
|
||||
REQUIRE(v.value == Approx(x));
|
||||
}
|
||||
|
||||
TEST_CASE("default constructed int_value_type") {
|
||||
vtzero::int_value_type v;
|
||||
REQUIRE(v.value == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("int_value_type with value") {
|
||||
vtzero::int_value_type v{123};
|
||||
REQUIRE(v.value == 123);
|
||||
}
|
||||
|
||||
TEST_CASE("default constructed uint_value_type") {
|
||||
vtzero::uint_value_type v;
|
||||
REQUIRE(v.value == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("uint_value_type with value") {
|
||||
vtzero::uint_value_type v{123};
|
||||
REQUIRE(v.value == 123);
|
||||
}
|
||||
|
||||
TEST_CASE("default constructed sint_value_type") {
|
||||
vtzero::sint_value_type v;
|
||||
REQUIRE(v.value == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("sint_value_type with value") {
|
||||
vtzero::sint_value_type v{-14};
|
||||
REQUIRE(v.value == -14);
|
||||
}
|
||||
|
||||
TEST_CASE("default constructed bool_value_type") {
|
||||
vtzero::bool_value_type v;
|
||||
REQUIRE_FALSE(v.value);
|
||||
}
|
||||
|
||||
TEST_CASE("bool_value_type with value") {
|
||||
bool x = true;
|
||||
vtzero::bool_value_type v{x};
|
||||
REQUIRE(v.value);
|
||||
}
|
||||
|
||||
TEST_CASE("property_value_type names") {
|
||||
REQUIRE(std::string{vtzero::property_value_type_name(vtzero::property_value_type::string_value)} == "string");
|
||||
REQUIRE(std::string{vtzero::property_value_type_name(vtzero::property_value_type::float_value)} == "float");
|
||||
REQUIRE(std::string{vtzero::property_value_type_name(vtzero::property_value_type::double_value)} == "double");
|
||||
REQUIRE(std::string{vtzero::property_value_type_name(vtzero::property_value_type::int_value)} == "int");
|
||||
REQUIRE(std::string{vtzero::property_value_type_name(vtzero::property_value_type::uint_value)} == "uint");
|
||||
REQUIRE(std::string{vtzero::property_value_type_name(vtzero::property_value_type::sint_value)} == "sint");
|
||||
REQUIRE(std::string{vtzero::property_value_type_name(vtzero::property_value_type::bool_value)} == "bool");
|
||||
}
|
||||
|
||||
TEST_CASE("default constructed index value") {
|
||||
vtzero::index_value v;
|
||||
REQUIRE_FALSE(v.valid());
|
||||
REQUIRE_ASSERT(v.value());
|
||||
}
|
||||
|
||||
TEST_CASE("valid index value") {
|
||||
vtzero::index_value v{32};
|
||||
REQUIRE(v.valid());
|
||||
REQUIRE(v.value() == 32);
|
||||
}
|
||||
|
||||
TEST_CASE("default constructed geometry") {
|
||||
vtzero::geometry geom;
|
||||
REQUIRE(geom.type() == vtzero::GeomType::UNKNOWN);
|
||||
REQUIRE(geom.data().empty());
|
||||
}
|
||||
|
||||
TEST_CASE("GeomType names") {
|
||||
REQUIRE(std::string{vtzero::geom_type_name(vtzero::GeomType::UNKNOWN)} == "unknown");
|
||||
REQUIRE(std::string{vtzero::geom_type_name(vtzero::GeomType::POINT)} == "point");
|
||||
REQUIRE(std::string{vtzero::geom_type_name(vtzero::GeomType::LINESTRING)} == "linestring");
|
||||
REQUIRE(std::string{vtzero::geom_type_name(vtzero::GeomType::POLYGON)} == "polygon");
|
||||
}
|
||||
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
|
||||
#include <test.hpp>
|
||||
|
||||
#include <vtzero/vector_tile.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
TEST_CASE("open a vector tile with string") {
|
||||
const auto data = load_test_tile();
|
||||
REQUIRE(vtzero::is_vector_tile(data));
|
||||
vtzero::vector_tile tile{data};
|
||||
|
||||
REQUIRE_FALSE(tile.empty());
|
||||
REQUIRE(tile.count_layers() == 12);
|
||||
}
|
||||
|
||||
TEST_CASE("open a vector tile with data_view") {
|
||||
const auto data = load_test_tile();
|
||||
const vtzero::data_view dv{data};
|
||||
vtzero::vector_tile tile{dv};
|
||||
|
||||
REQUIRE_FALSE(tile.empty());
|
||||
REQUIRE(tile.count_layers() == 12);
|
||||
}
|
||||
|
||||
TEST_CASE("open a vector tile with pointer and size") {
|
||||
const auto data = load_test_tile();
|
||||
vtzero::vector_tile tile{data.data(), data.size()};
|
||||
|
||||
REQUIRE_FALSE(tile.empty());
|
||||
REQUIRE(tile.count_layers() == 12);
|
||||
}
|
||||
|
||||
TEST_CASE("get layer by index") {
|
||||
const auto data = load_test_tile();
|
||||
vtzero::vector_tile tile{data};
|
||||
|
||||
auto layer = tile.get_layer(0);
|
||||
REQUIRE(layer);
|
||||
REQUIRE(layer.name() == "landuse");
|
||||
|
||||
layer = tile.get_layer(1);
|
||||
REQUIRE(layer);
|
||||
REQUIRE(layer.name() == "waterway");
|
||||
|
||||
layer = tile.get_layer(11);
|
||||
REQUIRE(layer);
|
||||
REQUIRE(layer.name() == "waterway_label");
|
||||
|
||||
layer = tile.get_layer(12);
|
||||
REQUIRE_FALSE(layer);
|
||||
}
|
||||
|
||||
TEST_CASE("get layer by name") {
|
||||
const auto data = load_test_tile();
|
||||
vtzero::vector_tile tile{data};
|
||||
|
||||
auto layer = tile.get_layer_by_name("landuse");
|
||||
REQUIRE(layer);
|
||||
REQUIRE(layer.name() == "landuse");
|
||||
|
||||
layer = tile.get_layer_by_name(std::string{"road"});
|
||||
REQUIRE(layer);
|
||||
REQUIRE(layer.name() == "road");
|
||||
|
||||
const vtzero::data_view name{"poi_label"};
|
||||
layer = tile.get_layer_by_name(name);
|
||||
REQUIRE(layer);
|
||||
REQUIRE(layer.name() == "poi_label");
|
||||
|
||||
layer = tile.get_layer_by_name("unknown");
|
||||
REQUIRE_FALSE(layer);
|
||||
}
|
||||
|
||||
TEST_CASE("iterate over layers") {
|
||||
const auto data = load_test_tile();
|
||||
vtzero::vector_tile tile{data};
|
||||
|
||||
std::vector<std::string> names;
|
||||
|
||||
SECTION("external iterator") {
|
||||
while (auto layer = tile.next_layer()) {
|
||||
names.emplace_back(layer.name());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("internal iterator") {
|
||||
const bool done = tile.for_each_layer([&names](const vtzero::layer& layer) {
|
||||
names.emplace_back(layer.name());
|
||||
return true;
|
||||
});
|
||||
REQUIRE(done);
|
||||
}
|
||||
|
||||
REQUIRE(names.size() == 12);
|
||||
|
||||
static std::vector<std::string> expected = {
|
||||
"landuse", "waterway", "water", "barrier_line", "building", "road",
|
||||
"bridge", "place_label", "water_label", "poi_label", "road_label",
|
||||
"waterway_label"
|
||||
};
|
||||
|
||||
REQUIRE(names == expected);
|
||||
|
||||
tile.reset_layer();
|
||||
int num = 0;
|
||||
while (auto layer = tile.next_layer()) {
|
||||
++num;
|
||||
}
|
||||
REQUIRE(num == 12);
|
||||
}
|
||||
|
||||
TEST_CASE("iterate over some of the layers") {
|
||||
const auto data = load_test_tile();
|
||||
vtzero::vector_tile tile{data};
|
||||
|
||||
int num_layers = 0;
|
||||
|
||||
SECTION("external iterator") {
|
||||
while (auto layer = tile.next_layer()) {
|
||||
++num_layers;
|
||||
if (layer.name() == "water") {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("internal iterator") {
|
||||
const bool done = tile.for_each_layer([&num_layers](const vtzero::layer& layer) noexcept {
|
||||
++num_layers;
|
||||
return layer.name() != "water";
|
||||
});
|
||||
REQUIRE_FALSE(done);
|
||||
}
|
||||
|
||||
REQUIRE(num_layers == 3);
|
||||
}
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <test.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
bool got_an_assert = false;
|
||||
|
||||
std::string load_test_tile() {
|
||||
std::string path{"data/mapbox-streets-v6-14-8714-8017.mvt"};
|
||||
std::ifstream stream{path, std::ios_base::in|std::ios_base::binary};
|
||||
if (!stream.is_open()) {
|
||||
throw std::runtime_error{"could not open: '" + path + "'"};
|
||||
}
|
||||
|
||||
const std::string message{std::istreambuf_iterator<char>(stream.rdbuf()),
|
||||
std::istreambuf_iterator<char>()};
|
||||
|
||||
stream.close();
|
||||
return message;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user