Skip to content

Commit

Permalink
Added unit tests and test/ref data
Browse files Browse the repository at this point in the history
  • Loading branch information
jackiryan committed Feb 10, 2025
1 parent e1685f9 commit b86a64b
Show file tree
Hide file tree
Showing 5 changed files with 221 additions and 67 deletions.
53 changes: 27 additions & 26 deletions docker/test/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ ENV GDAL_VERSION=$GDAL_VERSION

# Install dependencies
RUN dnf install -y \
proj-8.2.0 \
proj-devel-8.2.0 \
geos-3.10.1 \
fribidi-devel-1.0.10 \
cairo-devel-1.17.4 \
cmake-3.26.5 \
geos-devel-3.10.1 \
harfbuzz-devel-2.7.4 \
fcgi-devel-2.4.0 \
protobuf-c-devel-1.3.3 && \
dnf clean all
proj-8.2.0 \
proj-devel-8.2.0 \
geos-3.10.1 \
fribidi-devel-1.0.10 \
cairo-devel-1.17.4 \
cmake-3.26.5 \
geos-devel-3.10.1 \
harfbuzz-devel-2.7.4 \
fcgi-devel-2.4.0 \
protobuf-c-devel-1.3.3 && \
dnf clean all

# libspatialindex
WORKDIR /tmp
Expand All @@ -38,21 +38,21 @@ RUN wget http://download.osgeo.org/gdal/${GDAL_VERSION}/gdal-${GDAL_VERSION}.tar
mkdir build && \
cd build && \
cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH=/usr/local/ \
-DCMAKE_INSTALL_PREFIX=/usr/local/ \
-DCMAKE_INSTALL_LIBDIR=lib \
-DBUILD_SHARED_LIBS=ON \
-DBUILD_TESTING=OFF \
-DGDAL_USE_PARQUET=OFF \
-DGDAL_USE_ARROW=OFF \
-DGDAL_USE_ARROWDATASET=OFF \
-DGDAL_ENABLE_HDF5_GLOBAL_LOCK:BOOL=ON \
-DBRUNSLI_INCLUDE_DIR=/usr/local/include/brunsli \
-DGDAL_USE_BRUNSLI=ON \
-DBUILD_PYTHON_BINDINGS:BOOL=ON \
-DBUILD_JAVA_BINDINGS:BOOL=OFF \
-DBUILD_CSHARP_BINDINGS:BOOL=OFF \
.. && \
-DCMAKE_PREFIX_PATH=/usr/local/ \
-DCMAKE_INSTALL_PREFIX=/usr/local/ \
-DCMAKE_INSTALL_LIBDIR=lib \
-DBUILD_SHARED_LIBS=ON \
-DBUILD_TESTING=OFF \
-DGDAL_USE_PARQUET=OFF \
-DGDAL_USE_ARROW=OFF \
-DGDAL_USE_ARROWDATASET=OFF \
-DGDAL_ENABLE_HDF5_GLOBAL_LOCK:BOOL=ON \
-DBRUNSLI_INCLUDE_DIR=/usr/local/include/brunsli \
-DGDAL_USE_BRUNSLI=ON \
-DBUILD_PYTHON_BINDINGS:BOOL=ON \
-DBUILD_JAVA_BINDINGS:BOOL=OFF \
-DBUILD_CSHARP_BINDINGS:BOOL=OFF \
.. && \
cmake --build . && \
cmake --build . --config Release --target install && \
export LD_LIBRARY_PATH=:/usr/local/lib && \
Expand Down Expand Up @@ -206,6 +206,7 @@ RUN install -m 755 src/empty_tile/oe_generate_empty_tile.py -D /usr/bin/oe_gener
install -m 755 src/colormaps/bin/SLDtoColorMap.py -D /usr/bin/SLDtoColorMap.py && \
install -m 755 src/vectorgen/oe_vectorgen.py -D /usr/bin/oe_vectorgen && \
install -m 755 src/vectorgen/oe_create_mvt_mrf.py -D /usr/bin/oe_create_mvt_mrf.py && \
install -m 755 src/vectorgen/oe_json_to_uvtile.py -D /usr/bin/oe_json_to_uvtile && \
install -m 755 src/scripts/oe_sync_s3_idx.py -D /usr/bin/oe_sync_s3_idx.py && \
install -m 755 src/scripts/oe_sync_s3_configs.py -D /usr/bin/oe_sync_s3_configs.py && \
install -m 755 src/scripts/oe_sync_s3_shapefiles.py -D /usr/bin/oe_sync_s3_shapefiles.py && \
Expand Down
83 changes: 42 additions & 41 deletions docker/tools/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,33 @@ RUN dnf -y update && \
dnf groupinstall -y "Development Tools" && \
dnf clean all && \
dnf config-manager --set-enabled crb && \
dnf install -y epel-release-9-5.el9 && \
dnf install -y epel-release-9-5.el9 && \
dnf install -y \
lua-devel-5.4.4 \
jansson-devel-2.14 \
libpng-devel-1.6.37 \
pcre-devel-8.44 \
wget-1.21.1 \
libyaml-devel-0.2.5 \
libcurl-devel-7.76.1 \
libjpeg-turbo-devel-2.0.90 \
libxml2-devel-2.9.13 \
luarocks-3.9.2 \
redis-6.2.7 \
cronie-1.5.7 \
logrotate-3.18.0 \
fribidi-devel-1.0.10 \
cairo-devel-1.17.4 \
cmake-3.26.5 \
harfbuzz-devel-2.7.4 \
fcgi-devel-2.4.0 \
proj-8.2.0 \
proj-devel-8.2.0 \
geos-3.10.1 \
geos-devel-3.10.1 \
python3-devel-3.9.18 \
protobuf-c-devel-1.3.3 && \
dnf clean all
lua-devel-5.4.4 \
jansson-devel-2.14 \
libpng-devel-1.6.37 \
pcre-devel-8.44 \
wget-1.21.1 \
libyaml-devel-0.2.5 \
libcurl-devel-7.76.1 \
libjpeg-turbo-devel-2.0.90 \
libxml2-devel-2.9.13 \
luarocks-3.9.2 \
redis-6.2.7 \
cronie-1.5.7 \
logrotate-3.18.0 \
fribidi-devel-1.0.10 \
cairo-devel-1.17.4 \
cmake-3.26.5 \
harfbuzz-devel-2.7.4 \
fcgi-devel-2.4.0 \
proj-8.2.0 \
proj-devel-8.2.0 \
geos-3.10.1 \
geos-devel-3.10.1 \
python3-devel-3.9.18 \
protobuf-c-devel-1.3.3 && \
dnf clean all

# libspatialindex
WORKDIR /tmp
Expand Down Expand Up @@ -71,21 +71,21 @@ RUN wget http://download.osgeo.org/gdal/${GDAL_VERSION}/gdal-${GDAL_VERSION}.tar
mkdir build && \
cd build && \
cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH=/usr/local/ \
-DCMAKE_INSTALL_PREFIX=/usr/local/ \
-DCMAKE_INSTALL_LIBDIR=lib \
-DBUILD_SHARED_LIBS=ON \
-DBUILD_TESTING=OFF \
-DGDAL_USE_PARQUET=OFF \
-DGDAL_USE_ARROW=OFF \
-DGDAL_USE_ARROWDATASET=OFF \
-DGDAL_ENABLE_HDF5_GLOBAL_LOCK:BOOL=ON \
-DBRUNSLI_INCLUDE_DIR=/usr/local/include/brunsli \
-DGDAL_USE_BRUNSLI=ON \
-DBUILD_PYTHON_BINDINGS:BOOL=ON \
-DBUILD_JAVA_BINDINGS:BOOL=OFF \
-DBUILD_CSHARP_BINDINGS:BOOL=OFF \
.. && \
-DCMAKE_PREFIX_PATH=/usr/local/ \
-DCMAKE_INSTALL_PREFIX=/usr/local/ \
-DCMAKE_INSTALL_LIBDIR=lib \
-DBUILD_SHARED_LIBS=ON \
-DBUILD_TESTING=OFF \
-DGDAL_USE_PARQUET=OFF \
-DGDAL_USE_ARROW=OFF \
-DGDAL_USE_ARROWDATASET=OFF \
-DGDAL_ENABLE_HDF5_GLOBAL_LOCK:BOOL=ON \
-DBRUNSLI_INCLUDE_DIR=/usr/local/include/brunsli \
-DGDAL_USE_BRUNSLI=ON \
-DBUILD_PYTHON_BINDINGS:BOOL=ON \
-DBUILD_JAVA_BINDINGS:BOOL=OFF \
-DBUILD_CSHARP_BINDINGS:BOOL=OFF \
.. && \
cmake --build . && \
cmake --build . --config Release --target install && \
export LD_LIBRARY_PATH=:/usr/local/lib && \
Expand Down Expand Up @@ -152,6 +152,7 @@ RUN install -m 755 src/empty_tile/oe_generate_empty_tile.py -D /usr/bin/oe_gener
install -m 755 src/colormaps/bin/SLDtoColorMap.py -D /usr/bin/SLDtoColorMap.py && \
install -m 755 src/vectorgen/oe_vectorgen.py -D /usr/bin/oe_vectorgen && \
install -m 755 src/vectorgen/oe_create_mvt_mrf.py -D /usr/bin/oe_create_mvt_mrf.py && \
install -m 755 src/vectorgen/oe_json_to_uvtile.py -D /usr/bin/oe_json_to_uvtile && \
install -m 755 src/scripts/oe_sync_s3_idx.py -D /usr/bin/oe_sync_s3_idx.py && \
install -m 755 src/scripts/oe_sync_s3_configs.py -D /usr/bin/oe_sync_s3_configs.py && \
install -m 755 src/scripts/oe_sync_s3_shapefiles.py -D /usr/bin/oe_sync_s3_shapefiles.py && \
Expand Down
152 changes: 152 additions & 0 deletions src/test/test_json_to_uvtile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
#!/usr/bin/env python3
import argparse
import numpy as np
import os
from PIL import Image
import shutil
import subprocess
import unittest

SAVE_RESULT = False


def run_script(*args):
"""Run oe_json_to_uvtile script"""
result = subprocess.run(
[
"python3",
"/Users/jryan/gibs_repos/onearth/src/vectorgen/oe_json_to_uvtile.py",
*args,
],
capture_output=True,
text=True,
)
return result


def mse(img1, img2, dtype=np.float32):
"""Compute Mean Squared Error between test and reference images."""
arr1 = np.array(img1, dtype=dtype)
arr2 = np.array(img2, dtype=dtype)
return np.mean((arr1 - arr2) ** 2)


class TestUsage(unittest.TestCase):
def test_usage(self):
"""Test with no args (should fail)."""
result = run_script()
self.assertEqual(result.returncode, 2)
self.assertIn("usage", result.stderr)


class TestOscar(unittest.TestCase):

test_data_path = os.path.join(os.getcwd(), "vectorgen_test_data")
# identical to test_data_path, but could be different later
reference_data_path = os.path.join(os.getcwd(), "vectorgen_test_data")
main_artifact_path = os.path.join(os.getcwd(), "json_uvtile_oscar_artifacts")
tests_passed = True

@classmethod
def setUpClass(cls):
oscar_input_gz = os.path.join(
cls.test_data_path,
"test_geojson",
"oscar_currents_final_uv_20200101_compress.json.gz",
)
cls.oscar_input = os.path.join(
cls.test_data_path,
"test_geojson",
"oscar_currents_final_uv_20200101_compress.json",
)

if not os.path.exists(cls.oscar_input) and os.path.exists(oscar_input_gz):
# Decompress oscar geojson file before running tests
# The file is stored compressed due to its large size (for a git repo, at least)
unzip_result = subprocess.run(["gunzip", oscar_input_gz])
if unzip_result.returncode != 0:
raise RuntimeError(
f"unable to unzip input test file: {oscar_input_gz}, {unzip_result.stderr}"
)
print(f"decompressed oscar data to {cls.oscar_input}")

os.makedirs(cls.main_artifact_path, exist_ok=True)

@classmethod
def tearDownClass(cls):
cls.oscar_input = os.path.join(
cls.test_data_path,
"test_geojson",
"oscar_currents_final_uv_20200101_compress.json",
)
if cls.tests_passed:
if os.path.exists(cls.oscar_input):
subprocess.run(["gzip", "-9", cls.oscar_input])
shutil.rmtree(cls.main_artifact_path)

def run(self, result=None):
"""Override run method to track test failures."""
result = super().run(result)
if not result.wasSuccessful():
self.__class__.tests_passed = False # Mark as failed
return result

def test_simple(self):
"""Test running oe_json_to_uvtile with only the input argument.
All further tests exercise the -o option."""
# First test is idiosyncratic because the output is placed in the
# test input dir (default behavior without -o)
artifact_path = os.path.join(
self.test_data_path,
"test_geojson",
"oscar_currents_final_uv_20200101_compress.png",
)

oscar_result = run_script(self.oscar_input)
self.assertEqual(
oscar_result.returncode,
0,
f"command retcode = {oscar_result.returncode}: {oscar_result.stderr}",
)
self.assertEqual(
os.path.exists(artifact_path),
True,
f"output file not found: {artifact_path}",
)
# clean up the artifact from the test input directory
os.remove(artifact_path)

def test_oscar_out(self):
"""Test oscar input with --output argument, comparing images this time."""
artifact_path = os.path.join(
self.main_artifact_path,
"oscar_currents_final_uv_20200101.png",
)
reference_path = os.path.join(self.reference_data_path, "test_oscar.png")
oscar_result = run_script(self.oscar_input, "-o", artifact_path)
self.assertEqual(
oscar_result.returncode,
0,
f"command retcode = {oscar_result.returncode}: {oscar_result.stderr}",
)
self.assertEqual(
os.path.exists(artifact_path),
True,
f"output file not found: {artifact_path}",
)
imgtest = Image.open(artifact_path).convert("RGB")
imgref = Image.open(reference_path).convert("RGB")
self.assertEqual(
imgtest.size,
imgref.size,
f"image dimensions do not match: {imgtest.size} (test), {imgref.size} (ref)",
)
# Compare rasters with MSE because compression reduces precision of input geojson
error = mse(imgtest, imgref, dtype=np.uint8)
self.assertLess(
error, 0.01, f"test image is too different from reference, MSE: {error}"
)


if __name__ == "__main__":
unittest.main()
Binary file not shown.
Binary file added src/test/vectorgen_test_data/test_oscar.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit b86a64b

Please sign in to comment.