]> git.openstreetmap.org Git - nominatim.git/blob - test/behave/environment.py
environment for behave tests
[nominatim.git] / test / behave / environment.py
1 from behave import *
2 import logging
3 import os
4 import psycopg2
5 import psycopg2.extras
6 import subprocess
7 from sys import version_info as python_version
8
9 logger = logging.getLogger(__name__)
10
11 userconfig = {
12     'BASEURL' : 'http://localhost/nominatim',
13     'BUILDDIR' : '../build',
14     'REMOVE_TEMPLATE' : False,
15     'KEEP_TEST_DB' : False,
16     'TEMPLATE_DB' : 'test_template_nominatim',
17     'TEST_DB' : 'test_nominatim',
18     'TEST_SETTINGS_FILE' : '/tmp/nominatim_settings.php'
19 }
20
21 class NominatimEnvironment(object):
22     """ Collects all functions for the execution of Nominatim functions.
23     """
24
25     def __init__(self, config):
26         self.build_dir = os.path.abspath(config['BUILDDIR'])
27         self.template_db = config['TEMPLATE_DB']
28         self.test_db = config['TEST_DB']
29         self.local_settings_file = config['TEST_SETTINGS_FILE']
30         self.reuse_template = not config['REMOVE_TEMPLATE']
31         self.keep_scenario_db = config['KEEP_TEST_DB']
32         os.environ['NOMINATIM_SETTINGS'] = self.local_settings_file
33
34         self.template_db_done = False
35
36     def write_nominatim_config(self, dbname):
37         f = open(self.local_settings_file, 'w')
38         f.write("<?php\n  @define('CONST_Database_DSN', 'pgsql://@/%s');\n" % dbname)
39         f.close()
40
41     def cleanup(self):
42         try:
43             os.remove(self.local_settings_file)
44         except OSError:
45             pass # ignore missing file
46
47     def db_drop_database(self, name):
48         conn = psycopg2.connect(database='postgres')
49         conn.set_isolation_level(0)
50         cur = conn.cursor()
51         cur.execute('DROP DATABASE IF EXISTS %s' % (name, ))
52         conn.close()
53
54     def setup_template_db(self):
55         if self.template_db_done:
56             return
57
58         self.template_db_done = True
59
60         if self.reuse_template:
61             # check that the template is there
62             conn = psycopg2.connect(database='postgres')
63             cur = conn.cursor()
64             cur.execute('select count(*) from pg_database where datname = %s',
65                         (self.template_db,))
66             if cur.fetchone()[0] == 1:
67                 return
68             conn.close()
69         else:
70             # just in case... make sure a previous table has been dropped
71             self.db_drop_database(self.template_db)
72
73         # call the first part of database setup
74         self.write_nominatim_config(self.template_db)
75         self.run_setup_script('create-db', 'setup-db')
76         # remove external data to speed up indexing for tests
77         conn = psycopg2.connect(database=self.template_db)
78         cur = conn.cursor()
79         cur.execute("""select tablename from pg_tables
80                        where tablename in ('gb_postcode', 'us_postcode')""")
81         for t in cur:
82             conn.cursor().execute('TRUNCATE TABLE %s' % (t[0],))
83         conn.commit()
84         conn.close()
85
86         # execute osm2pgsql on an empty file to get the right tables
87         osm2pgsql = os.path.join(self.build_dir, 'osm2pgsql', 'osm2pgsql')
88         proc = subprocess.Popen([osm2pgsql, '-lsc', '-r', 'xml',
89                                  '-O', 'gazetteer', '-d', self.template_db, '-'],
90                                 cwd=self.build_dir, stdin=subprocess.PIPE,
91                                 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
92         [outstr, errstr] = proc.communicate(input=b'<osm version="0.6"></osm>')
93         logger.debug("running osm2pgsql for template: %s\n%s\n%s" % (osm2pgsql, outstr, errstr))
94         self.run_setup_script('create-functions', 'create-tables',
95                               'create-partition-tables', 'create-partition-functions',
96                               'load-data', 'create-search-indices')
97
98
99
100     def setup_db(self, context):
101         self.setup_template_db()
102         self.write_nominatim_config(self.test_db)
103         conn = psycopg2.connect(database=self.template_db)
104         conn.set_isolation_level(0)
105         cur = conn.cursor()
106         cur.execute('DROP DATABASE IF EXISTS %s' % (self.test_db, ))
107         cur.execute('CREATE DATABASE %s TEMPLATE = %s' % (self.test_db, self.template_db))
108         conn.close()
109         context.db = psycopg2.connect(database=self.test_db)
110         if python_version[0] < 3:
111             psycopg2.extras.register_hstore(context.db, globally=False, unicode=True)
112         else:
113             psycopg2.extras.register_hstore(context.db, globally=False)
114
115     def teardown_db(self, context):
116         if 'db' in context:
117             context.db.close()
118
119         if not self.keep_scenario_db:
120             self.db_drop_database(self.test_db)
121
122     def run_setup_script(self, *args):
123         self.run_nominatim_script('setup', *args)
124
125     def run_nominatim_script(self, script, *args):
126         cmd = [os.path.join(self.build_dir, 'utils', '%s.php' % script)]
127         cmd.extend(['--%s' % x for x in args])
128         proc = subprocess.Popen(cmd, cwd=self.build_dir,
129                                 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
130         (outp, outerr) = proc.communicate()
131         logger.debug("run_nominatim_script: %s\n%s\n%s" % (cmd, outp, outerr))
132         assert (proc.returncode == 0), "Script '%s' failed:\n%s\n%s\n" % (script, outp, outerr)
133
134
135 class OSMDataFactory(object):
136
137     def __init__(self):
138         scriptpath = os.path.dirname(os.path.abspath(__file__))
139         self.scene_path = os.environ.get('SCENE_PATH',
140                            os.path.join(scriptpath, '..', 'scenes', 'data'))
141
142
143 def before_all(context):
144     for k,v in userconfig.items():
145         context.config.userdata.setdefault(k, v)
146     print('config:', context.config.userdata)
147     # logging setup
148     context.config.setup_logging()
149     # Nominatim test setup
150     context.nominatim = NominatimEnvironment(context.config.userdata)
151     context.osm = OSMDataFactory()
152
153 def after_all(context):
154     context.nominatim.cleanup()
155
156
157 def before_scenario(context, scenario):
158     if 'DB' in context.tags:
159         context.nominatim.setup_db(context)
160
161 def after_scenario(context, scenario):
162     if 'DB' in context.tags:
163         context.nominatim.teardown_db(context)
164