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