]> git.openstreetmap.org Git - nominatim.git/blob - test/python/test_cli.py
update osm2pgsql (disable install rule)
[nominatim.git] / test / python / test_cli.py
1 """
2 Tests for command line interface wrapper.
3
4 These tests just check that the various command line parameters route to the
5 correct functionionality. They use a lot of monkeypatching to avoid executing
6 the actual functions.
7 """
8 import datetime as dt
9 import psycopg2
10 import pytest
11 import time
12
13 import nominatim.cli
14 import nominatim.clicmd.api
15 import nominatim.clicmd.refresh
16 import nominatim.clicmd.admin
17 import nominatim.indexer.indexer
18 import nominatim.tools.refresh
19 import nominatim.tools.replication
20 from nominatim.errors import UsageError
21 from nominatim.db import status
22
23 def call_nominatim(*args):
24     return nominatim.cli.nominatim(module_dir='build/module',
25                                    osm2pgsql_path='build/osm2pgsql/osm2pgsql',
26                                    phplib_dir='lib',
27                                    data_dir='.',
28                                    phpcgi_path='/usr/bin/php-cgi',
29                                    cli_args=args)
30
31 class MockParamCapture:
32     """ Mock that records the parameters with which a function was called
33         as well as the number of calls.
34     """
35     def __init__(self, retval=0):
36         self.called = 0
37         self.return_value = retval
38
39     def __call__(self, *args, **kwargs):
40         self.called += 1
41         self.last_args = args
42         self.last_kwargs = kwargs
43         return self.return_value
44
45 @pytest.fixture
46 def mock_run_legacy(monkeypatch):
47     mock = MockParamCapture()
48     monkeypatch.setattr(nominatim.cli, 'run_legacy_script', mock)
49     return mock
50
51
52 def test_cli_help(capsys):
53     """ Running nominatim tool without arguments prints help.
54     """
55     assert 1 == call_nominatim()
56
57     captured = capsys.readouterr()
58     assert captured.out.startswith('usage:')
59
60
61 @pytest.mark.parametrize("command,script", [
62                          (('import', '--continue', 'load-data'), 'setup'),
63                          (('freeze',), 'setup'),
64                          (('special-phrases',), 'specialphrases'),
65                          (('add-data', '--tiger-data', 'tiger'), 'setup'),
66                          (('add-data', '--file', 'foo.osm'), 'update'),
67                          (('export',), 'export')
68                          ])
69 def test_legacy_commands_simple(mock_run_legacy, command, script):
70     assert 0 == call_nominatim(*command)
71
72     assert mock_run_legacy.called == 1
73     assert mock_run_legacy.last_args[0] == script + '.php'
74
75
76 @pytest.mark.parametrize("params", [('--warm', ),
77                                     ('--warm', '--reverse-only'),
78                                     ('--warm', '--search-only'),
79                                     ('--check-database', )])
80 def test_admin_command_legacy(monkeypatch, params):
81     mock_run_legacy = MockParamCapture()
82     monkeypatch.setattr(nominatim.clicmd.admin, 'run_legacy_script', mock_run_legacy)
83
84     assert 0 == call_nominatim('admin', *params)
85
86     assert mock_run_legacy.called == 1
87
88 @pytest.mark.parametrize("func, params", [('analyse_indexing', ('--analyse-indexing', ))])
89 def test_admin_command_tool(monkeypatch, func, params):
90     mock = MockParamCapture()
91     monkeypatch.setattr(nominatim.tools.admin, func, mock)
92
93     assert 0 == call_nominatim('admin', *params)
94     assert mock.called == 1
95
96 @pytest.mark.parametrize("name,oid", [('file', 'foo.osm'), ('diff', 'foo.osc'),
97                                       ('node', 12), ('way', 8), ('relation', 32)])
98 def test_add_data_command(mock_run_legacy, name, oid):
99     assert 0 == call_nominatim('add-data', '--' + name, str(oid))
100
101     assert mock_run_legacy.called == 1
102     assert mock_run_legacy.last_args == ('update.php', '--import-' + name, oid)
103
104
105 @pytest.mark.parametrize("params,do_bnds,do_ranks", [
106                           ([], 1, 1),
107                           (['--boundaries-only'], 1, 0),
108                           (['--no-boundaries'], 0, 1),
109                           (['--boundaries-only', '--no-boundaries'], 0, 0)])
110 def test_index_command(monkeypatch, temp_db_cursor, params, do_bnds, do_ranks):
111     temp_db_cursor.execute("CREATE TABLE import_status (indexed bool)")
112     bnd_mock = MockParamCapture()
113     monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_boundaries', bnd_mock)
114     rank_mock = MockParamCapture()
115     monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_by_rank', rank_mock)
116
117     assert 0 == call_nominatim('index', *params)
118
119     assert bnd_mock.called == do_bnds
120     assert rank_mock.called == do_ranks
121
122
123 @pytest.mark.parametrize("command,params", [
124                          ('wiki-data', ('setup.php', '--import-wikipedia-articles')),
125                          ('importance', ('update.php', '--recompute-importance')),
126                          ('website', ('setup.php', '--setup-website')),
127                          ])
128 def test_refresh_legacy_command(monkeypatch, temp_db, command, params):
129     mock_run_legacy = MockParamCapture()
130     monkeypatch.setattr(nominatim.clicmd.refresh, 'run_legacy_script', mock_run_legacy)
131
132     assert 0 == call_nominatim('refresh', '--' + command)
133
134     assert mock_run_legacy.called == 1
135     assert len(mock_run_legacy.last_args) >= len(params)
136     assert mock_run_legacy.last_args[:len(params)] == params
137
138 @pytest.mark.parametrize("command,func", [
139                          ('postcodes', 'update_postcodes'),
140                          ('word-counts', 'recompute_word_counts'),
141                          ('address-levels', 'load_address_levels_from_file'),
142                          ('functions', 'create_functions'),
143                          ])
144 def test_refresh_command(monkeypatch, temp_db, command, func):
145     func_mock = MockParamCapture()
146     monkeypatch.setattr(nominatim.tools.refresh, func, func_mock)
147
148     assert 0 == call_nominatim('refresh', '--' + command)
149     assert func_mock.called == 1
150
151
152 def test_refresh_importance_computed_after_wiki_import(monkeypatch, temp_db):
153     mock_run_legacy = MockParamCapture()
154     monkeypatch.setattr(nominatim.clicmd.refresh, 'run_legacy_script', mock_run_legacy)
155
156     assert 0 == call_nominatim('refresh', '--importance', '--wiki-data')
157
158     assert mock_run_legacy.called == 2
159     assert mock_run_legacy.last_args == ('update.php', '--recompute-importance')
160
161
162 @pytest.mark.parametrize("params,func", [
163                          (('--init', '--no-update-functions'), 'init_replication'),
164                          (('--check-for-updates',), 'check_for_updates')
165                          ])
166 def test_replication_command(monkeypatch, temp_db, params, func):
167     func_mock = MockParamCapture()
168     monkeypatch.setattr(nominatim.tools.replication, func, func_mock)
169
170     assert 0 == call_nominatim('replication', *params)
171     assert func_mock.called == 1
172
173
174 def test_replication_update_bad_interval(monkeypatch, temp_db):
175     monkeypatch.setenv('NOMINATIM_REPLICATION_UPDATE_INTERVAL', 'xx')
176
177     assert call_nominatim('replication') == 1
178
179
180 def test_replication_update_bad_interval_for_geofabrik(monkeypatch, temp_db):
181     monkeypatch.setenv('NOMINATIM_REPLICATION_URL',
182                        'https://download.geofabrik.de/europe/ireland-and-northern-ireland-updates')
183
184     assert call_nominatim('replication') == 1
185
186
187 @pytest.mark.parametrize("state, retval", [
188                          (nominatim.tools.replication.UpdateState.UP_TO_DATE, 0),
189                          (nominatim.tools.replication.UpdateState.NO_CHANGES, 3)
190                          ])
191 def test_replication_update_once_no_index(monkeypatch, temp_db, temp_db_conn,
192                                           status_table, state, retval):
193     status.set_status(temp_db_conn, date=dt.datetime.now(dt.timezone.utc), seq=1)
194     func_mock = MockParamCapture(retval=state)
195     monkeypatch.setattr(nominatim.tools.replication, 'update', func_mock)
196
197     assert retval == call_nominatim('replication', '--once', '--no-index')
198
199
200 def test_replication_update_continuous(monkeypatch, temp_db_conn, status_table):
201     status.set_status(temp_db_conn, date=dt.datetime.now(dt.timezone.utc), seq=1)
202     states = [nominatim.tools.replication.UpdateState.UP_TO_DATE,
203               nominatim.tools.replication.UpdateState.UP_TO_DATE]
204     monkeypatch.setattr(nominatim.tools.replication, 'update',
205                         lambda *args, **kwargs: states.pop())
206
207     index_mock = MockParamCapture()
208     monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_boundaries', index_mock)
209     monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_by_rank', index_mock)
210
211     with pytest.raises(IndexError):
212         call_nominatim('replication')
213
214     assert index_mock.called == 4
215
216
217 def test_replication_update_continuous_no_change(monkeypatch, temp_db_conn, status_table):
218     status.set_status(temp_db_conn, date=dt.datetime.now(dt.timezone.utc), seq=1)
219     states = [nominatim.tools.replication.UpdateState.NO_CHANGES,
220               nominatim.tools.replication.UpdateState.UP_TO_DATE]
221     monkeypatch.setattr(nominatim.tools.replication, 'update',
222                         lambda *args, **kwargs: states.pop())
223
224     index_mock = MockParamCapture()
225     monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_boundaries', index_mock)
226     monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_by_rank', index_mock)
227
228     sleep_mock = MockParamCapture()
229     monkeypatch.setattr(time, 'sleep', sleep_mock)
230
231     with pytest.raises(IndexError):
232         call_nominatim('replication')
233
234     assert index_mock.called == 2
235     assert sleep_mock.called == 1
236     assert sleep_mock.last_args[0] == 60
237
238
239 def test_serve_command(monkeypatch):
240     func = MockParamCapture()
241     monkeypatch.setattr(nominatim.cli, 'run_php_server', func)
242
243     call_nominatim('serve')
244
245     assert func.called == 1
246
247 @pytest.mark.parametrize("params", [
248                          ('search', '--query', 'new'),
249                          ('reverse', '--lat', '0', '--lon', '0'),
250                          ('lookup', '--id', 'N1'),
251                          ('details', '--node', '1'),
252                          ('details', '--way', '1'),
253                          ('details', '--relation', '1'),
254                          ('details', '--place_id', '10001'),
255                          ('status',)
256                          ])
257 def test_api_commands_simple(monkeypatch, params):
258     mock_run_api = MockParamCapture()
259     monkeypatch.setattr(nominatim.clicmd.api, 'run_api_script', mock_run_api)
260
261     assert 0 == call_nominatim(*params)
262
263     assert mock_run_api.called == 1
264     assert mock_run_api.last_args[0] == params[0]