Source code for geonode.thumbs.tests.test_backgrounds

#########################################################################
#
# Copyright (C) 2023 OSGeo
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#########################################################################
import os
import logging
from unittest.mock import patch

from pixelmatch.contrib.PIL import pixelmatch
from PIL import Image

from django.test import override_settings

from geonode.tests.base import GeoNodeBaseTestSupport
from geonode.thumbs.background import GenericWMTSBackground

[docs] logger = logging.getLogger(__name__)
[docs] WMTS_TILEMATRIX_LEVELS = [ { "zoom": 0, "bounds": [-20037508.342787, -60112525.02833891, 20037508.342775952, 20037508.342787], "scaledenominator": 559082264.028501, "tilewidth": 256, "tileheight": 256, "pixelspan": 156543.0339279803, "tilespanx": 40075016.68556295, "tilespany": 40075016.68556295, }, { "zoom": 1, "bounds": [-20037508.342787, -40075016.68555735, 20037508.3427759, 20037508.342787], "scaledenominator": 279541132.01425016, "tilewidth": 256, "tileheight": 256, "pixelspan": 78271.51696399004, "tilespanx": 20037508.34278145, "tilespany": 20037508.34278145, }, { "zoom": 2, "bounds": [-20037508.342787, -40075016.685557604, 20037508.342776064, 20037508.342787], "scaledenominator": 139770566.00712565, "tilewidth": 256, "tileheight": 256, "pixelspan": 39135.75848199518, "tilespanx": 10018754.171390766, "tilespany": 10018754.171390766, }, { "zoom": 3, "bounds": [-20037508.342787, -35065639.599861786, 20037508.34277575, 20037508.342787], "scaledenominator": 69885283.00356229, "tilewidth": 256, "tileheight": 256, "pixelspan": 19567.879240997438, "tilespanx": 5009377.085695344, "tilespany": 5009377.085695344, }, { "zoom": 4, "bounds": [-20037508.342787, -32560951.057014164, 20037508.34277579, 20037508.342787], "scaledenominator": 34942641.50178117, "tilewidth": 256, "tileheight": 256, "pixelspan": 9783.939620498728, "tilespanx": 2504688.5428476743, "tilespany": 2504688.5428476743, }, { "zoom": 5, "bounds": [-20037508.342787, -31308606.785590325, 20037508.34277579, 20037508.342787], "scaledenominator": 17471320.750890587, "tilewidth": 256, "tileheight": 256, "pixelspan": 4891.969810249364, "tilespanx": 1252344.2714238372, "tilespany": 1252344.2714238372, }, { "zoom": 6, "bounds": [-20037508.342787, -30682434.6498784, 20037508.34277579, 20037508.342787], "scaledenominator": 8735660.375445293, "tilewidth": 256, "tileheight": 256, "pixelspan": 2445.984905124682, "tilespanx": 626172.1357119186, "tilespany": 626172.1357119186, }, { "zoom": 7, "bounds": [-20037508.342787, -30369348.58202224, 20037508.342775624, 20037508.342787], "scaledenominator": 4367830.187722629, "tilewidth": 256, "tileheight": 256, "pixelspan": 1222.992452562336, "tilespanx": 313086.067855958, "tilespany": 313086.067855958, }, { "zoom": 8, "bounds": [-20037508.342787, -30369348.58203337, 20037508.342784476, 20037508.342787], "scaledenominator": 2183915.093861797, "tilewidth": 256, "tileheight": 256, "pixelspan": 611.496226281303, "tilespanx": 156543.03392801358, "tilespany": 156543.03392801358, }, { "zoom": 9, "bounds": [-20037508.342787, -30291077.06504764, 20037508.342767175, 20037508.342787], "scaledenominator": 1091957.546930427, "tilewidth": 256, "tileheight": 256, "pixelspan": 305.74811314051954, "tilespanx": 78271.516963973, "tilespany": 78271.516963973, }, { "zoom": 10, "bounds": [-20037508.342787, -30251941.306609083, 20037508.342801783, 20037508.342787], "scaledenominator": 545978.773465685, "tilewidth": 256, "tileheight": 256, "pixelspan": 152.8740565703918, "tilespanx": 39135.7584820203, "tilespany": 39135.7584820203, }, { "zoom": 11, "bounds": [-20037508.342787, -30251941.30652203, 20037508.34273241, 20037508.342787], "scaledenominator": 272989.38673236995, "tilewidth": 256, "tileheight": 256, "pixelspan": 76.43702828506358, "tilespanx": 19567.879240976275, "tilespany": 19567.879240976275, }, { "zoom": 12, "bounds": [-20037508.342787, -30242157.366901536, 20037508.34273241, 20037508.342787], "scaledenominator": 136494.69336618498, "tilewidth": 256, "tileheight": 256, "pixelspan": 38.21851414253179, "tilespanx": 9783.939620488138, "tilespany": 9783.939620488138, }, { "zoom": 13, "bounds": [-20037508.342787, -30242157.366901536, 20037508.34273241, 20037508.342787], "scaledenominator": 68247.34668309249, "tilewidth": 256, "tileheight": 256, "pixelspan": 19.109257071265894, "tilespanx": 4891.969810244069, "tilespany": 4891.969810244069, }, { "zoom": 14, "bounds": [-20037508.342787, -30242157.366901536, 20037508.34273241, 20037508.342787], "scaledenominator": 34123.673341546244, "tilewidth": 256, "tileheight": 256, "pixelspan": 9.554628535632947, "tilespanx": 2445.9849051220344, "tilespany": 2445.9849051220344, }, { "zoom": 15, "bounds": [-20037508.342787, -30242157.3682939, 20037508.343842182, 20037508.342787], "scaledenominator": 17061.836671245605, "tilewidth": 256, "tileheight": 256, "pixelspan": 4.777314267948769, "tilespanx": 1222.9924525948848, "tilespany": 1222.9924525948848, }, { "zoom": 16, "bounds": [-20037508.342787, -30241545.8720675, 20037508.3438421, 20037508.342787], "scaledenominator": 8530.918335622784, "tilewidth": 256, "tileheight": 256, "pixelspan": 2.3886571339743794, "tilespanx": 611.4962262974411, "tilespany": 611.4962262974411, }, { "zoom": 17, "bounds": [-20037508.342787, -30241240.11838522, 20037508.339403186, 20037508.342787], "scaledenominator": 4265.459167338928, "tilewidth": 256, "tileheight": 256, "pixelspan": 1.1943285668548997, "tilespanx": 305.74811311485433, "tilespany": 305.74811311485433, }, { "zoom": 18, "bounds": [-20037508.342787, -30241087.25546706, 20037508.34828115, 20037508.342787], "scaledenominator": 2132.7295841419354, "tilewidth": 256, "tileheight": 256, "pixelspan": 0.5971642835597418, "tilespanx": 152.8740565912939, "tilespany": 152.8740565912939, }, { "zoom": 19, "bounds": [-20037508.342787, -30241010.79616208, 20037508.330525283, 20037508.342787], "scaledenominator": 1066.364791598498, "tilewidth": 256, "tileheight": 256, "pixelspan": 0.2985821416475794, "tilespanx": 76.43702826178033, "tilespany": 76.43702826178033, }, { "zoom": 20, "bounds": [-20037508.342787, -30240972.57764789, 20037508.330525238, 20037508.342787], "scaledenominator": 533.1823957992484, "tilewidth": 256, "tileheight": 256, "pixelspan": 0.14929107082378953, "tilespanx": 38.21851413089012, "tilespany": 38.21851413089012, }, { "zoom": 21, "bounds": [-20037508.342787, -30240972.57764789, 20037508.330525238, 20037508.342787], "scaledenominator": 266.5911978996242, "tilewidth": 256, "tileheight": 256, "pixelspan": 0.07464553541189477, "tilespanx": 19.10925706544506, "tilespany": 19.10925706544506, }, { "zoom": 22, "bounds": [-20037508.342787, -30240972.57764789, 20037508.330525238, 20037508.342787], "scaledenominator": 133.2955989498121, "tilewidth": 256, "tileheight": 256, "pixelspan": 0.037322767705947384, "tilespanx": 9.55462853272253, "tilespany": 9.55462853272253, }, { "zoom": 23, "bounds": [-20037508.342787, -30240972.57764789, 20037508.330525238, 20037508.342787], "scaledenominator": 66.64779947490605, "tilewidth": 256, "tileheight": 256, "pixelspan": 0.018661383852973692, "tilespanx": 4.777314266361265, "tilespany": 4.777314266361265, }, ]
[docs] THUMBNAIL_BACKGROUND = { "class": "geonode.thumbs.background.GenericWMTSBackground", "options": { "url": "https://myserver.com/WMTS", "layer": "Hosted_basemap_inforac_3857", "style": "default", "tilematrixset": "default028mm", "minscaledenominator": 272989.38673236995, }, }
[docs] EXPECTED_RESULTS_DIR = "geonode/thumbs/tests/expected_results/"
[docs] base_request_url = "https://myserver.com/WMTS?&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image/png&layer=Hosted_basemap_inforac_3857&style=default&tilematrixset=default028mm&"
[docs] mocked_requests = { base_request_url + "TileMatrix=4&TileRow=5&TileCol=7": f"{EXPECTED_RESULTS_DIR}/tiles/wmts_7_5_4.png", base_request_url + "TileMatrix=4&TileRow=6&TileCol=7": f"{EXPECTED_RESULTS_DIR}/tiles/wmts_7_6_4.png", base_request_url + "TileMatrix=4&TileRow=5&TileCol=8": f"{EXPECTED_RESULTS_DIR}/tiles/wmts_8_5_4.png", base_request_url + "TileMatrix=4&TileRow=6&TileCol=8": f"{EXPECTED_RESULTS_DIR}/tiles/wmts_8_6_4.png", base_request_url + "TileMatrix=4&TileRow=5&TileCol=9": f"{EXPECTED_RESULTS_DIR}/tiles/wmts_9_5_4.png", base_request_url + "TileMatrix=4&TileRow=6&TileCol=9": f"{EXPECTED_RESULTS_DIR}/tiles/wmts_9_6_4.png", }
[docs] class Response: def __init__(self, status_code=200, content=None) -> None:
[docs] self.status_code = status_code
[docs] self.content = content
[docs] def get_mock(*args): file_path = mocked_requests.get(args[0]) if file_path and os.path.exists(file_path): with open(file_path, "rb") as fin: return Response(200, fin.read())
[docs] class GeoNodeThumbnailWMTSBackground(GeoNodeBaseTestSupport): @classmethod
[docs] def setUpClass(cls): super().setUpClass()
@override_settings(THUMBNAIL_BACKGROUND=THUMBNAIL_BACKGROUND) @patch("geonode.thumbs.background.WMTS_TILEMATRIXSET_LEVELS", WMTS_TILEMATRIX_LEVELS)
[docs] def test_get_target_pixelspan(self, *args): bbox = [-757689.8225283397, 4231175.960993547, 3557041.3914652625, 5957068.446590988] expected_target_pixelspan = 8629.462427987204 background = GenericWMTSBackground(thumbnail_width=500, thumbnail_height=200) target_pixelspan = background.get_target_pixelspan(bbox) self.assertAlmostEqual(expected_target_pixelspan, target_pixelspan)
@override_settings(THUMBNAIL_BACKGROUND=THUMBNAIL_BACKGROUND) @patch("geonode.thumbs.background.WMTS_TILEMATRIXSET_LEVELS", WMTS_TILEMATRIX_LEVELS)
[docs] def test_get_level_for_targetpixelspan(self, *args): target_pixelspan = 8629.462427987204 background = GenericWMTSBackground(thumbnail_width=500, thumbnail_height=200) level = background.get_level_for_targetpixelspan(target_pixelspan) self.assertDictEqual(level, WMTS_TILEMATRIX_LEVELS[4])
@override_settings(THUMBNAIL_BACKGROUND=THUMBNAIL_BACKGROUND) @patch("geonode.thumbs.background.WMTS_TILEMATRIXSET_LEVELS", WMTS_TILEMATRIX_LEVELS)
[docs] def test_get_tiles_coords(self, *args): bbox = [-757689.8225283397, 4231175.960993547, 3557041.3914652625, 5957068.446590988] level = WMTS_TILEMATRIX_LEVELS[4] expected_tile_rowcols = [[7, 5], [7, 6], [8, 5], [8, 6], [9, 5], [9, 6]] background = GenericWMTSBackground(thumbnail_width=500, thumbnail_height=200) tile_rowcols = background.get_tiles_coords(level, bbox) self.assertListEqual(expected_tile_rowcols, tile_rowcols)
@override_settings(THUMBNAIL_BACKGROUND=THUMBNAIL_BACKGROUND) @patch("geonode.thumbs.background.WMTS_TILEMATRIXSET_LEVELS", WMTS_TILEMATRIX_LEVELS)
[docs] def test_build_request(self, *args): expected_imgurl = "https://myserver.com/WMTS?&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image/png&\ layer=Hosted_basemap_inforac_3857&style=default&tilematrixset=default028mm&TileMatrix=4&TileRow=5&TileCol=7" background = GenericWMTSBackground(thumbnail_width=500, thumbnail_height=200) imgurl = background.build_request((7, 5, 4)) self.assertEqual(expected_imgurl, imgurl)
@override_settings(THUMBNAIL_BACKGROUND=THUMBNAIL_BACKGROUND) @patch("geonode.thumbs.background.WMTS_TILEMATRIXSET_LEVELS", WMTS_TILEMATRIX_LEVELS) @patch("geonode.thumbs.background.requests.get", get_mock)
[docs] def test_tile_request(self, *args): bbox = [-757689.8225283397, 3557041.3914652625, 4231175.960993547, 5957068.446590988, "EPSG:3857"] background = GenericWMTSBackground(thumbnail_width=500, thumbnail_height=200) image = background.fetch(bbox) expected_image = Image.open(f"{EXPECTED_RESULTS_DIR}/tiles/background.png") diff = Image.new("RGB", image.size) mismatch = pixelmatch(image, expected_image, diff) if mismatch >= expected_image.size[0] * expected_image.size[1] * 0.01: logger.warn("Mismatch, it was not possible to bump the bg!") else: self.assertTrue( mismatch < expected_image.size[0] * expected_image.size[1] * 0.01, "Expected test and pre-generated backgrounds to differ up to 1%", )