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',
31 class MockParamCapture:
32 """ Mock that records the parameters with which a function was called
33 as well as the number of calls.
35 def __init__(self, retval=0):
37 self.return_value = retval
39 def __call__(self, *args, **kwargs):
42 self.last_kwargs = kwargs
43 return self.return_value
46 def mock_run_legacy(monkeypatch):
47 mock = MockParamCapture()
48 monkeypatch.setattr(nominatim.cli, 'run_legacy_script', mock)
52 def test_cli_help(capsys):
53 """ Running nominatim tool without arguments prints help.
55 assert 1 == call_nominatim()
57 captured = capsys.readouterr()
58 assert captured.out.startswith('usage:')
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')
69 def test_legacy_commands_simple(mock_run_legacy, command, script):
70 assert 0 == call_nominatim(*command)
72 assert mock_run_legacy.called == 1
73 assert mock_run_legacy.last_args[0] == script + '.php'
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)
84 assert 0 == call_nominatim('admin', *params)
86 assert mock_run_legacy.called == 1
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)
93 assert 0 == call_nominatim('admin', *params)
94 assert mock.called == 1
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))
101 assert mock_run_legacy.called == 1
102 assert mock_run_legacy.last_args == ('update.php', '--import-' + name, oid)
105 @pytest.mark.parametrize("params,do_bnds,do_ranks", [
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)
117 assert 0 == call_nominatim('index', *params)
119 assert bnd_mock.called == do_bnds
120 assert rank_mock.called == do_ranks
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')),
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)
132 assert 0 == call_nominatim('refresh', '--' + command)
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
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'),
144 def test_refresh_command(monkeypatch, temp_db, command, func):
145 func_mock = MockParamCapture()
146 monkeypatch.setattr(nominatim.tools.refresh, func, func_mock)
148 assert 0 == call_nominatim('refresh', '--' + command)
149 assert func_mock.called == 1
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)
156 assert 0 == call_nominatim('refresh', '--importance', '--wiki-data')
158 assert mock_run_legacy.called == 2
159 assert mock_run_legacy.last_args == ('update.php', '--recompute-importance')
162 @pytest.mark.parametrize("params,func", [
163 (('--init', '--no-update-functions'), 'init_replication'),
164 (('--check-for-updates',), 'check_for_updates')
166 def test_replication_command(monkeypatch, temp_db, params, func):
167 func_mock = MockParamCapture()
168 monkeypatch.setattr(nominatim.tools.replication, func, func_mock)
170 assert 0 == call_nominatim('replication', *params)
171 assert func_mock.called == 1
174 def test_replication_update_bad_interval(monkeypatch, temp_db):
175 monkeypatch.setenv('NOMINATIM_REPLICATION_UPDATE_INTERVAL', 'xx')
177 assert call_nominatim('replication') == 1
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')
184 assert call_nominatim('replication') == 1
187 @pytest.mark.parametrize("state, retval", [
188 (nominatim.tools.replication.UpdateState.UP_TO_DATE, 0),
189 (nominatim.tools.replication.UpdateState.NO_CHANGES, 3)
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)
197 assert retval == 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]