]> git.openstreetmap.org Git - nominatim.git/commitdiff
add interpolation tests
authorSarah Hoffmann <lonvia@denofr.de>
Sat, 26 Nov 2016 23:47:37 +0000 (00:47 +0100)
committerSarah Hoffmann <lonvia@denofr.de>
Fri, 30 Dec 2016 21:58:58 +0000 (22:58 +0100)
test/bdd/db/import/interpolation.feature [new file with mode: 0644]
test/bdd/steps/db_ops.py

diff --git a/test/bdd/db/import/interpolation.feature b/test/bdd/db/import/interpolation.feature
new file mode 100644 (file)
index 0000000..4ed66b9
--- /dev/null
@@ -0,0 +1,303 @@
+@DB
+Feature: Import of address interpolations
+    Tests that interpolated addresses are added correctly
+
+    Scenario: Simple even interpolation line with two points
+        Given the places
+          | osm | class | type   | housenr | geometry |
+          | N1  | place | house  | 2       | 1 1 |
+          | N2  | place | house  | 6       | 1 1.001 |
+          | W1  | place | houses | even    | 1 1, 1 1.001 |
+        And the ways
+          | id | nodes |
+          | 1  | 1,2 |
+        When importing
+        Then W1 expands to interpolation
+          | start | end | geometry |
+          | 2     | 6   | 1 1, 1 1.001 |
+
+    Scenario: Backwards even two point interpolation line
+        Given the places
+          | osm | class | type   | housenr | geometry |
+          | N1  | place | house  | 2       | 1 1 |
+          | N2  | place | house  | 6       | 1 1.001 |
+          | W1  | place | houses | even    | 1 1.001, 1 1 |
+        And the ways
+          | id | nodes |
+          | 1  | 2,1 |
+        When importing
+        Then W1 expands to interpolation
+          | start | end | geometry |
+          | 2     | 6   | 1 1, 1 1.001 |
+
+    Scenario: Simple odd two point interpolation
+        Given the places
+          | osm | class | type   | housenr | geometry |
+          | N1  | place | house  | 1       | 1 1 |
+          | N2  | place | house  | 11      | 1 1.001 |
+          | W1  | place | houses | odd     | 1 1, 1 1.001 |
+        And the ways
+          | id | nodes |
+          | 1  | 1,2 |
+        When importing
+        Then W1 expands to interpolation
+          | start | end | geometry |
+          | 1     | 11  | 1 1, 1 1.001 |
+
+    Scenario: Simple all two point interpolation
+        Given the places
+          | osm | class | type   | housenr | geometry |
+          | N1  | place | house  | 1       | 1 1 |
+          | N2  | place | house  | 3       | 1 1.001 |
+          | W1  | place | houses | all     | 1 1, 1 1.001 |
+        And the ways
+          | id | nodes |
+          | 1  | 1,2 |
+        When importing
+        Then W1 expands to interpolation
+          | start | end | geometry |
+          | 1     | 3   | 1 1, 1 1.001 |
+
+    Scenario: Even two point interpolation line with intermediate empty node
+        Given the places
+          | osm | class | type   | housenr | geometry |
+          | N1  | place | house  | 2       | 1 1 |
+          | N2  | place | house  | 10      | 1.001 1.001 |
+          | W1  | place | houses | even    | 1 1, 1 1.001, 1.001 1.001 |
+        And the ways
+          | id | nodes |
+          | 1  | 1,3,2 |
+        When importing
+        Then W1 expands to interpolation
+          | start | end | geometry |
+          | 2     | 10  | 1 1, 1 1.001, 1.001 1.001 |
+
+    Scenario: Even two point interpolation line with intermediate duplicated empty node
+        Given the places
+          | osm | class | type   | housenr | geometry |
+          | N1  | place | house  | 2       | 1 1 |
+          | N2  | place | house  | 10      | 1.001 1.001 |
+          | W1  | place | houses | even    | 1 1, 1 1.001, 1.001 1.001 |
+        And the ways
+          | id | nodes |
+          | 1  | 1,3,3,2 |
+        When importing
+        Then W1 expands to interpolation
+          | start | end | geometry |
+          | 2     | 10  | 1 1, 1 1.001, 1.001 1.001 |
+
+    Scenario: Simple even three point interpolation line
+        Given the places
+          | osm | class | type   | housenr | geometry |
+          | N1  | place | house  | 2       | 1 1 |
+          | N2  | place | house  | 14      | 1.001 1.001 |
+          | N3  | place | house  | 10      | 1 1.001 |
+          | W1  | place | houses | even    | 1 1, 1 1.001, 1.001 1.001 |
+        And the ways
+          | id | nodes |
+          | 1  | 1,3,2 |
+        When importing
+        Then W1 expands to interpolation
+          | start | end | geometry |
+          | 2     | 10  | 1 1, 1 1.001 |
+          | 10    | 14  | 1 1.001, 1.001 1.001 |
+
+    Scenario: Simple even four point interpolation line
+        Given the places
+          | osm | class | type  | housenr | geometry |
+          | N1  | place | house | 2       | 1 1 |
+          | N2  | place | house | 14      | 1.001 1.001 |
+          | N3  | place | house | 10      | 1 1.001 |
+          | N4  | place | house | 18      | 1.001 1.002 |
+          | W1  | place | houses | even    | 1 1, 1 1.001, 1.001 1.001, 1.001 1.002 |
+        And the ways
+          | id | nodes |
+          | 1  | 1,3,2,4 |
+        When importing
+        Then W1 expands to interpolation
+          | start | end | geometry |
+          | 2     | 10  | 1 1, 1 1.001 |
+          | 10    | 14  | 1 1.001, 1.001 1.001 |
+          | 14    | 18  | 1.001 1.001, 1.001 1.002 |
+
+    Scenario: Reverse simple even three point interpolation line
+        Given the places
+          | osm | class | type  | housenr | geometry |
+          | N1  | place | house | 2       | 1 1 |
+          | N2  | place | house | 14      | 1.001 1.001 |
+          | N3  | place | house | 10      | 1 1.001 |
+          | W1  | place | houses | even    | 1.001 1.001, 1 1.001, 1 1 |
+        And the ways
+          | id | nodes |
+          | 1  | 2,3,1 |
+        When importing
+        Then W1 expands to interpolation
+          | start | end | geometry |
+          | 2     | 10  | 1 1, 1 1.001 |
+          | 10    | 14  | 1 1.001, 1.001 1.001 |
+
+    Scenario: Even three point interpolation line with odd center point
+        Given the places
+          | osm | class | type  | housenr | geometry |
+          | N1  | place | house | 2       | 1 1 |
+          | N2  | place | house | 8       | 1.001 1.001 |
+          | N3  | place | house | 7       | 1 1.001 |
+          | W1  | place | houses | even    | 1 1, 1 1.001, 1.001 1.001 |
+        And the ways
+          | id | nodes |
+          | 1  | 1,3,2 |
+        When importing
+        Then W1 expands to interpolation
+          | start | end | geometry |
+          | 2     | 7   | 1 1, 1 1.001 |
+          | 7     | 8   | 1 1.001, 1.001 1.001 |
+
+    Scenario: Interpolation line with self-intersecting way
+        Given the places
+          | osm | class | type  | housenr | geometry |
+          | N1  | place | house | 2       | 0 0 |
+          | N2  | place | house | 6       | 0 0.001 |
+          | N3  | place | house | 10      | 0 0.002 |
+          | W1  | place | houses | even    | 0 0, 0 0.001, 0 0.002, 0 0.001 |
+        And the ways
+          | id | nodes |
+          | 1  | 1,2,3,2 |
+        When importing
+        Then W1 expands to interpolation
+          | start | end | geometry |
+          | 2     | 6   | 0 0, 0 0.001 |
+          | 6     | 10  | 0 0.001, 0 0.002 |
+          | 6     | 10  | 0 0.001, 0 0.002 |
+
+    Scenario: Interpolation line with self-intersecting way II
+        Given the places
+          | osm | class | type  | housenr | geometry |
+          | N1  | place | house | 2       | 0 0 |
+          | N2  | place | house | 6       | 0 0.001 |
+          | W1  | place | houses | even    | 0 0, 0 0.001, 0 0.002, 0 0.001 |
+        And the ways
+          | id | nodes |
+          | 1  | 1,2,3,2 |
+        When importing
+        Then W1 expands to interpolation
+          | start | end | geometry |
+          | 2     | 6   | 0 0, 0 0.001 |
+
+    Scenario: addr:street on interpolation way
+        Given the scene parallel-road
+        And the places
+          | osm | class | type  | housenr | geometry |
+          | N1  | place | house | 2       | :n-middle-w |
+          | N2  | place | house | 6       | :n-middle-e |
+          | N3  | place | house | 12      | :n-middle-w |
+          | N4  | place | house | 16      | :n-middle-e |
+        And the places
+          | osm | class   | type    | housenr | street       | geometry |
+          | W10 | place   | houses  | even    |              | :w-middle |
+          | W11 | place   | houses  | even    | Cloud Street | :w-middle |
+        And the places
+          | osm | class   | type     | name         | geometry |
+          | W2  | highway | tertiary | Sun Way      | :w-north |
+          | W3  | highway | tertiary | Cloud Street | :w-south |
+        And the ways
+          | id | nodes |
+          | 10  | 1,100,101,102,2 |
+          | 11  | 3,200,201,202,4 |
+        When importing
+        Then placex contains
+          | object | parent_place_id |
+          | N1     | W2 |
+          | N2     | W2 |
+          | N3     | W3 |
+          | N4     | W3 |
+        Then W10 expands to interpolation
+          | parent_place_id | start | end |
+          | W2              | 2     | 6 |
+        Then W11 expands to interpolation
+          | parent_place_id | start | end |
+          | W3              | 12    | 16 |
+        When searching for "16 Cloud Street"
+        Then results contain
+         | ID | osm_type | osm_id |
+         | 0  | N        | 4 |
+        When searching for "14 Cloud Street"
+        Then results contain
+         | ID | osm_type | osm_id |
+         | 0  | W        | 11 |
+        When searching for "18 Cloud Street"
+        Then results contain
+         | ID | osm_type | osm_id |
+         | 0  | W        | 3 |
+
+    Scenario: addr:street on housenumber way
+        Given the scene parallel-road
+        And the places
+          | osm | class | type  | housenr | street       | geometry |
+          | N1  | place | house | 2       |              | :n-middle-w |
+          | N2  | place | house | 6       |              | :n-middle-e |
+          | N3  | place | house | 12      | Cloud Street | :n-middle-w |
+          | N4  | place | house | 16      | Cloud Street | :n-middle-e |
+        And the places
+          | osm | class   | type    | housenr | geometry |
+          | W10 | place   | houses  | even    | :w-middle |
+          | W11 | place   | houses  | even    | :w-middle |
+        And the places
+          | osm | class   | type     | name         | geometry |
+          | W2  | highway | tertiary | Sun Way      | :w-north |
+          | W3  | highway | tertiary | Cloud Street | :w-south |
+        And the ways
+          | id  | nodes |
+          | 10  | 1,100,101,102,2 |
+          | 11  | 3,200,201,202,4 |
+        When importing
+        Then placex contains
+          | object | parent_place_id |
+          | N1     | W2 |
+          | N2     | W2 |
+          | N3     | W3 |
+          | N4     | W3 |
+        Then W10 expands to interpolation
+          | parent_place_id | start | end |
+          | W2              | 2     | 6 |
+        Then W11 expands to interpolation
+          | parent_place_id | start | end |
+          | W3              | 12    | 16 |
+        When searching for "16 Cloud Street"
+        Then results contain
+         | ID | osm_type | osm_id |
+         | 0  | N        | 4 |
+        When searching for "14 Cloud Street"
+        Then results contain
+         | ID | osm_type | osm_id |
+         | 0  | W        | 11 |
+
+    Scenario: Geometry of points and way don't match (github #253)
+        Given the places
+          | osm | class | type        | housenr | geometry |
+          | N1  | place | house       | 10      | 144.9632341 -37.76163 |
+          | N2  | place | house       | 6       | 144.9630541 -37.7628174 |
+          | N3  | shop  | supermarket | 2       | 144.9629794 -37.7630755 |
+          | W1  | place | houses      | even    | 144.9632341 -37.76163,144.9630541 -37.7628172,144.9629794 -37.7630755 |
+        And the ways
+          | id | nodes |
+          | 1  | 1,2,3 |
+        When importing
+        Then W1 expands to interpolation
+          | start | end | geometry |
+          | 2     | 6   | 144.9629794 -37.7630755, 144.9630541 -37.7628174 |
+          | 6     | 10  | 144.9630541 -37.7628174, 144.9632341 -37.76163 |
+
+    Scenario: Place with missing address information
+        Given the places
+          | osm | class   | type   | housenr | geometry |
+          | N1  | place   | house  | 23      | 0.0001 0.0001 |
+          | N2  | amenity | school |         | 0.0001 0.0002 |
+          | N3  | place   | house  | 29      | 0.0001 0.0004 |
+          | W1  | place   | houses | odd     | 0.0001 0.0001,0.0001 0.0002,0.0001 0.0004 |
+        And the ways
+          | id | nodes |
+          | 1  | 1,2,3 |
+        When importing
+        Then W1 expands to interpolation
+          | start | end | geometry |
+          | 23    | 29  | 0.0001 0.0001, 0.0001 0.0002, 0.0001 0.0004 |
index 3f6c797666e21e3766fa3c25abfcb2ac649b0ab2..da65984d15ff4bc1e4633e5c1f4711e81d8ca208 100644 (file)
@@ -23,7 +23,7 @@ class PlaceColumn:
         else:
             assert_in(key, ('class', 'type', 'street', 'addr_place',
                             'isin', 'postcode'))
-            self.columns[key] = value
+            self.columns[key] = None if value == '' else value
 
     def set_key_name(self, value):
         self.add_hstore('name', 'name', value)
@@ -39,10 +39,10 @@ class PlaceColumn:
         self.columns['admin_level'] = int(value)
 
     def set_key_housenr(self, value):
-        self.columns['housenumber'] = value
+        self.columns['housenumber'] = None if value == '' else value
 
     def set_key_country(self, value):
-        self.columns['country_code'] = value
+        self.columns['country_code'] = None if value == '' else value
 
     def set_key_geometry(self, value):
         self.geometry = self.context.osm.parse_geometry(value, self.context.scene)
@@ -111,7 +111,7 @@ class NominatimID:
         return cur.fetchone()[0]
 
 
-def assert_db_column(row, column, value):
+def assert_db_column(row, column, value, context):
     if column == 'object':
         return
 
@@ -120,6 +120,12 @@ def assert_db_column(row, column, value):
         x, y = value.split(' ')
         assert_almost_equal(float(x) * fac, row['cx'])
         assert_almost_equal(float(y) * fac, row['cy'])
+    elif column == 'geometry':
+        geom = context.osm.parse_geometry(value, context.scene)
+        cur = context.db.cursor()
+        cur.execute("SELECT ST_MaxDistance(%s, ST_SetSRID(%%s::geometry, 4326))" % geom,
+                    (row['geomtxt'],))
+        assert_less(cur.fetchone()[0], 0.005)
     else:
         eq_(value, str(row[column]),
             "Row '%s': expected: %s, got: %s"
@@ -247,7 +253,7 @@ def check_placex_contents(context, exact):
                         eq_(NominatimID(row[h]).get_place_id(context.db.cursor()),
                             res[h])
                 else:
-                    assert_db_column(res, h, row[h])
+                    assert_db_column(res, h, row[h], context)
 
     if exact:
         cur.execute('SELECT osm_type, osm_id, class from placex')
@@ -278,11 +284,49 @@ def check_search_name_contents(context):
                         assert_in(wid[0], res[h],
                                   "Missing term for %s/%s: %s" % (pid, h, wid[1]))
                 else:
-                    assert_db_column(res, h, row[h])
+                    assert_db_column(res, h, row[h], context)
 
 
     context.db.commit()
 
+@then("(?P<oid>\w+) expands to interpolation")
+def check_location_property_osmline(context, oid):
+    cur = context.db.cursor(cursor_factory=psycopg2.extras.DictCursor)
+    nid = NominatimID(oid)
+
+    eq_('W', nid.typ, "interpolation must be a way")
+
+    cur.execute("""SELECT *, ST_AsText(linegeo) as geomtxt
+                   FROM location_property_osmline WHERE osm_id = %s""",
+                (nid.oid, ))
+
+    todo = list(range(len([context.table])))
+    for res in cur:
+        for i in todo:
+            row = context.table[i]
+            if (int(row['start']) == res['startnumber']
+                and int(row['end']) == res['endnumber']):
+                todo.remove(i)
+                break
+        else:
+            assert(False, "Unexpected row %s" % (str(res)))
+
+        for h in row.headings:
+            if h in ('start', 'end'):
+                continue
+            elif h == 'parent_place_id':
+                if row[h] == '0':
+                    eq_(0, res[h])
+                elif row[h] == '-':
+                    assert_is_none(res[h])
+                else:
+                    eq_(NominatimID(row[h]).get_place_id(context.db.cursor()),
+                        res[h])
+            else:
+                assert_db_column(res, h, row[h], context)
+
+    eq_(todo, [])
+
 
 @then("placex has no entry for (?P<oid>.*)")
 def check_placex_has_entry(context, oid):