]> git.openstreetmap.org Git - nominatim.git/commitdiff
add placex import tests
authorSarah Hoffmann <lonvia@denofr.de>
Sun, 20 Nov 2016 19:03:51 +0000 (20:03 +0100)
committerSarah Hoffmann <lonvia@denofr.de>
Fri, 30 Dec 2016 21:58:58 +0000 (22:58 +0100)
test/bdd/db/import/placex.feature [new file with mode: 0644]
test/bdd/db/import/search_simple.feature [deleted file]
test/bdd/environment.py
test/bdd/steps/db_ops.py

diff --git a/test/bdd/db/import/placex.feature b/test/bdd/db/import/placex.feature
new file mode 100644 (file)
index 0000000..7cbedaa
--- /dev/null
@@ -0,0 +1,313 @@
+@DB
+Feature: Import into placex
+    Tests that data in placex is completed correctly.
+
+    Scenario: No country code tag is available
+        Given the named places
+          | osm | class   | type     | geometry   |
+          | N1  | highway | primary  | country:us |
+        When importing
+        Then placex contains
+          | object | country_code | calculated_country_code |
+          | N1     | None         | us                      |
+
+    Scenario: Location overwrites country code tag
+        Given the named places
+          | osm | class   | type     | country | geometry |
+          | N1  | highway | primary  | de      | country:us |
+        When importing
+        Then placex contains
+          | object | country_code | calculated_country_code |
+          | N1     | de           | us                      |
+
+    Scenario: Country code tag overwrites location for countries
+        Given the named places
+          | osm | class    | type            | admin | country | geometry |
+          | R1  | boundary | administrative  | 2     | de      | (-100 40, -101 40, -101 41, -100 41, -100 40) |
+        When importing
+        Then placex contains
+          | object | country_code | calculated_country_code |
+          | R1     | de           | de                      |
+
+    Scenario: Illegal country code tag for countries is ignored
+        Given the named places
+          | osm | class    | type            | admin | country | geometry |
+          | R1  | boundary | administrative  | 2     | xx      | (-100 40, -101 40, -101 41, -100 41, -100 40) |
+        When importing
+        Then placex contains
+          | object | country_code | calculated_country_code |
+          | R1     | xx           | us                      |
+
+    Scenario: admin level is copied over
+        Given the named places
+          | osm | class | type      | admin |
+          | N1  | place | state     | 3     |
+        When importing
+        Then placex contains
+          | object | admin_level |
+          | N1     | 3           |
+
+    Scenario: admin level is default 15
+        Given the named places
+          | osm | class   | type   |
+          | N1  | amenity | prison |
+        When importing
+        Then placex contains
+          | object | admin_level |
+          | N1     | 15          |
+
+    Scenario: admin level is never larger than 15
+        Given the named places
+          | osm | class   | type   | admin |
+          | N1  | amenity | prison | 16 |
+        When importing
+        Then placex contains
+          | object | admin_level |
+          | N1     | 15          |
+
+    Scenario: postcode node without postcode is dropped
+        Given the places
+          | osm | class   | type     | name+ref |
+          | N1  | place   | postcode | 12334    |
+        When importing
+        Then placex has no entry for N1
+
+    Scenario: postcode boundary without postcode is dropped
+        Given the places
+          | osm | class    | type        | name+ref | geometry |
+          | R1  | boundary | postal_code | 554476   | poly-area:0.1 |
+        When importing
+        Then placex has no entry for R1
+
+    Scenario: search and address ranks for GB post codes correctly assigned
+        Given the places
+         | osm  | class | type     | postcode | geometry |
+         | N1   | place | postcode | E45 2CD  | country:gb |
+         | N2   | place | postcode | E45 2    | country:gb |
+         | N3   | place | postcode | Y45      | country:gb |
+        When importing
+        Then placex contains
+         | object | postcode | calculated_country_code | rank_search | rank_address |
+         | N1     | E45 2CD  | gb                      | 25          | 5 |
+         | N2     | E45 2    | gb                      | 23          | 5 |
+         | N3     | Y45      | gb                      | 21          | 5 |
+
+    Scenario: wrongly formatted GB postcodes are down-ranked
+        Given the places
+         | osm  | class | type     | postcode | geometry |
+         | N1   | place | postcode | EA452CD  | country:gb |
+         | N2   | place | postcode | E45 23   | country:gb |
+         | N3   | place | postcode | y45      | country:gb |
+        When importing
+        Then placex contains
+         | object | calculated_country_code | rank_search | rank_address |
+         | N1     | gb                      | 30          | 30 |
+         | N2     | gb                      | 30          | 30 |
+         | N3     | gb                      | 30          | 30 |
+
+    Scenario: search and address rank for DE postcodes correctly assigned
+        Given the places
+         | osm | class | type     | postcode | geometry |
+         | N1  | place | postcode | 56427    | country:de |
+         | N2  | place | postcode | 5642     | country:de |
+         | N3  | place | postcode | 5642A    | country:de |
+         | N4  | place | postcode | 564276   | country:de |
+        When importing
+        Then placex contains
+         | object | calculated_country_code | rank_search | rank_address |
+         | N1     | de                      | 21          | 11 |
+         | N2     | de                      | 30          | 30 |
+         | N3     | de                      | 30          | 30 |
+         | N4     | de                      | 30          | 30 |
+
+    Scenario: search and address rank for other postcodes are correctly assigned
+        Given the places
+         | osm | class | type     | postcode | geometry |
+         | N1  | place | postcode | 1        | country:ca |
+         | N2  | place | postcode | X3       | country:ca |
+         | N3  | place | postcode | 543      | country:ca |
+         | N4  | place | postcode | 54dc     | country:ca |
+         | N5  | place | postcode | 12345    | country:ca |
+         | N6  | place | postcode | 55TT667  | country:ca |
+         | N7  | place | postcode | 123-65   | country:ca |
+         | N8  | place | postcode | 12 445 4 | country:ca |
+         | N9  | place | postcode | A1:bc10  | country:ca |
+        When importing
+        Then placex contains
+         | object | calculated_country_code | rank_search | rank_address |
+         | N1     | ca                      | 21          | 11 |
+         | N2     | ca                      | 21          | 11 |
+         | N3     | ca                      | 21          | 11 |
+         | N4     | ca                      | 21          | 11 |
+         | N5     | ca                      | 21          | 11 |
+         | N6     | ca                      | 21          | 11 |
+         | N7     | ca                      | 25          | 11 |
+         | N8     | ca                      | 25          | 11 |
+         | N9     | ca                      | 25          | 11 |
+
+    Scenario: search and address ranks for places are correctly assigned
+        Given the named places
+          | osm  | class     | type      |
+          | N1   | foo       | bar       |
+          | N11  | place     | Continent |
+          | N12  | place     | continent |
+          | N13  | place     | sea       |
+          | N14  | place     | country   |
+          | N15  | place     | state     |
+          | N16  | place     | region    |
+          | N17  | place     | county    |
+          | N18  | place     | city      |
+          | N19  | place     | island    |
+          | N20  | place     | town      |
+          | N21  | place     | village   |
+          | N22  | place     | hamlet    |
+          | N23  | place     | municipality |
+          | N24  | place     | district     |
+          | N25  | place     | unincorporated_area |
+          | N26  | place     | borough             |
+          | N27  | place     | suburb              |
+          | N28  | place     | croft               |
+          | N29  | place     | subdivision         |
+          | N30  | place     | isolated_dwelling   |
+          | N31  | place     | farm                |
+          | N32  | place     | locality            |
+          | N33  | place     | islet               |
+          | N34  | place     | mountain_pass       |
+          | N35  | place     | neighbourhood       |
+          | N36  | place     | house               |
+          | N37  | place     | building            |
+          | N38  | place     | houses              |
+        And the named places
+          | osm  | class     | type      | extra+locality |
+          | N100 | place     | locality  | townland |
+        And the named places
+          | osm  | class     | type      | extra+capital |
+          | N101 | place     | city      | yes |
+        When importing
+        Then placex contains
+          | object | rank_search | rank_address |
+          | N1     | 30          | 30 |
+          | N11    | 30          | 30 |
+          | N12    | 2           | 2 |
+          | N13    | 2           | 0 |
+          | N14    | 4           | 4 |
+          | N15    | 8           | 8 |
+          | N16    | 18          | 0 |
+          | N17    | 12          | 12 |
+          | N18    | 16          | 16 |
+          | N19    | 17          | 0 |
+          | N20    | 18          | 16 |
+          | N21    | 19          | 16 |
+          | N22    | 19          | 16 |
+          | N23    | 19          | 16 |
+          | N24    | 19          | 16 |
+          | N25    | 19          | 16 |
+          | N26    | 19          | 16 |
+          | N27    | 20          | 20 |
+          | N28    | 20          | 20 |
+          | N29    | 20          | 20 |
+          | N30    | 20          | 20 |
+          | N31    | 20          | 0 |
+          | N32    | 20          | 0 |
+          | N33    | 20          | 0 |
+          | N34    | 20          | 0 |
+          | N100   | 20          | 20 |
+          | N101   | 15          | 16 |
+          | N35    | 22          | 22 |
+          | N36    | 30          | 30 |
+          | N37    | 30          | 30 |
+          | N38    | 28          | 0 |
+
+    Scenario: search and address ranks for boundaries are correctly assigned
+        Given the named places
+          | osm | class    | type |
+          | N1  | boundary | administrative |
+        And the named places
+          | osm | class    | type           | geometry |
+          | W10 | boundary | administrative | 10 10, 11 11 |
+        And the named places
+          | osm | class    | type           | admin | geometry |
+          | R20 | boundary | administrative | 2     | (1 1, 2 2, 1 2, 1 1) |
+          | R21 | boundary | administrative | 32    | (3 3, 4 4, 3 4, 3 3) |
+          | R22 | boundary | nature_park    | 6     | (0 0, 1 0, 0 1, 0 0) |
+          | R23 | boundary | natural_reserve| 10    | (0 0, 1 1, 1 0, 0 0) |
+        When importing
+        Then placex has no entry for N1
+        And placex has no entry for W10
+        And placex contains
+          | object | rank_search | rank_address |
+          | R20    | 4           | 4 |
+          | R21    | 30          | 30 |
+          | R22    | 12          | 0 |
+          | R23    | 20          | 0 |
+
+    Scenario: search and address ranks for highways correctly assigned
+        Given the scene roads-with-pois
+        And the places
+          | osm | class    | type  |
+          | N1  | highway  | bus_stop |
+        And the places
+          | osm | class    | type         | geometry |
+          | W1  | highway  | primary      | :w-south |
+          | W2  | highway  | secondary    | :w-south |
+          | W3  | highway  | tertiary     | :w-south |
+          | W4  | highway  | residential  | :w-north |
+          | W5  | highway  | unclassified | :w-north |
+          | W6  | highway  | something    | :w-north |
+        When importing
+        Then placex contains
+          | object | rank_search | rank_address |
+          | N1     | 30          | 30 |
+          | W1     | 26          | 26 |
+          | W2     | 26          | 26 |
+          | W3     | 26          | 26 |
+          | W4     | 26          | 26 |
+          | W5     | 26          | 26 |
+          | W6     | 26          | 26 |
+
+    Scenario: rank and inclusion of landuses
+        Given the named places
+          | osm | class   | type |
+          | N2  | landuse | residential |
+        And the named places
+          | osm | class   | type        | geometry |
+          | W2  | landuse | residential | 1 1, 1 1.1 |
+          | W4  | landuse | residential | poly-area:0.1 |
+          | R2  | landuse | residential | poly-area:0.05 |
+          | R3  | landuse | forrest     | poly-area:0.5 |
+        When importing
+        Then placex contains
+          | object | rank_search | rank_address |
+          | N2     | 30          | 30 |
+          | W2     | 30          | 30 |
+          | W4     | 22          | 22 |
+          | R2     | 22          | 22 |
+          | R3     | 22          | 0 |
+
+    Scenario: rank and inclusion of naturals
+       Given the named places
+          | osm | class   | type |
+          | N2  | natural | peak |
+          | N4  | natural | volcano |
+          | N5  | natural | foobar |
+       And the named places
+          | osm | class   | type           | geometry |
+          | W2  | natural | mountain_range | 12 12,11 11 |
+          | W3  | natural | foobar         | 13 13,13.1 13 |
+          | R3  | natural | volcano        | poly-area:0.1 |
+          | R4  | natural | foobar         | poly-area:0.5 |
+          | R5  | natural | sea            | poly-area:5.0 |
+          | R6  | natural | sea            | poly-area:0.01 |
+       When importing
+       Then placex contains
+          | object | rank_search | rank_address |
+          | N2     | 18          | 0 |
+          | N4     | 18          | 0 |
+          | N5     | 30          | 30 |
+          | W2     | 18          | 0 |
+          | R3     | 18          | 0 |
+          | R4     | 22          | 0 |
+          | R5     | 4           | 4 |
+          | R6     | 4           | 4 |
+          | W3     | 30          | 30 |
+
diff --git a/test/bdd/db/import/search_simple.feature b/test/bdd/db/import/search_simple.feature
deleted file mode 100644 (file)
index fb4071d..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-@DB
-Feature: Import of simple objects
-    Testing simple stuff
-
-    @wip
-    Scenario: Import place node
-        Given the places
-          | osm | class | type    | name | name+ref | geometry   |
-          | N1  | place | village | Foo  | 32       | 10.0 -10.0 |
-        And the named places
-          | osm | class | type    | housenr |
-          | N2  | place | village |         |
-        When importing
-        Then placex contains
-          | object | class  | type    | name | name+ref | centroid*10 |
-          | N1     | place  | village | Foo  | 32       | 1 -1        |
index c878c61c5f90bf4f407038654fbe76673508b131..a954b2533010f283ef4a128a2687bb81ff49a95d 100644 (file)
@@ -4,6 +4,7 @@ import os
 import psycopg2
 import psycopg2.extras
 import subprocess
+from nose.tools import * # for assert functions
 from sys import version_info as python_version
 
 logger = logging.getLogger(__name__)
@@ -143,28 +144,28 @@ class OSMDataFactory(object):
         self.scene_cache = {}
 
     def parse_geometry(self, geom, scene):
-        if geom[0].find(':') >= 0:
-            out = self.get_scene_geometry(scene, geom[1:])
-        if geom.find(',') < 0:
-            out = 'POINT(%s)' % geom
+        if geom.find(':') >= 0:
+            out = self.get_scene_geometry(scene, geom)
+        elif geom.find(',') < 0:
+            out = "'POINT(%s)'::geometry" % geom
         elif geom.find('(') < 0:
-            out = 'LINESTRING(%s)' % geom
+            out = "'LINESTRING(%s)'::geometry" % geom
         else:
-            out = 'POLYGON(%s)' % geom
+            out = "'POLYGON(%s)'::geometry" % geom
 
-        # TODO parse precision
-        return out, 0
+        return "ST_SetSRID(%s, 4326)" % out
 
     def get_scene_geometry(self, default_scene, name):
         geoms = []
-        defscene = self.load_scene(default_scene)
         for obj in name.split('+'):
             oname = obj.strip()
             if oname.startswith(':'):
+                assert_is_not_none(default_scene, "You need to set a scene")
+                defscene = self.load_scene(default_scene)
                 wkt = defscene[oname[1:]]
             else:
                 scene, obj = oname.split(':', 2)
-                scene_geoms = world.load_scene(scene)
+                scene_geoms = self.load_scene(scene)
                 wkt = scene_geoms[obj]
 
             geoms.append("'%s'::geometry" % wkt)
index 1bb2acaa040a68f2057276506c8d3e24fc8e1eda..201bf373db3ba2fff04067e5cb70e421a4cb6c90 100644 (file)
@@ -8,7 +8,7 @@ import psycopg2.extras
 class PlaceColumn:
 
     def __init__(self, context, force_name):
-        self.columns = {}
+        self.columns = { 'admin_level' : 100}
         self.force_name = force_name
         self.context = context
         self.geometry = None
@@ -41,14 +41,12 @@ class PlaceColumn:
     def set_key_housenr(self, value):
         self.columns['housenumber'] = value
 
-    def set_key_cc(self, value):
-        ok_(len(value) == 2)
+    def set_key_country(self, value):
         self.columns['country_code'] = value
 
     def set_key_geometry(self, value):
-        geom, precision = self.context.osm.parse_geometry(value, self.context.scene)
-        assert_is_not_none(geom)
-        self.geometry = "ST_SetSRID('%s'::geometry, 4326)" % geom
+        self.geometry = self.context.osm.parse_geometry(value, self.context.scene)
+        assert_is_not_none(self.geometry)
 
     def add_hstore(self, column, key, value):
         if column in self.columns:
@@ -104,6 +102,9 @@ class NominatimID:
 
         return where, params
 
+@given(u'the scene (?P<scene>.+)')
+def set_default_scene(context, scene):
+    context.scene = scene
 
 @given("the (?P<named>named )?places")
 def add_data_to_place_table(context, named):
@@ -169,5 +170,18 @@ def check_placex_contents(context, exact):
                     assert_almost_equal(float(x) * fac, res['cx'])
                     assert_almost_equal(float(y) * fac, res['cy'])
                 else:
-                    eq_(row[h], str(res[h]))
+                    eq_(row[h], str(res[h]),
+                        "Row '%s': expected: %s, got: %s" % (h, row[h], str(res[h])))
+    context.db.commit()
+
+@then("placex has no entry for (?P<oid>.*)")
+def check_placex_has_entry(context, oid):
+    cur = context.db.cursor(cursor_factory=psycopg2.extras.DictCursor)
+    nid = NominatimID(oid)
+    where, params = nid.table_select()
+    cur.execute("""SELECT *, ST_AsText(geometry) as geomtxt,
+                   ST_X(centroid) as cx, ST_Y(centroid) as cy
+                   FROM placex where %s""" % where,
+                params)
+    eq_(0, cur.rowcount)
     context.db.commit()