]> git.openstreetmap.org Git - nominatim.git/blob - test/python/conftest.py
969a6aaac25136401eb1947f17695f85ad462a61
[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
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     def mk_table(name, definition='id INT', content=None):
91         temp_db_cursor.execute('CREATE TABLE {} ({})'.format(name, definition))
92         if content is not None:
93             temp_db_cursor.execute_values("INSERT INTO {} VALUES %s".format(name), content)
94
95     return mk_table
96
97
98 @pytest.fixture
99 def def_config():
100     cfg = Configuration(None, SRC_DIR.resolve() / 'settings')
101     cfg.set_libdirs(module='.', osm2pgsql='.',
102                     php=SRC_DIR / 'lib-php',
103                     sql=SRC_DIR / 'lib-sql',
104                     data=SRC_DIR / 'data')
105     return cfg
106
107 @pytest.fixture
108 def src_dir():
109     return SRC_DIR.resolve()
110
111 @pytest.fixture
112 def tmp_phplib_dir():
113     with tempfile.TemporaryDirectory() as phpdir:
114         (Path(phpdir) / 'admin').mkdir()
115
116         yield Path(phpdir)
117
118
119 @pytest.fixture
120 def property_table(table_factory):
121     table_factory('nominatim_properties', 'property TEXT, value TEXT')
122
123 @pytest.fixture
124 def status_table(temp_db_conn):
125     """ Create an empty version of the status table and
126         the status logging table.
127     """
128     with temp_db_conn.cursor() as cur:
129         cur.execute("""CREATE TABLE import_status (
130                            lastimportdate timestamp with time zone NOT NULL,
131                            sequence_id integer,
132                            indexed boolean
133                        )""")
134         cur.execute("""CREATE TABLE import_osmosis_log (
135                            batchend timestamp,
136                            batchseq integer,
137                            batchsize bigint,
138                            starttime timestamp,
139                            endtime timestamp,
140                            event text
141                            )""")
142     temp_db_conn.commit()
143
144
145 @pytest.fixture
146 def place_table(temp_db_with_extensions, temp_db_conn):
147     """ Create an empty version of the place table.
148     """
149     with temp_db_conn.cursor() as cur:
150         cur.execute("""CREATE TABLE place (
151                            osm_id int8 NOT NULL,
152                            osm_type char(1) NOT NULL,
153                            class text NOT NULL,
154                            type text NOT NULL,
155                            name hstore,
156                            admin_level smallint,
157                            address hstore,
158                            extratags hstore,
159                            geometry Geometry(Geometry,4326) NOT NULL)""")
160     temp_db_conn.commit()
161
162
163 @pytest.fixture
164 def place_row(place_table, temp_db_cursor):
165     """ A factory for rows in the place table. The table is created as a
166         prerequisite to the fixture.
167     """
168     idseq = itertools.count(1001)
169     def _insert(osm_type='N', osm_id=None, cls='amenity', typ='cafe', names=None,
170                 admin_level=None, address=None, extratags=None, geom=None):
171         temp_db_cursor.execute("INSERT INTO place VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)",
172                                (osm_id or next(idseq), osm_type, cls, typ, names,
173                                 admin_level, address, extratags,
174                                 geom or 'SRID=4326;POINT(0 0)'))
175
176     return _insert
177
178 @pytest.fixture
179 def placex_table(temp_db_with_extensions, temp_db_conn):
180     """ Create an empty version of the place table.
181     """
182     return mocks.MockPlacexTable(temp_db_conn)
183
184
185 @pytest.fixture
186 def osmline_table(temp_db_with_extensions, temp_db_conn):
187     with temp_db_conn.cursor() as cur:
188         cur.execute("""CREATE TABLE location_property_osmline (
189                            place_id BIGINT,
190                            osm_id BIGINT,
191                            parent_place_id BIGINT,
192                            geometry_sector INTEGER,
193                            indexed_date TIMESTAMP,
194                            startnumber INTEGER,
195                            endnumber INTEGER,
196                            partition SMALLINT,
197                            indexed_status SMALLINT,
198                            linegeo GEOMETRY,
199                            interpolationtype TEXT,
200                            address HSTORE,
201                            postcode TEXT,
202                            country_code VARCHAR(2))""")
203     temp_db_conn.commit()
204
205
206 @pytest.fixture
207 def word_table(temp_db_conn):
208     return mocks.MockWordTable(temp_db_conn)
209
210
211 @pytest.fixture
212 def osm2pgsql_options(temp_db):
213     return dict(osm2pgsql='echo',
214                 osm2pgsql_cache=10,
215                 osm2pgsql_style='style.file',
216                 threads=1,
217                 dsn='dbname=' + temp_db,
218                 flatnode_file='',
219                 tablespaces=dict(slim_data='', slim_index='',
220                                  main_data='', main_index=''))
221
222 @pytest.fixture
223 def sql_preprocessor(temp_db_conn, tmp_path, monkeypatch, table_factory):
224     table_factory('country_name', 'partition INT', ((0, ), (1, ), (2, )))
225     cfg = Configuration(None, SRC_DIR.resolve() / 'settings')
226     cfg.set_libdirs(module='.', osm2pgsql='.', php=SRC_DIR / 'lib-php',
227                     sql=tmp_path, data=SRC_DIR / 'data')
228
229     return SQLPreprocessor(temp_db_conn, cfg)
230
231
232 @pytest.fixture
233 def tokenizer_mock(monkeypatch, property_table, temp_db_conn, tmp_path):
234     """ Sets up the configuration so that the test dummy tokenizer will be
235         loaded when the tokenizer factory is used. Also returns a factory
236         with which a new dummy tokenizer may be created.
237     """
238     monkeypatch.setenv('NOMINATIM_TOKENIZER', 'dummy')
239
240     def _import_dummy(module, *args, **kwargs):
241         return dummy_tokenizer
242
243     monkeypatch.setattr(nominatim.tokenizer.factory, "_import_tokenizer", _import_dummy)
244     properties.set_property(temp_db_conn, 'tokenizer', 'dummy')
245
246     def _create_tokenizer():
247         return dummy_tokenizer.DummyTokenizer(None, None)
248
249     return _create_tokenizer