forked from hans/Nominatim
add functional tests
These are the tests that were formerly located at https://github.com/lonvia/test-nominatim
This commit is contained in:
212
tests/steps/osm2pgsql_setup.py
Normal file
212
tests/steps/osm2pgsql_setup.py
Normal file
@@ -0,0 +1,212 @@
|
||||
""" Steps for setting up a test database for osm2pgsql import.
|
||||
|
||||
Note that osm2pgsql features need a database and therefore need
|
||||
to be tagged with @DB.
|
||||
"""
|
||||
|
||||
from nose.tools import *
|
||||
from lettuce import *
|
||||
|
||||
import logging
|
||||
import random
|
||||
import tempfile
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@before.each_scenario
|
||||
def osm2pgsql_setup_test(scenario):
|
||||
world.osm2pgsql = []
|
||||
|
||||
@step(u'the osm nodes:')
|
||||
def osm2pgsql_import_nodes(step):
|
||||
""" Define a list of OSM nodes to be imported, given as a table.
|
||||
Each line describes one node with all its attributes.
|
||||
'id' is mendatory, all other fields are filled with random values
|
||||
when not given. If 'tags' is missing an empty tag list is assumed.
|
||||
For updates, a mandatory 'action' column needs to contain 'A' (add),
|
||||
'M' (modify), 'D' (delete).
|
||||
"""
|
||||
for line in step.hashes:
|
||||
node = { 'type' : 'N', 'version' : '1', 'timestamp': "2012-05-01T15:06:20Z",
|
||||
'changeset' : "11470653", 'uid' : "122294", 'user' : "foo"
|
||||
}
|
||||
node.update(line)
|
||||
node['id'] = int(node['id'])
|
||||
if 'geometry' in node:
|
||||
lat, lon = node['geometry'].split(' ')
|
||||
node['lat'] = float(lat)
|
||||
node['lon'] = float(lon)
|
||||
else:
|
||||
node['lon'] = random.random()*360 - 180
|
||||
node['lat'] = random.random()*180 - 90
|
||||
if 'tags' in node:
|
||||
node['tags'] = world.make_hash(line['tags'])
|
||||
else:
|
||||
node['tags'] = {}
|
||||
|
||||
world.osm2pgsql.append(node)
|
||||
|
||||
|
||||
@step(u'the osm ways:')
|
||||
def osm2pgsql_import_ways(step):
|
||||
""" Define a list of OSM ways to be imported.
|
||||
"""
|
||||
for line in step.hashes:
|
||||
way = { 'type' : 'W', 'version' : '1', 'timestamp': "2012-05-01T15:06:20Z",
|
||||
'changeset' : "11470653", 'uid' : "122294", 'user' : "foo"
|
||||
}
|
||||
way.update(line)
|
||||
|
||||
way['id'] = int(way['id'])
|
||||
if 'tags' in way:
|
||||
way['tags'] = world.make_hash(line['tags'])
|
||||
else:
|
||||
way['tags'] = None
|
||||
way['nodes'] = way['nodes'].strip().split()
|
||||
|
||||
world.osm2pgsql.append(way)
|
||||
|
||||
membertype = { 'N' : 'node', 'W' : 'way', 'R' : 'relation' }
|
||||
|
||||
@step(u'the osm relations:')
|
||||
def osm2pgsql_import_rels(step):
|
||||
""" Define a list of OSM relation to be imported.
|
||||
"""
|
||||
for line in step.hashes:
|
||||
rel = { 'type' : 'R', 'version' : '1', 'timestamp': "2012-05-01T15:06:20Z",
|
||||
'changeset' : "11470653", 'uid' : "122294", 'user' : "foo"
|
||||
}
|
||||
rel.update(line)
|
||||
|
||||
rel['id'] = int(rel['id'])
|
||||
if 'tags' in rel:
|
||||
rel['tags'] = world.make_hash(line['tags'])
|
||||
else:
|
||||
rel['tags'] = {}
|
||||
members = []
|
||||
if rel['members'].strip():
|
||||
for mem in line['members'].split(','):
|
||||
memparts = mem.strip().split(':', 2)
|
||||
memid = memparts[0].upper()
|
||||
members.append((membertype[memid[0]],
|
||||
memid[1:],
|
||||
memparts[1] if len(memparts) == 2 else ''
|
||||
))
|
||||
rel['members'] = members
|
||||
|
||||
world.osm2pgsql.append(rel)
|
||||
|
||||
|
||||
|
||||
def _sort_xml_entries(x, y):
|
||||
if x['type'] == y['type']:
|
||||
return cmp(x['id'], y['id'])
|
||||
else:
|
||||
return cmp('NWR'.find(x['type']), 'NWR'.find(y['type']))
|
||||
|
||||
def write_osm_obj(fd, obj):
|
||||
if obj['type'] == 'N':
|
||||
fd.write('<node id="%(id)d" lat="%(lat).8f" lon="%(lon).8f" version="%(version)s" timestamp="%(timestamp)%" changeset="%(changeset)s" uid="%(uid)s" user="%(user)s"'% obj)
|
||||
if obj['tags'] is None:
|
||||
fd.write('/>\n')
|
||||
else:
|
||||
fd.write('>\n')
|
||||
for k,v in obj['tags'].iteritems():
|
||||
fd.write(' <tag k="%s" v="%s"/>\n' % (k, v))
|
||||
fd.write('</node>\n')
|
||||
elif obj['type'] == 'W':
|
||||
fd.write('<way id="%(id)d" version="%(version)s" changeset="%(changeset)s" timestamp="%(timestamp)s" user="%(user)s" uid="%(uid)s">\n' % obj)
|
||||
for nd in obj['nodes']:
|
||||
fd.write('<nd ref="%s" />\n' % (nd,))
|
||||
for k,v in obj['tags'].iteritems():
|
||||
fd.write(' <tag k="%s" v="%s"/>\n' % (k, v))
|
||||
fd.write('</way>\n')
|
||||
elif obj['type'] == 'R':
|
||||
fd.write('<relation id="%(id)d" version="%(version)s" changeset="%(changeset)s" timestamp="%(timestamp)s" user="%(user)s" uid="%(uid)s">\n' % obj)
|
||||
for mem in obj['members']:
|
||||
fd.write(' <member type="%s" ref="%s" role="%s"/>\n' % mem)
|
||||
for k,v in obj['tags'].iteritems():
|
||||
fd.write(' <tag k="%s" v="%s"/>\n' % (k, v))
|
||||
fd.write('</relation>\n')
|
||||
|
||||
@step(u'loading osm data')
|
||||
def osm2pgsql_load_place(step):
|
||||
"""Imports the previously defined OSM data into a fresh copy of a
|
||||
Nominatim test database.
|
||||
"""
|
||||
|
||||
world.osm2pgsql.sort(cmp=_sort_xml_entries)
|
||||
|
||||
# create a OSM file in /tmp
|
||||
with tempfile.NamedTemporaryFile(dir='/tmp', delete=False) as fd:
|
||||
fname = fd.name
|
||||
fd.write("<?xml version='1.0' encoding='UTF-8'?>\n")
|
||||
fd.write('<osm version="0.6" generator="test-nominatim" timestamp="2014-08-26T20:22:02Z">\n')
|
||||
fd.write('\t<bounds minlat="43.72335" minlon="7.409205" maxlat="43.75169" maxlon="7.448637"/>\n')
|
||||
|
||||
for obj in world.osm2pgsql:
|
||||
write_osm_obj(fd, obj)
|
||||
|
||||
fd.write('</osm>\n')
|
||||
|
||||
logger.debug( "Filename: %s" % fname)
|
||||
|
||||
cmd = [os.path.join(world.config.source_dir, 'utils', 'setup.php')]
|
||||
cmd.extend(['--osm-file', fname, '--import-data'])
|
||||
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
(outp, outerr) = proc.communicate()
|
||||
assert (proc.returncode == 0), "OSM data import failed:\n%s\n%s\n" % (outp, outerr)
|
||||
|
||||
### reintroduce the triggers/indexes we've lost by having osm2pgsql set up place again
|
||||
cur = world.conn.cursor()
|
||||
cur.execute("""CREATE TRIGGER place_before_delete BEFORE DELETE ON place
|
||||
FOR EACH ROW EXECUTE PROCEDURE place_delete()""")
|
||||
cur.execute("""CREATE TRIGGER place_before_insert BEFORE INSERT ON place
|
||||
FOR EACH ROW EXECUTE PROCEDURE place_insert()""")
|
||||
cur.execute("""CREATE UNIQUE INDEX idx_place_osm_unique on place using btree(osm_id,osm_type,class,type)""")
|
||||
world.conn.commit()
|
||||
|
||||
|
||||
os.remove(fname)
|
||||
world.osm2pgsql = []
|
||||
|
||||
actiontypes = { 'C' : 'create', 'M' : 'modify', 'D' : 'delete' }
|
||||
|
||||
@step(u'updating osm data')
|
||||
def osm2pgsql_update_place(step):
|
||||
"""Creates an osc file from the previously defined data and imports it
|
||||
into the database.
|
||||
"""
|
||||
world.run_nominatim_script('setup', 'create-functions', 'create-partition-functions')
|
||||
cur = world.conn.cursor()
|
||||
cur.execute("""insert into placex (osm_type, osm_id, class, type, name, admin_level,
|
||||
housenumber, street, addr_place, isin, postcode, country_code, extratags,
|
||||
geometry) select * from place""")
|
||||
world.conn.commit()
|
||||
world.run_nominatim_script('setup', 'index', 'index-noanalyse')
|
||||
world.run_nominatim_script('setup', 'create-functions', 'create-partition-functions', 'enable-diff-updates')
|
||||
|
||||
with tempfile.NamedTemporaryFile(dir='/tmp', delete=False) as fd:
|
||||
fname = fd.name
|
||||
fd.write("<?xml version='1.0' encoding='UTF-8'?>\n")
|
||||
fd.write('<osmChange version="0.6" generator="Osmosis 0.43.1">\n')
|
||||
|
||||
for obj in world.osm2pgsql:
|
||||
fd.write('<%s>\n' % (actiontypes[obj['action']], ))
|
||||
write_osm_obj(fd, obj)
|
||||
fd.write('</%s>\n' % (actiontypes[obj['action']], ))
|
||||
|
||||
fd.write('</osmChange>\n')
|
||||
|
||||
logger.debug( "Filename: %s" % fname)
|
||||
|
||||
cmd = [os.path.join(world.config.source_dir, 'utils', 'update.php')]
|
||||
cmd.extend(['--import-diff', fname])
|
||||
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
(outp, outerr) = proc.communicate()
|
||||
assert (proc.returncode == 0), "OSM data update failed:\n%s\n%s\n" % (outp, outerr)
|
||||
|
||||
os.remove(fname)
|
||||
world.osm2pgsql = []
|
||||
Reference in New Issue
Block a user