]> git.openstreetmap.org Git - nominatim.git/commitdiff
bdd: fully check correctness of geojson and geocodejson
authorSarah Hoffmann <lonvia@denofr.de>
Thu, 9 Mar 2023 15:36:46 +0000 (16:36 +0100)
committerSarah Hoffmann <lonvia@denofr.de>
Thu, 9 Mar 2023 15:36:46 +0000 (16:36 +0100)
Parse code now checks presence of all required fields and exports
all fields for inspection.

test/bdd/steps/check_functions.py
test/bdd/steps/http_responses.py

index f214a88627f4fed870c06d2515cd2b9e4f6b4465..1a6f08ef33ff9507ba543c3fe2a5f513bc4676ee 100644 (file)
@@ -7,6 +7,7 @@
 """
 Collection of assertion functions used for the steps.
 """
+import json
 
 class Almost:
     """ Compares a float value with a certain jitter.
@@ -41,3 +42,24 @@ class Bbox:
 
     def __str__(self):
         return str(self.coord)
+
+
+
+def check_for_attributes(obj, attrs, presence='present'):
+    """ Check that the object has the given attributes. 'attrs' is a
+        string with a comma-separated list of attributes. If 'presence'
+        is set to 'absent' then the function checks that the attributes do
+        not exist for the object
+    """
+    def _dump_json():
+        return json.dumps(obj, sort_keys=True, indent=2, ensure_ascii=False)
+
+    for attr in attrs.split(','):
+        attr = attr.strip()
+        if presence == 'absent':
+            assert attr not in obj, \
+                   f"Unexpected attribute {attr}. Full response:\n{_dump_json()}"
+        else:
+            assert attr in obj, \
+                   f"No attribute '{attr}'. Full response:\n{_dump_json()}"
+
index dcce1b5865dddd23c917f34286289ca675bf76d8..aee0d7f069b62950292aab92cf6c983077b658a6 100644 (file)
@@ -11,7 +11,7 @@ import re
 import json
 import xml.etree.ElementTree as ET
 
-from check_functions import Almost
+from check_functions import Almost, check_for_attributes
 
 OSM_TYPE = {'N' : 'node', 'W' : 'way', 'R' : 'relation',
             'n' : 'node', 'w' : 'way', 'r' : 'relation',
@@ -76,15 +76,47 @@ class GenericResponse:
             else:
                 self.result = [self.result]
 
+
     def _parse_geojson(self):
         self._parse_json()
         if self.result:
-            self.result = list(map(_geojson_result_to_json_result, self.result[0]['features']))
+            geojson = self.result[0]
+            # check for valid geojson
+            check_for_attributes(geojson, 'type,features')
+            assert geojson['type'] == 'FeatureCollection'
+            assert isinstance(geojson['features'], list)
+
+            self.result = []
+            for result in geojson['features']:
+                check_for_attributes(result, 'type,properties,geometry')
+                assert result['type'] == 'Feature'
+                new = result['properties']
+                check_for_attributes(new, 'geojson', 'absent')
+                new['geojson'] = result['geometry']
+                if 'bbox' in result:
+                    check_for_attributes(new, 'boundingbox', 'absent')
+                    # bbox is  minlon, minlat, maxlon, maxlat
+                    # boundingbox is minlat, maxlat, minlon, maxlon
+                    new['boundingbox'] = [result['bbox'][1],
+                                          result['bbox'][3],
+                                          result['bbox'][0],
+                                          result['bbox'][2]]
+                for k, v in geojson.items():
+                    if k not in ('type', 'features'):
+                        check_for_attributes(new, '__' + k, 'absent')
+                        new['__' + k] = v
+                self.result.append(new)
+
 
     def _parse_geocodejson(self):
         self._parse_geojson()
-        if self.result is not None:
-            self.result = [r['geocoding'] for r in self.result]
+        if self.result:
+            for r in self.result:
+                assert set(r.keys()) == {'geocoding', 'geojson', '__geocoding'}, \
+                       f"Unexpected keys in result: {r.keys()}"
+                check_for_attributes(r['geocoding'], 'geojson', 'absent')
+                r |= r.pop('geocoding')
+
 
     def assert_field(self, idx, field, value):
         """ Check that result row `idx` has a field `field` with value `value`.