File test_gpkg.cpp
File List > io > tests > test_gpkg.cpp
Go to the documentation of this file
#include <gtest/gtest.h>
#include <fstream>
#include <set>
#include <vector>
#include "contour/contour.hpp"
#include "io/gpkg.hpp"
#include "polyline/polyline.hpp"
#include "testing/output_dir.hpp"
#include "utilities/coordinate.hpp"
#include "utilities/filesystem.hpp"
#include "utilities/progress_tracker.hpp"
// Test GPKGWriter basic functionality
TEST(GPKG, WriteAndReadContours) {
// Create a temporary file path
fs::path test_file = blaze::test::unique_test_output_path("contours", ".gpkg");
// Clean up if file exists
if (fs::exists(test_file)) {
fs::remove(test_file);
}
// Create a simple projection string (WGS84)
std::string projection =
R"(GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]])";
// Write contours
{
GPKGWriter writer(test_file.string(), projection);
// Create test contours
std::vector<Coordinate2D<double>> points1 = {
Coordinate2D<double>(0.0, 0.0), Coordinate2D<double>(1.0, 0.0),
Coordinate2D<double>(1.0, 1.0), Coordinate2D<double>(0.0, 1.0)};
std::vector<Coordinate2D<double>> points2 = {Coordinate2D<double>(2.0, 2.0),
Coordinate2D<double>(3.0, 2.0),
Coordinate2D<double>(3.0, 3.0)};
Polyline polyline1;
polyline1.layer = "test_layer";
polyline1.name = "contour_1";
polyline1.vertices = points1;
Polyline polyline2;
polyline2.layer = "test_layer";
polyline2.name = "contour_2";
polyline2.vertices = points2;
writer.write_polyline(polyline1, {{"elevation", 10.0}});
writer.write_polyline(polyline2, {{"elevation", 20.0}});
}
// Read contours back
std::vector<Contour> contours = read_gpkg(test_file, ProgressTracker());
// Verify we got the contours back
EXPECT_EQ(contours.size(), 2);
// Check first contour
EXPECT_DOUBLE_EQ(contours[0].height(), 10.0);
EXPECT_EQ(contours[0].points().size(), 4);
// Check second contour
EXPECT_DOUBLE_EQ(contours[1].height(), 20.0);
EXPECT_EQ(contours[1].points().size(), 3);
// Clean up
if (fs::exists(test_file)) {
fs::remove(test_file);
}
}
// Test GPKGWriter with multiple layers
TEST(GPKG, MultipleLayers) {
fs::path test_file = blaze::test::unique_test_output_path("multilayer", ".gpkg");
if (fs::exists(test_file)) {
fs::remove(test_file);
}
std::string projection =
R"(GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]])";
{
GPKGWriter writer(test_file.string(), projection);
Polyline polyline1;
polyline1.layer = "layer1";
polyline1.name = "line1";
polyline1.vertices = {Coordinate2D<double>(0.0, 0.0), Coordinate2D<double>(1.0, 1.0)};
Polyline polyline2;
polyline2.layer = "layer2";
polyline2.name = "line2";
polyline2.vertices = {Coordinate2D<double>(2.0, 2.0), Coordinate2D<double>(3.0, 3.0)};
writer.write_polyline(polyline1);
writer.write_polyline(polyline2);
}
// Read back - should get both layers
std::vector<Contour> contours = read_gpkg(test_file, ProgressTracker());
EXPECT_GE(contours.size(), 2);
if (fs::exists(test_file)) {
fs::remove(test_file);
}
}
// Test GPKGWriter with different field types
TEST(GPKG, DifferentFieldTypes) {
fs::path test_file = blaze::test::unique_test_output_path("fields", ".gpkg");
if (fs::exists(test_file)) {
fs::remove(test_file);
}
std::string projection =
R"(GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]])";
{
GPKGWriter writer(test_file.string(), projection);
Polyline polyline;
polyline.layer = "test";
polyline.name = "test_line";
polyline.vertices = {Coordinate2D<double>(0.0, 0.0), Coordinate2D<double>(1.0, 1.0)};
// Test with int, double, and string fields
writer.write_polyline(
polyline, {{"elevation", 100.0}, {"id", 42}, {"name_str", std::string("test_name")}});
}
// File should exist and be readable
EXPECT_TRUE(fs::exists(test_file));
std::vector<Contour> contours = read_gpkg(test_file, ProgressTracker());
EXPECT_GE(contours.size(), 1);
if (fs::exists(test_file)) {
fs::remove(test_file);
}
}
// Test read_gpkg with non-existent file
TEST(GPKG, ReadNonExistentFile) {
fs::path test_file = blaze::test::unique_test_output_path("nonexistent", ".gpkg");
// Ensure file doesn't exist
if (fs::exists(test_file)) {
fs::remove(test_file);
}
// Should throw an error for non-existent files
EXPECT_THROW(read_gpkg(test_file, ProgressTracker()), std::runtime_error);
}
// Test read_gpkg with empty file (not a valid GPKG)
TEST(GPKG, ReadEmptyFile) {
fs::path test_file = blaze::test::unique_test_output_path("empty", ".gpkg");
if (fs::exists(test_file)) {
fs::remove(test_file);
}
// Create empty file (not a valid GPKG)
std::ofstream ofs(test_file.string());
ofs.close();
// Should throw an error for invalid GPKG files
EXPECT_THROW(read_gpkg(test_file, ProgressTracker()), std::runtime_error);
if (fs::exists(test_file)) {
fs::remove(test_file);
}
}
TEST(GPKG, CombineGpkgs) {
fs::path contours_file = blaze::test::unique_test_output_path("combine_contours", ".gpkg");
fs::path streams_file = blaze::test::unique_test_output_path("combine_streams", ".gpkg");
fs::path output_file = blaze::test::unique_test_output_path("combined_map", ".gpkg");
std::string projection =
R"(GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]])";
{
GPKGWriter writer(contours_file.string(), projection, "Contour");
writer.write_polyline(
Polyline{.layer = "101_Contour", .name = "10", .vertices = {{0, 0}, {1, 0}, {1, 1}}},
{{"elevation", 10.0}});
writer.write_polyline(
Polyline{.layer = "103_Form_Line", .name = "2.5", .vertices = {{2, 0}, {3, 0}, {3, 1}}},
{{"elevation", 2.5}});
}
{
GPKGWriter writer(streams_file.string(), projection, "streams");
writer.write_polyline(
Polyline{.layer = "streams", .name = "0.03", .vertices = {{0, 2}, {1, 2}, {2, 2}}},
{{"catchment", 0.03}});
}
combine_gpkgs({contours_file, streams_file}, output_file, projection, ProgressTracker());
ASSERT_TRUE(fs::exists(output_file));
ensure_gdal_initialized();
GDALDataset* dataset = (GDALDataset*)GDALOpenEx(output_file.string().c_str(), GDAL_OF_VECTOR,
nullptr, nullptr, nullptr);
ASSERT_NE(dataset, nullptr);
std::set<std::string> layer_names;
int feature_count = 0;
for (int i = 0; i < dataset->GetLayerCount(); i++) {
OGRLayer* layer = dataset->GetLayer(i);
if (!layer || layer->GetFeatureCount(false) == 0) continue;
layer_names.insert(layer->GetName());
feature_count += layer->GetFeatureCount(false);
}
GDALClose(dataset);
EXPECT_EQ(feature_count, 3);
EXPECT_TRUE(layer_names.contains("101_Contour"));
EXPECT_TRUE(layer_names.contains("103_Form_Line"));
EXPECT_TRUE(layer_names.contains("streams"));
for (const fs::path& path : {contours_file, streams_file, output_file}) {
if (fs::exists(path)) fs::remove(path);
}
}
TEST(GPKG, CombineGpkgsIncludesVegetationPolygons) {
fs::path contours_file = blaze::test::unique_test_output_path("combine_contours_vege", ".gpkg");
fs::path vegetation_file = blaze::test::unique_test_output_path("combine_vegetation", ".gpkg");
fs::path output_file = blaze::test::unique_test_output_path("combined_map_vege", ".gpkg");
std::string projection =
R"(GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]])";
{
GPKGWriter writer(contours_file.string(), projection, "Contour");
writer.write_polyline(
Polyline{.layer = "101_Contour", .name = "10", .vertices = {{0, 0}, {1, 0}, {1, 1}}},
{{"elevation", 10.0}});
}
{
GPKGWriter writer(vegetation_file.string(), projection, "vegetation");
writer.write_polygon("406_Slow_Running", "406", {{0, 0}, {10, 0}, {10, 10}, {0, 10}}, {});
writer.write_polygon("405_Forest", "405", {{20, 0}, {30, 0}, {30, 10}, {20, 10}}, {});
}
combine_gpkgs({contours_file, vegetation_file}, output_file, projection, ProgressTracker());
ASSERT_TRUE(fs::exists(output_file));
ensure_gdal_initialized();
GDALDataset* dataset = (GDALDataset*)GDALOpenEx(output_file.string().c_str(), GDAL_OF_VECTOR,
nullptr, nullptr, nullptr);
ASSERT_NE(dataset, nullptr);
std::set<std::string> layer_names;
for (int i = 0; i < dataset->GetLayerCount(); i++) {
OGRLayer* layer = dataset->GetLayer(i);
if (!layer || layer->GetFeatureCount(false) == 0) continue;
layer_names.insert(layer->GetName());
}
GDALClose(dataset);
EXPECT_TRUE(layer_names.contains("101_Contour"));
EXPECT_TRUE(layer_names.contains("406_Slow_Running"));
EXPECT_TRUE(layer_names.contains("405_Forest"));
for (const fs::path& path : {contours_file, vegetation_file, output_file}) {
if (fs::exists(path)) fs::remove(path);
}
}