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