]> git.openstreetmap.org Git - nominatim.git/blob - test/python/conftest.py
77093c4e349e5fe8b0cd85e76322f71a93157a7d
[nominatim.git] / test / python / conftest.py
1 import itertools
2 import sys
3 import tempfile
4 from pathlib import Path
5
6 import psycopg2
7 import pytest
8
9 SRC_DIR = Path(__file__) / '..' / '..' / '..'
10
11 # always test against the source
12 sys.path.insert(0, str(SRC_DIR.resolve()))
13
14 from nominatim.config import Configuration
15 from nominatim.db import connection
16 from nominatim.db.sql_preprocessor import SQLPreprocessor
17 from nominatim.db import properties
18 import nominatim.tokenizer.factory
19 import nominatim.cli
20
21 import dummy_tokenizer
22 import mocks
23 from cursor import CursorForTesting
24
25
26 @pytest.fixture
27 def temp_db(monkeypatch):
28     """ Create an empty database for the test. The database name is also
29         exported into NOMINATIM_DATABASE_DSN.
30     """
31     name = 'test_nominatim_python_unittest'
32     conn = psycopg2.connect(database='postgres')
33
34     conn.set_isolation_level(0)
35     with conn.cursor() as cur:
36         cur.execute('DROP DATABASE IF EXISTS {}'.format(name))
37         cur.execute('CREATE DATABASE {}'.format(name))
38
39     conn.close()
40
41     monkeypatch.setenv('NOMINATIM_DATABASE_DSN', 'dbname=' + name)
42
43     yield name
44
45     conn = psycopg2.connect(database='postgres')
46
47     conn.set_isolation_level(0)
48     with conn.cursor() as cur:
49         cur.execute('DROP DATABASE IF EXISTS {}'.format(name))
50
51     conn.close()
52
53
54 @pytest.fixture
55 def dsn(temp_db):
56     return 'dbname=' + temp_db
57
58
59 @pytest.fixture
60 def temp_db_with_extensions(temp_db):
61     conn = psycopg2.connect(database=temp_db)
62     with conn.cursor() as cur:
63         cur.execute('CREATE EXTENSION hstore; CREATE EXTENSION postgis;')
64     conn.commit()
65     conn.close()
66
67     return temp_db
68
69 @pytest.fixture
70 def temp_db_conn(temp_db):
71     """ Connection to the test database.
72     """
73     with connection.connect('dbname=' + temp_db) as conn:
74         yield conn
75
76
77 @pytest.fixture
78 def temp_db_cursor(temp_db):
79     """ Connection and cursor towards the test database. The connection will
80         be in auto-commit mode.
81     """
82     conn = psycopg2.connect('dbname=' + temp_db)
83     conn.set_isolation_level(0)
84     with conn.cursor(cursor_factory=CursorForTesting) as cur:
85         yield cur
86     conn.close()
87
88
89 @pytest.fixture
90 def table_factory(temp_db_cursor):
91     def mk_table(name, definition='id INT', content=None):
92         temp_db_cursor.execute('CREATE TABLE {} ({})'.format(name, definition))
93         if content is not None:
94             temp_db_cursor.execute_values("INSERT INTO {} VALUES %s".format(name), content)
95
96     return mk_table
97
98
99 @pytest.fixture
100 def def_config():
101     cfg = Configuration(None, SRC_DIR.resolve() / 'settings')
102     cfg.set_libdirs(module='.', osm2pgsql='.',
103                     php=SRC_DIR / 'lib-php',
104                     sql=SRC_DIR / 'lib-sql',
105                     data=SRC_DIR / 'data')
106     return cfg
107
108
109 @pytest.fixture
110 def src_dir():
111     return SRC_DIR.resolve()
112
113
114 @pytest.fixture
115 def cli_call():
116     def _call_nominatim(*args):
117         return nominatim.cli.nominatim(
118                    module_dir='MODULE NOT AVAILABLE',
119                    osm2pgsql_path='OSM2PGSQL NOT AVAILABLE',
120                    phplib_dir=str(SRC_DIR / 'lib-php'),
121                    data_dir=str(SRC_DIR / 'data'),
122                    phpcgi_path='/usr/bin/php-cgi',
123                    sqllib_dir=str(SRC_DIR / 'lib-sql'),
124                    config_dir=str(SRC_DIR / 'settings'),
125                    cli_args=args)
126
127     return _call_nominatim
128
129
130 @pytest.fixture
131 def tmp_phplib_dir():
132     with tempfile.TemporaryDirectory() as phpdir:
133         (Path(phpdir) / 'admin').mkdir()
134
135         yield Path(phpdir)
136
137
138 @pytest.fixture
139 def property_table(table_factory):
140     table_factory('nominatim_properties', 'property TEXT, value TEXT')
141
142 @pytest.fixture
143 def status_table(temp_db_conn):
144     """ Create an empty version of the status table and
145         the status logging table.
146     """
147     with temp_db_conn.cursor() as cur:
148         cur.execute("""CREATE TABLE import_status (
149                            lastimportdate timestamp with time zone NOT NULL,
150                            sequence_id integer,
151                            indexed boolean
152                        )""")
153         cur.execute("""CREATE TABLE import_osmosis_log (
154                            batchend timestamp,
155                            batchseq integer,
156                            batchsize bigint,
157                            starttime timestamp,
158                            endtime timestamp,
159                            event text
160                            )""")
161     temp_db_conn.commit()
162
163
164 @pytest.fixture
165 def place_table(temp_db_with_extensions, temp_db_conn):
166     """ Create an empty version of the place table.
167     """
168     with temp_db_conn.cursor() as cur:
169         cur.execute("""CREATE TABLE place (
170                            osm_id int8 NOT NULL,
171                            osm_type char(1) NOT NULL,
172                            class text NOT NULL,
173                            type text NOT NULL,
174                            name hstore,
175                            admin_level smallint,
176                            address hstore,
177                            extratags hstore,
178                            geometry Geometry(Geometry,4326) NOT NULL)""")
179     temp_db_conn.commit()
180
181
182 @pytest.fixture
183 def place_row(place_table, temp_db_cursor):
184     """ A factory for rows in the place table. The table is created as a
185         prerequisite to the fixture.
186     """
187     idseq = itertools.count(1001)
188     def _insert(osm_type='N', osm_id=None, cls='amenity', typ='cafe', names=None,
189                 admin_level=None, address=None, extratags=None, geom=None):
190         temp_db_cursor.execute("INSERT INTO place VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)",
191                                (osm_id or next(idseq), osm_type, cls, typ, names,
192                                 admin_level, address, extratags,
193                                 geom or 'SRID=4326;POINT(0 0)'))
194
195     return _insert
196
197 @pytest.fixture
198 def placex_table(temp_db_with_extensions, temp_db_conn):
199     """ Create an empty version of the place table.
200     """
201     return mocks.MockPlacexTable(temp_db_conn)
202
203
204 @pytest.fixture
205 def osmline_table(temp_db_with_extensions, temp_db_conn):
206     with temp_db_conn.cursor() as cur:
207         cur.execute("""CREATE TABLE location_property_osmline (
208                            place_id BIGINT,
209                            osm_id BIGINT,
210                            parent_place_id BIGINT,
211                            geometry_sector INTEGER,
212                            indexed_date TIMESTAMP,
213                            startnumber INTEGER,
214                            endnumber INTEGER,
215                            partition SMALLINT,
216                            indexed_status SMALLINT,
217                            linegeo GEOMETRY,
218                            interpolationtype TEXT,
219                            address HSTORE,
220                            postcode TEXT,
221                            country_code VARCHAR(2))""")
222     temp_db_conn.commit()
223
224
225 @pytest.fixture
226 def word_table(temp_db_conn):
227     return mocks.MockWordTable(temp_db_conn)
228
229
230 @pytest.fixture
231 def osm2pgsql_options(temp_db):
232     return dict(osm2pgsql='echo',
233                 osm2pgsql_cache=10,
234                 osm2pgsql_style='style.file',
235                 threads=1,
236                 dsn='dbname=' + temp_db,
237                 flatnode_file='',
238                 tablespaces=dict(slim_data='', slim_index='',
239                                  main_data='', main_index=''))
240
241 @pytest.fixture
242 def sql_preprocessor(temp_db_conn, tmp_path, monkeypatch, table_factory):
243     table_factory('country_name', 'partition INT', ((0, ), (1, ), (2, )))
244     cfg = Configuration(None, SRC_DIR.resolve() / 'settings')
245     cfg.set_libdirs(module='.', osm2pgsql='.', php=SRC_DIR / 'lib-php',
246                     sql=tmp_path, data=SRC_DIR / 'data')
247
248     return SQLPreprocessor(temp_db_conn, cfg)
249
250
251 @pytest.fixture
252 def tokenizer_mock(monkeypatch, property_table, temp_db_conn, tmp_path):
253     """ Sets up the configuration so that the test dummy tokenizer will be
254         loaded when the tokenizer factory is used. Also returns a factory
255         with which a new dummy tokenizer may be created.
256     """
257     monkeypatch.setenv('NOMINATIM_TOKENIZER', 'dummy')
258
259     def _import_dummy(module, *args, **kwargs):
260         return dummy_tokenizer
261
262     monkeypatch.setattr(nominatim.tokenizer.factory, "_import_tokenizer", _import_dummy)
263     properties.set_property(temp_db_conn, 'tokenizer', 'dummy')
264
265     def _create_tokenizer():
266         return dummy_tokenizer.DummyTokenizer(None, None)
267
268     return _create_tokenizer