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