Raster to GTiff workflow implementation

Implemented simple GTiff file parser to test sandboxed part of code on a real data, added unit tests.
Need to improve the CMake file to make it work without specifying the absolute paths to libraries.
pull/64/head
Bohdan Tyshchenko 2020-10-01 03:59:18 -07:00
parent 0b1951ea4c
commit b06d020f32
11 changed files with 736 additions and 1 deletions

2
.gitmodules vendored
View File

@ -9,4 +9,4 @@
url = https://github.com/curl/curl
[submodule "oss-internship-2020/gdal/gdal"]
path = oss-internship-2020/gdal/gdal
url = https://github.com/OSGeo/gdal/tree/master/gdal
url = https://github.com/OSGeo/gdal/

View File

@ -0,0 +1,103 @@
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.10)
project(GDALSandbox CXX C)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(SAPI_ROOT "" CACHE PATH "Path to the Sandboxed API source tree")
# cmake .. -G Ninja -DSAPI_ROOT=$HOME/sapi_root
set(SAPI_ENABLE_EXAMPLES OFF CACHE BOOL "")
set(SAPI_ENABLE_TESTS OFF CACHE BOOL "")
add_subdirectory("${SAPI_ROOT}"
"${CMAKE_BINARY_DIR}/sandboxed-api-build"
# Omit this to have the full Sandboxed API in IDE
EXCLUDE_FROM_ALL)
add_library(libgdal STATIC IMPORTED)
set_property(TARGET libgdal PROPERTY IMPORTED_LOCATION
"${CMAKE_CURRENT_SOURCE_DIR}/lib/libgdal.a")
# TODO: Build PROJ statically and link it as gdal
# TODO: Use environment variables to specify path prefix to libproj and gdal header
# TODO: Add environment variable to enable tests
target_link_libraries(libgdal INTERFACE
crypto expat jpeg
/usr/local/lib/libproj.so
sqlite3 tiff z pthread m rt dl curl)
add_sapi_library(gdal_sapi
FUNCTIONS
GDALOpen
GDALAllRegister
GDALGetDatasetDriver
GDALCreate
GDALGetDriverByName
GDALGetRasterBand
GDALSetRasterColorInterpretation
GDALSetProjection
GDALSetGeoTransform
GDALSetRasterNoDataValue
GDALRasterIO
GDALClose
INPUTS "../gdal/gdal/gcore/gdal.h"
LIBRARY libgdal
LIBRARY_NAME gdal
NAMESPACE "gdal::sandbox"
)
target_include_directories(gdal_sapi INTERFACE
"${PROJECT_BINARY_DIR}"
)
add_library(data_retriever STATIC
get_raster_data.h get_raster_data.cc
)
target_link_libraries(data_retriever
libgdal
)
add_executable(raster_to_gtiff
raster_to_gtiff.cc
)
target_link_libraries(raster_to_gtiff
data_retriever
gdal_sapi
sapi::sapi
)
find_package(GTest REQUIRED)
include_directories(${GTEST_INCLUDE_DIRS})
add_executable(tests tests.cc)
target_link_libraries(tests
PRIVATE
gdal_sapi
data_retriever
sapi::sapi
sandbox2::temp_file
sandbox2::fileops
${GTEST_LIBRARIES}
${GTEST_MAIN_LIBRARIES}
)

View File

@ -0,0 +1,67 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef GDAL_SANDBOX_H_
#define GDAL_SANDBOX_H_
#include <string>
#include <syscall.h>
#include "gdal_sapi.sapi.h"
#include "sandboxed_api/sandbox2/util/fileops.h"
namespace gdal::sandbox {
class GdalSapiSandbox : public gdalSandbox {
public:
GdalSapiSandbox(std::string path)
: gdalSandbox(),
path_(std::move(path))
{}
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
sandbox2::PolicyBuilder*) override {
return sandbox2::PolicyBuilder()
.AllowDynamicStartup()
.AllowRead()
.AllowSystemMalloc()
.AllowWrite()
.AllowExit()
.AllowOpen()
.AllowSyscalls({
__NR_futex,
__NR_getdents64, // DriverRegisterAll()
__NR_lseek, // GDALCreate()
__NR_getpid, // GDALCreate()
__NR_sysinfo, // VSI_TIFFOpen_common()
__NR_prlimit64, // CPLGetUsablePhysicalRAM()
__NR_ftruncate, // GTiffDataset::FillEmptyTiles()
__NR_unlink, // GDALDriver::Delete()
})
// TODO: Deal with proj.db so you don't need to specify exact path ih the policy
.AddFile("/usr/local/share/proj/proj.db") // proj.db is required
.AddDirectory("/usr/local/lib") // To add libproj.so.19.1.1
.AddDirectory(path_, /*is_ro=*/false)
.BuildOrDie();
}
private:
std::string path_;
};
} // namespace gdal::sandbox
#endif // GDAL_SANDBOX_H_

View File

@ -0,0 +1,128 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "get_raster_data.h"
#include <iostream>
#include <memory>
#include "gdal.h"
namespace gdal::sandbox::tests::parser {
namespace {
inline constexpr int kGeoTransformSize = 6;
void PrintInformationAboutDataset(GDALDatasetH dataset, GDALDriverH driver) {
double adfGeoTransform[6];
printf("Driver: %s/%s\n",
GDALGetDriverShortName(driver),
GDALGetDriverLongName(driver));
printf("Size is %dx%dx%d\n",
GDALGetRasterXSize(dataset),
GDALGetRasterYSize(dataset),
GDALGetRasterCount(dataset) );
if(GDALGetProjectionRef(dataset) != NULL )
printf("Projection is `%s'\n", GDALGetProjectionRef(dataset));
if(GDALGetGeoTransform(dataset, adfGeoTransform) == CE_None)
{
printf("Origin = (%.6f,%.6f)\n",
adfGeoTransform[0], adfGeoTransform[3]);
printf("Pixel Size = (%.6f,%.6f)\n",
adfGeoTransform[1], adfGeoTransform[5]);
}
}
} // namespace
RasterDataset GetRasterBandsFromFile(const std::string& filename) {
GDALAllRegister();
GDALDatasetH dataset = GDALOpen(filename.data(), GA_ReadOnly);
GDALDriverH driver = GDALGetDatasetDriver(dataset);
RasterDataset result_dataset = {
GDALGetRasterXSize(dataset),
GDALGetRasterYSize(dataset)
};
if (GDALGetProjectionRef(dataset) != nullptr) {
result_dataset.wkt_projection = std::string(GDALGetProjectionRef(dataset));
}
std::vector<double> geo_transform(kGeoTransformSize, 0.0);
if (GDALGetGeoTransform(dataset, geo_transform.data()) == CE_None) {
result_dataset.geo_transform = std::move(geo_transform);
}
int bands_count = GDALGetRasterCount(dataset);
std::vector<RasterBandData> bands_data;
bands_data.reserve(bands_count);
for (int i = 1; i <= bands_count; ++i) {
GDALRasterBandH band = GDALGetRasterBand(dataset, i);
int width = GDALGetRasterBandXSize(band);
int height = GDALGetRasterBandYSize(band);
std::unique_ptr<int> no_data_result = nullptr;
double no_data_value = GDALGetRasterNoDataValue(band, no_data_result.get());
std::optional<double> no_data_value_holder =
no_data_result.get() == nullptr ? std::nullopt
: std::make_optional<double>(no_data_value);
int data_type = static_cast<int>(GDALGetRasterDataType(band));
int color_interp = static_cast<int>(GDALGetRasterColorInterpretation(band));
// Use std::variant or void* and reinterpet casts for the runtime template deduction
std::vector<int> band_raster_data;
band_raster_data.resize(width * height);
// GDALRasterIO with GF_Read should use the same type (GDT_Int32)
GDALRasterIO(band, GF_Read, 0, 0, width, height, band_raster_data.data(),
width, height, GDT_Int32, 0, 0);
bands_data.push_back(
{
width,
height,
std::move(band_raster_data),
data_type,
color_interp,
std::move(no_data_value_holder)
}
);
}
result_dataset.bands = std::move(bands_data);
return result_dataset;
}
bool operator==(const RasterBandData& lhs, const RasterBandData& rhs) {
return lhs.width == rhs.width && lhs.height == rhs.height
&& lhs.data == rhs.data && lhs.data_type == rhs.data_type
&& lhs.color_interp == rhs.color_interp
&& lhs.no_data_value == rhs.no_data_value;
}
bool operator==(const RasterDataset& lhs, const RasterDataset& rhs) {
return lhs.width == rhs.width && lhs.height == rhs.height
&& lhs.bands == rhs.bands
&& lhs.wkt_projection == rhs.wkt_projection
&& lhs.geo_transform == rhs.geo_transform;
}
} // namespace gdal::sandbox::tests:parser

View File

@ -0,0 +1,47 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef GET_RASTER_DATA_H_
#define GET_RASTER_DATA_H_
#include <optional>
#include <string>
#include <vector>
namespace gdal::sandbox::tests::parser {
struct RasterBandData {
int width;
int height;
std::vector<int> data;
int data_type; // Corresponds to the GDALDataType enum
int color_interp; // Corresponds to the
std::optional<double> no_data_value;
};
struct RasterDataset {
int width;
int height;
std::vector<RasterBandData> bands;
std::string wkt_projection; // OpenGIS WKT format
std::vector<double> geo_transform;
};
RasterDataset GetRasterBandsFromFile(const std::string& filename);
bool operator==(const RasterBandData& lhs, const RasterBandData& rhs);
bool operator==(const RasterDataset& lhs, const RasterDataset& rhs);
} // namespace gdal::sandbox::tests::parser
#endif // GET_RASTER_DATA_H

View File

@ -0,0 +1,166 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <iostream>
#include <vector>
#include <string>
#include <filesystem>
#include "sandboxed_api/sandbox2/util/fileops.h"
#include "gdal_sandbox.h"
#include "get_raster_data.h"
namespace {
#define SAPI_FAIL_IF_NOT(x, y) \
if (!(x)) { \
return absl::FailedPreconditionError(y); \
}
inline constexpr absl::string_view kDriverName = "GTiff";
absl::Status SaveToGTiff(gdal::sandbox::tests::parser::RasterDataset bands_data,
std::string out_file) {
using namespace gdal::sandbox;
std::string output_data_folder = "";
if (!sandbox2::file_util::fileops::RemoveLastPathComponent(out_file,
&output_data_folder)) {
return absl::FailedPreconditionError("Error getting output file directory");
}
GdalSapiSandbox sandbox(output_data_folder);
SAPI_RETURN_IF_ERROR(sandbox.Init());
gdalApi api(&sandbox);
SAPI_RETURN_IF_ERROR(api.GDALAllRegister());
sapi::v::ConstCStr driver_name_ptr(kDriverName.data());
SAPI_ASSIGN_OR_RETURN(sapi::StatusOr<GDALDriverH> driver,
api.GDALGetDriverByName(driver_name_ptr.PtrBefore()));
SAPI_FAIL_IF_NOT(driver.value() != nullptr,
"Error getting GTiff driver");
sapi::v::RemotePtr driver_ptr(driver.value());
sapi::v::ConstCStr out_file_full_path_ptr(out_file.data());
sapi::v::NullPtr create_options;
GDALDataType type = bands_data.bands.size() > 0 ?
static_cast<GDALDataType>(bands_data.bands[0].data_type)
: GDALDataType::GDT_Unknown;
SAPI_ASSIGN_OR_RETURN(sapi::StatusOr<GDALDatasetH> dataset,
api.GDALCreate(&driver_ptr, out_file_full_path_ptr.PtrBefore(),
bands_data.width, bands_data.height, bands_data.bands.size(), type,
&create_options));
SAPI_FAIL_IF_NOT(dataset.value(),
"Error creating dataset");
sapi::v::RemotePtr dataset_ptr(dataset.value());
for (int i = 0; i < bands_data.bands.size(); ++i) {
SAPI_ASSIGN_OR_RETURN(sapi::StatusOr<GDALRasterBandH> band,
api.GDALGetRasterBand(&dataset_ptr, i + 1));
SAPI_FAIL_IF_NOT(band.value() != nullptr,
"Error getting band from dataset");
sapi::v::RemotePtr band_ptr(band.value());
sapi::v::Array<int> data_array(bands_data.bands[i].data.data(),
bands_data.bands[i].data.size());
SAPI_ASSIGN_OR_RETURN(sapi::StatusOr<CPLErr> result,
api.GDALRasterIO(&band_ptr, GF_Write, 0, 0,
bands_data.bands[i].width, bands_data.bands[i].height,
data_array.PtrBefore(), bands_data.bands[i].width,
bands_data.bands[i].height, GDALDataType::GDT_Int32, 0, 0));
SAPI_FAIL_IF_NOT(result.value() == CPLErr::CE_None,
"Error writing band to dataset");
SAPI_ASSIGN_OR_RETURN(result, api.GDALSetRasterColorInterpretation(
&band_ptr, static_cast<GDALColorInterp>(
bands_data.bands[i].color_interp)));
SAPI_FAIL_IF_NOT(result.value() == CPLErr::CE_None,
"Error setting color interpretation");
if (bands_data.bands[i].no_data_value.has_value()) {
SAPI_ASSIGN_OR_RETURN(result,
api.GDALSetRasterNoDataValue(&band_ptr,
bands_data.bands[i].no_data_value.value()));
SAPI_FAIL_IF_NOT(result.value() == CPLErr::CE_None,
"Error setting no data value for the band");
}
}
if (bands_data.wkt_projection.length() > 0) {
sapi::v::ConstCStr wkt_projection_ptr(bands_data.wkt_projection.data());
SAPI_ASSIGN_OR_RETURN(sapi::StatusOr<CPLErr> result,
api.GDALSetProjection(&dataset_ptr, wkt_projection_ptr.PtrBefore()));
SAPI_FAIL_IF_NOT(result.value() == CPLErr::CE_None,
"Error setting wkt projection");
}
if (bands_data.geo_transform.size() > 0) {
sapi::v::Array<double> geo_transform_ptr(bands_data.geo_transform.data(),
bands_data.geo_transform.size());
SAPI_ASSIGN_OR_RETURN(sapi::StatusOr<CPLErr> result,
api.GDALSetGeoTransform(&dataset_ptr, geo_transform_ptr.PtrBefore()));
SAPI_FAIL_IF_NOT(result.value() == CPLErr::CE_None,
"Error setting geo transform");
}
SAPI_RETURN_IF_ERROR(api.GDALClose(&dataset_ptr));
return absl::OkStatus();
}
void Usage() {
std::cerr << "Example application that converts raster data to GTiff"
" format inside the sandbox. Usage:\n"
"raster_to_gtiff input_filename output_filename\n"
"output_filename must be absolute" << std::endl;
}
} // namespace
int main(int argc, char** argv) {
using namespace gdal::sandbox;
if (argc < 3
|| !std::filesystem::path(std::string(argv[2])).is_absolute()) {
Usage();
return EXIT_FAILURE;
}
std::string input_data_path = std::string(argv[1]);
std::string output_data_path = std::string(argv[2]);
tests::parser::RasterDataset bands_data
= tests::parser::GetRasterBandsFromFile(std::move(input_data_path));
if (absl::Status status =
SaveToGTiff(std::move(bands_data), std::move(output_data_path));
!status.ok()) {
std::cerr << status.ToString() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,224 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <iostream>
#include <optional>
#include <string>
#include "gtest/gtest.h"
#include "sandboxed_api/transaction.h"
#include "sandboxed_api/sandbox2/util/temp_file.h"
#include "sandboxed_api/sandbox2/util/fileops.h"
#include "gdal_sandbox.h"
#include "get_raster_data.h"
namespace gdal::sandbox::tests {
namespace {
inline constexpr absl::string_view kDriverName = "GTiff";
inline constexpr absl::string_view kTempFilePrefix = "temp_data";
inline constexpr absl::string_view kFirstTestDataPath =
"../testdata/map.tif";
inline constexpr absl::string_view kSecondTestDataPath =
"../testdata/map_large.tif";
inline constexpr absl::string_view kThirdTestDataPath =
"../testdata/earth_map.tif";
// RAII wrapper that creates temporary file and automatically unlinks it
class TempFile {
public:
explicit TempFile(absl::string_view prefix)
{
auto file_data = sandbox2::CreateNamedTempFile(prefix);
if (file_data.ok()) {
file_data_ = std::move(file_data.value());
}
}
~TempFile() {
if (file_data_.has_value()) {
unlink(file_data_.value().first.c_str());
}
}
bool HasValue() const {
return file_data_.has_value();
}
int GetFd() const {
return file_data_.value().second;
}
std::string GetPath() const {
return file_data_.value().first;
}
private:
std::optional<std::pair<std::string, int>> file_data_ = std::nullopt;
};
// Wrapper around raster to GTiff workflow
class RasterToGTiffProcessor : public sapi::Transaction {
public:
explicit RasterToGTiffProcessor(std::string out_filename,
std::string out_path,
parser::RasterDataset data,
int retry_count = 0)
: sapi::Transaction(std::make_unique<GdalSapiSandbox>(out_path)),
out_filename_(std::move(out_filename)),
out_path_(std::move(out_path)),
data_(std::move(data))
{
set_retry_count(retry_count);
SetTimeLimit(absl::InfiniteDuration());
}
private:
absl::Status Main() final;
const std::string out_filename_;
const std::string out_path_;
parser::RasterDataset data_;
};
absl::Status RasterToGTiffProcessor::Main() {
gdalApi api(sandbox());
SAPI_RETURN_IF_ERROR(api.GDALAllRegister());
sapi::v::ConstCStr driver_name_ptr(kDriverName.data());
SAPI_ASSIGN_OR_RETURN(sapi::StatusOr<GDALDriverH> driver,
api.GDALGetDriverByName(driver_name_ptr.PtrBefore()));
TRANSACTION_FAIL_IF_NOT(driver.value() != nullptr,
"Error getting GTiff driver");
sapi::v::RemotePtr driver_ptr(driver.value());
std::string out_file_full_path = absl::StrCat(out_path_, "/", out_filename_);
sapi::v::ConstCStr out_file_full_path_ptr(out_file_full_path.data());
sapi::v::NullPtr create_options;
GDALDataType type = data_.bands.size() > 0 ?
static_cast<GDALDataType>(data_.bands[0].data_type)
: GDALDataType::GDT_Unknown;
SAPI_ASSIGN_OR_RETURN(sapi::StatusOr<GDALDatasetH> dataset,
api.GDALCreate(&driver_ptr, out_file_full_path_ptr.PtrBefore(),
data_.width, data_.height, data_.bands.size(), type,
&create_options));
TRANSACTION_FAIL_IF_NOT(dataset.value(),
"Error creating dataset");
sapi::v::RemotePtr dataset_ptr(dataset.value());
for (int i = 0; i < data_.bands.size(); ++i) {
SAPI_ASSIGN_OR_RETURN(sapi::StatusOr<GDALRasterBandH> band,
api.GDALGetRasterBand(&dataset_ptr, i + 1));
TRANSACTION_FAIL_IF_NOT(band.value() != nullptr,
"Error getting band from dataset");
sapi::v::RemotePtr band_ptr(band.value());
sapi::v::Array<int> data_array(data_.bands[i].data.data(),
data_.bands[i].data.size());
SAPI_ASSIGN_OR_RETURN(sapi::StatusOr<CPLErr> result,
api.GDALRasterIO(&band_ptr, GF_Write, 0, 0,
data_.bands[i].width, data_.bands[i].height, data_array.PtrBefore(),
data_.bands[i].width, data_.bands[i].height, GDT_Int32, 0, 0));
TRANSACTION_FAIL_IF_NOT(result.value() == CPLErr::CE_None,
"Error writing band to dataset");
SAPI_ASSIGN_OR_RETURN(result, api.GDALSetRasterColorInterpretation(
&band_ptr, static_cast<GDALColorInterp>(
data_.bands[i].color_interp)));
TRANSACTION_FAIL_IF_NOT(result.value() == CPLErr::CE_None,
"Error setting color interpretation");
if (data_.bands[i].no_data_value.has_value()) {
SAPI_ASSIGN_OR_RETURN(result,
api.GDALSetRasterNoDataValue(&band_ptr,
data_.bands[i].no_data_value.value()));
TRANSACTION_FAIL_IF_NOT(result.value() == CPLErr::CE_None,
"Error setting no data value for the band");
}
}
if (data_.wkt_projection.length() > 0) {
sapi::v::ConstCStr wkt_projection_ptr(data_.wkt_projection.data());
SAPI_ASSIGN_OR_RETURN(sapi::StatusOr<CPLErr> result,
api.GDALSetProjection(&dataset_ptr, wkt_projection_ptr.PtrBefore()));
TRANSACTION_FAIL_IF_NOT(result.value() == CPLErr::CE_None,
"Error setting wkt projection");
}
if (data_.geo_transform.size() > 0) {
sapi::v::Array<double> geo_transform_ptr(data_.geo_transform.data(),
data_.geo_transform.size());
SAPI_ASSIGN_OR_RETURN(sapi::StatusOr<CPLErr> result,
api.GDALSetGeoTransform(&dataset_ptr, geo_transform_ptr.PtrBefore()));
TRANSACTION_FAIL_IF_NOT(result.value() == CPLErr::CE_None,
"Error setting geo transform");
}
SAPI_RETURN_IF_ERROR(api.GDALClose(&dataset_ptr));
return absl::OkStatus();
}
} // namespace
class TestGTiffProcessor : public testing::TestWithParam<absl::string_view> {
public:
TestGTiffProcessor()
: tempfile_(kTempFilePrefix)
{}
protected:
const TempFile tempfile_;
};
TEST_P(TestGTiffProcessor, TestProcessorOnGTiffData) {
std::string filename = std::string(GetParam());
ASSERT_TRUE(tempfile_.HasValue())
<< "Error creating temporary output file";
parser::RasterDataset original_bands_data =
parser::GetRasterBandsFromFile(filename);
RasterToGTiffProcessor processor(tempfile_.GetPath(),
sandbox2::file_util::fileops::GetCWD(), original_bands_data);
ASSERT_EQ(processor.Run(), absl::OkStatus())
<< "Error creating new GTiff dataset inside sandbox";
ASSERT_EQ(original_bands_data,
parser::GetRasterBandsFromFile(tempfile_.GetPath()))
<< "New dataset doesn't match the original one";
}
INSTANTIATE_TEST_CASE_P(
GDALTests,
TestGTiffProcessor,
::testing::Values(kFirstTestDataPath,
kSecondTestDataPath,
kThirdTestDataPath)
);
} // namespace gdal::sandbox::tests