""" Tests for AOI Packager Service """ import pytest from unittest.mock import patch, MagicMock, AsyncMock import json import sys sys.path.insert(0, '/app') from services.aoi_packager import AOIPackagerService class TestAOIPackagerService: """Tests for AOI Packager Service.""" @pytest.fixture def service(self): """Create service instance.""" return AOIPackagerService() def test_calculate_area_km2_small_polygon(self, service): """Test area calculation for small polygon.""" polygon = { "type": "Polygon", "coordinates": [ [ [9.19, 47.70], [9.20, 47.70], [9.20, 47.71], [9.19, 47.71], [9.19, 47.70], ] ], } area = service.calculate_area_km2(polygon) # Should be approximately 1 km² (rough estimate) assert 0.5 < area < 2.0 def test_calculate_area_km2_mainau(self, service): """Test area calculation for Mainau island polygon.""" polygon = { "type": "Polygon", "coordinates": [ [ [9.1875, 47.7055], [9.1975, 47.7055], [9.1975, 47.7115], [9.1875, 47.7115], [9.1875, 47.7055], ] ], } area = service.calculate_area_km2(polygon) # Mainau template claims ~0.45 km² assert 0.3 < area < 1.0 def test_is_within_germany_valid(self, service): """Test polygon within Germany.""" polygon = { "type": "Polygon", "coordinates": [ [ [9.19, 47.70], [9.20, 47.70], [9.20, 47.71], [9.19, 47.71], [9.19, 47.70], ] ], } assert service.is_within_germany(polygon) == True def test_is_within_germany_outside(self, service): """Test polygon outside Germany.""" # Paris polygon = { "type": "Polygon", "coordinates": [ [ [2.3, 48.8], [2.4, 48.8], [2.4, 48.9], [2.3, 48.9], [2.3, 48.8], ] ], } assert service.is_within_germany(polygon) == False def test_validate_polygon_valid(self, service): """Test valid polygon validation.""" polygon = { "type": "Polygon", "coordinates": [ [ [9.19, 47.70], [9.20, 47.70], [9.20, 47.71], [9.19, 47.71], [9.19, 47.70], ] ], } is_valid, message = service.validate_polygon(polygon) assert is_valid == True assert message == "Valid" def test_validate_polygon_not_closed(self, service): """Test polygon validation with unclosed ring.""" polygon = { "type": "Polygon", "coordinates": [ [ [9.19, 47.70], [9.20, 47.70], [9.20, 47.71], [9.19, 47.71], # Missing closing point ] ], } is_valid, message = service.validate_polygon(polygon) assert is_valid == False assert "closed" in message.lower() def test_validate_polygon_wrong_type(self, service): """Test polygon validation with wrong geometry type.""" polygon = { "type": "Point", "coordinates": [9.19, 47.70], } is_valid, message = service.validate_polygon(polygon) assert is_valid == False assert "Polygon" in message def test_estimate_bundle_size_low(self, service): """Test bundle size estimation for low quality.""" size = service.estimate_bundle_size_mb(1.0, "low") assert size == 10.0 def test_estimate_bundle_size_medium(self, service): """Test bundle size estimation for medium quality.""" size = service.estimate_bundle_size_mb(1.0, "medium") assert size == 25.0 def test_estimate_bundle_size_high(self, service): """Test bundle size estimation for high quality.""" size = service.estimate_bundle_size_mb(1.0, "high") assert size == 50.0 def test_estimate_bundle_size_scales_with_area(self, service): """Test bundle size scales with area.""" size_1km = service.estimate_bundle_size_mb(1.0, "medium") size_2km = service.estimate_bundle_size_mb(2.0, "medium") assert size_2km == size_1km * 2 class TestGeoUtils: """Tests for geo utility functions.""" def test_lat_lon_to_tile_berlin(self): """Test tile conversion for Berlin.""" from utils.geo_utils import lat_lon_to_tile # Berlin: 52.52, 13.405 x, y = lat_lon_to_tile(52.52, 13.405, 10) # At zoom 10, Berlin should be around tile 550, 335 assert 540 < x < 560 assert 325 < y < 345 def test_tile_to_bounds(self): """Test tile to bounds conversion.""" from utils.geo_utils import tile_to_bounds west, south, east, north = tile_to_bounds(10, 550, 335) # Should return valid bounds assert west < east assert south < north # Should be somewhere in Germany assert 5 < west < 20 assert 45 < south < 60 def test_calculate_distance(self): """Test distance calculation.""" from utils.geo_utils import calculate_distance # Berlin to Munich: ~504 km dist = calculate_distance(52.52, 13.405, 48.1351, 11.582) assert 450000 < dist < 550000 # meters def test_get_germany_bounds(self): """Test Germany bounds.""" from utils.geo_utils import get_germany_bounds west, south, east, north = get_germany_bounds() assert west == 5.87 assert south == 47.27 assert east == 15.04 assert north == 55.06 class TestLicenseChecker: """Tests for license checker utility.""" def test_osm_source_allowed(self): """Test OSM source is allowed.""" from utils.license_checker import LicenseChecker, DataSource assert LicenseChecker.is_source_allowed(DataSource.OPENSTREETMAP) == True def test_copernicus_source_allowed(self): """Test Copernicus source is allowed.""" from utils.license_checker import LicenseChecker, DataSource assert LicenseChecker.is_source_allowed(DataSource.COPERNICUS_DEM) == True def test_google_source_forbidden(self): """Test Google source is forbidden.""" from utils.license_checker import LicenseChecker, DataSource assert LicenseChecker.is_source_allowed(DataSource.GOOGLE) == False def test_validate_osm_url(self): """Test OSM URL validation.""" from utils.license_checker import LicenseChecker is_allowed, message = LicenseChecker.validate_url( "https://tile.openstreetmap.org/10/550/335.png" ) assert is_allowed == True assert "ALLOWED" in message def test_validate_google_url(self): """Test Google URL validation.""" from utils.license_checker import LicenseChecker is_allowed, message = LicenseChecker.validate_url( "https://maps.googleapis.com/maps/api/staticmap" ) assert is_allowed == False assert "FORBIDDEN" in message def test_get_attribution_for_sources(self): """Test getting attribution for sources.""" from utils.license_checker import LicenseChecker, DataSource sources = [DataSource.OPENSTREETMAP, DataSource.COPERNICUS_DEM] attributions = LicenseChecker.get_attribution_for_sources(sources) assert len(attributions) == 2 assert any("OpenStreetMap" in a["name"] for a in attributions) assert any("Copernicus" in a["name"] for a in attributions) def test_check_commercial_use_allowed(self): """Test commercial use check for allowed sources.""" from utils.license_checker import LicenseChecker, DataSource sources = [DataSource.OPENSTREETMAP, DataSource.COPERNICUS_DEM] allowed, issues = LicenseChecker.check_commercial_use(sources) assert allowed == True assert len(issues) == 0 def test_check_commercial_use_forbidden(self): """Test commercial use check with forbidden source.""" from utils.license_checker import LicenseChecker, DataSource sources = [DataSource.OPENSTREETMAP, DataSource.GOOGLE] allowed, issues = LicenseChecker.check_commercial_use(sources) assert allowed == False assert len(issues) > 0