2 Tests for command line interface wrapper.
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
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
23 def call_nominatim(*args):
24 return nominatim.cli.nominatim(module_dir='build/module',
25 osm2pgsql_path='build/osm2pgsql/osm2pgsql',
28 phpcgi_path='/usr/bin/php-cgi',
30 config_dir='settings',
33 class MockParamCapture:
34 """ Mock that records the parameters with which a function was called
35 as well as the number of calls.
37 def __init__(self, retval=0):
39 self.return_value = retval
41 def __call__(self, *args, **kwargs):
44 self.last_kwargs = kwargs
45 return self.return_value
48 def mock_run_legacy(monkeypatch):
49 mock = MockParamCapture()
50 monkeypatch.setattr(nominatim.cli, 'run_legacy_script', mock)
54 def test_cli_help(capsys):
55 """ Running nominatim tool without arguments prints help.
57 assert 1 == call_nominatim()
59 captured = capsys.readouterr()
60 assert captured.out.startswith('usage:')
63 @pytest.mark.parametrize("command,script", [
64 (('import', '--continue', 'load-data'), 'setup'),
65 (('freeze',), 'setup'),
66 (('special-phrases',), 'specialphrases'),
67 (('add-data', '--tiger-data', 'tiger'), 'setup'),
68 (('add-data', '--file', 'foo.osm'), 'update'),
69 (('export',), 'export')
71 def test_legacy_commands_simple(mock_run_legacy, command, script):
72 assert 0 == call_nominatim(*command)
74 assert mock_run_legacy.called == 1
75 assert mock_run_legacy.last_args[0] == script + '.php'
78 @pytest.mark.parametrize("params", [('--warm', ),
79 ('--warm', '--reverse-only'),
80 ('--warm', '--search-only'),
81 ('--check-database', )])
82 def test_admin_command_legacy(monkeypatch, params):
83 mock_run_legacy = MockParamCapture()
84 monkeypatch.setattr(nominatim.clicmd.admin, 'run_legacy_script', mock_run_legacy)
86 assert 0 == call_nominatim('admin', *params)
88 assert mock_run_legacy.called == 1
90 @pytest.mark.parametrize("func, params", [('analyse_indexing', ('--analyse-indexing', ))])
91 def test_admin_command_tool(temp_db, monkeypatch, func, params):
92 mock = MockParamCapture()
93 monkeypatch.setattr(nominatim.tools.admin, func, mock)
95 assert 0 == call_nominatim('admin', *params)
96 assert mock.called == 1
98 @pytest.mark.parametrize("name,oid", [('file', 'foo.osm'), ('diff', 'foo.osc'),
99 ('node', 12), ('way', 8), ('relation', 32)])
100 def test_add_data_command(mock_run_legacy, name, oid):
101 assert 0 == call_nominatim('add-data', '--' + name, str(oid))
103 assert mock_run_legacy.called == 1
104 assert mock_run_legacy.last_args == ('update.php', '--import-' + name, oid)
107 @pytest.mark.parametrize("params,do_bnds,do_ranks", [
109 (['--boundaries-only'], 1, 0),
110 (['--no-boundaries'], 0, 1),
111 (['--boundaries-only', '--no-boundaries'], 0, 0)])
112 def test_index_command(monkeypatch, temp_db_cursor, params, do_bnds, do_ranks):
113 temp_db_cursor.execute("CREATE TABLE import_status (indexed bool)")
114 bnd_mock = MockParamCapture()
115 monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_boundaries', bnd_mock)
116 rank_mock = MockParamCapture()
117 monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_by_rank', rank_mock)
119 assert 0 == call_nominatim('index', *params)
121 assert bnd_mock.called == do_bnds
122 assert rank_mock.called == do_ranks
125 @pytest.mark.parametrize("command,params", [
126 ('wiki-data', ('setup.php', '--import-wikipedia-articles')),
127 ('importance', ('update.php', '--recompute-importance')),
128 ('website', ('setup.php', '--setup-website')),
130 def test_refresh_legacy_command(monkeypatch, temp_db, command, params):
131 mock_run_legacy = MockParamCapture()
132 monkeypatch.setattr(nominatim.clicmd.refresh, 'run_legacy_script', mock_run_legacy)
134 assert 0 == call_nominatim('refresh', '--' + command)
136 assert mock_run_legacy.called == 1
137 assert len(mock_run_legacy.last_args) >= len(params)
138 assert mock_run_legacy.last_args[:len(params)] == params
140 @pytest.mark.parametrize("command,func", [
141 ('postcodes', 'update_postcodes'),
142 ('word-counts', 'recompute_word_counts'),
143 ('address-levels', 'load_address_levels_from_file'),
144 ('functions', 'create_functions'),
146 def test_refresh_command(monkeypatch, temp_db, command, func):
147 func_mock = MockParamCapture()
148 monkeypatch.setattr(nominatim.tools.refresh, func, func_mock)
150 assert 0 == call_nominatim('refresh', '--' + command)
151 assert func_mock.called == 1
154 def test_refresh_importance_computed_after_wiki_import(monkeypatch, temp_db):
155 mock_run_legacy = MockParamCapture()
156 monkeypatch.setattr(nominatim.clicmd.refresh, 'run_legacy_script', mock_run_legacy)
158 assert 0 == call_nominatim('refresh', '--importance', '--wiki-data')
160 assert mock_run_legacy.called == 2
161 assert mock_run_legacy.last_args == ('update.php', '--recompute-importance')
164 @pytest.mark.parametrize("params,func", [
165 (('--init', '--no-update-functions'), 'init_replication'),
166 (('--check-for-updates',), 'check_for_updates')
168 def test_replication_command(monkeypatch, temp_db, params, func):
169 func_mock = MockParamCapture()
170 monkeypatch.setattr(nominatim.tools.replication, func, func_mock)
172 assert 0 == call_nominatim('replication', *params)
173 assert func_mock.called == 1
176 def test_replication_update_bad_interval(monkeypatch, temp_db):
177 monkeypatch.setenv('NOMINATIM_REPLICATION_UPDATE_INTERVAL', 'xx')
179 assert call_nominatim('replication') == 1
182 def test_replication_update_bad_interval_for_geofabrik(monkeypatch, temp_db):
183 monkeypatch.setenv('NOMINATIM_REPLICATION_URL',
184 'https://download.geofabrik.de/europe/ireland-and-northern-ireland-updates')
186 assert call_nominatim('replication') == 1
189 @pytest.mark.parametrize("state", [nominatim.tools.replication.UpdateState.UP_TO_DATE,
190 nominatim.tools.replication.UpdateState.NO_CHANGES])
191 def test_replication_update_once_no_index(monkeypatch, temp_db, temp_db_conn,
192 status_table, state):
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)
197 assert 0 == call_nominatim('replication', '--once', '--no-index')
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())
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)
211 with pytest.raises(IndexError):
212 call_nominatim('replication')
214 assert index_mock.called == 4
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())
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)
228 sleep_mock = MockParamCapture()
229 monkeypatch.setattr(time, 'sleep', sleep_mock)
231 with pytest.raises(IndexError):
232 call_nominatim('replication')
234 assert index_mock.called == 2
235 assert sleep_mock.called == 1
236 assert sleep_mock.last_args[0] == 60
239 def test_serve_command(monkeypatch):
240 func = MockParamCapture()
241 monkeypatch.setattr(nominatim.cli, 'run_php_server', func)
243 call_nominatim('serve')
245 assert func.called == 1
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'),
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)
261 assert 0 == call_nominatim(*params)
263 assert mock_run_api.called == 1
264 assert mock_run_api.last_args[0] == params[0]