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.indexer.indexer
17 import nominatim.tools.refresh
18 import nominatim.tools.replication
19 from nominatim.errors import UsageError
20 from nominatim.db import status
22 def call_nominatim(*args):
23 return nominatim.cli.nominatim(module_dir='build/module',
24 osm2pgsql_path='build/osm2pgsql/osm2pgsql',
27 phpcgi_path='/usr/bin/php-cgi',
30 class MockParamCapture:
31 """ Mock that records the parameters with which a function was called
32 as well as the number of calls.
34 def __init__(self, retval=0):
36 self.return_value = retval
38 def __call__(self, *args, **kwargs):
41 self.last_kwargs = kwargs
42 return self.return_value
45 def mock_run_legacy(monkeypatch):
46 mock = MockParamCapture()
47 monkeypatch.setattr(nominatim.cli, 'run_legacy_script', mock)
51 def test_cli_help(capsys):
52 """ Running nominatim tool without arguments prints help.
54 assert 1 == call_nominatim()
56 captured = capsys.readouterr()
57 assert captured.out.startswith('usage:')
60 @pytest.mark.parametrize("command,script", [
61 (('import', '--continue', 'load-data'), 'setup'),
62 (('freeze',), 'setup'),
63 (('special-phrases',), 'specialphrases'),
64 (('add-data', '--tiger-data', 'tiger'), 'setup'),
65 (('add-data', '--file', 'foo.osm'), 'update'),
66 (('check-database',), 'check_import_finished'),
68 (('export',), 'export')
70 def test_legacy_commands_simple(mock_run_legacy, command, script):
71 assert 0 == call_nominatim(*command)
73 assert mock_run_legacy.called == 1
74 assert mock_run_legacy.last_args[0] == script + '.php'
77 @pytest.mark.parametrize("name,oid", [('file', 'foo.osm'), ('diff', 'foo.osc'),
78 ('node', 12), ('way', 8), ('relation', 32)])
79 def test_add_data_command(mock_run_legacy, name, oid):
80 assert 0 == call_nominatim('add-data', '--' + name, str(oid))
82 assert mock_run_legacy.called == 1
83 assert mock_run_legacy.last_args == ('update.php', '--import-' + name, oid)
86 @pytest.mark.parametrize("params,do_bnds,do_ranks", [
88 (['--boundaries-only'], 1, 0),
89 (['--no-boundaries'], 0, 1),
90 (['--boundaries-only', '--no-boundaries'], 0, 0)])
91 def test_index_command(monkeypatch, temp_db_cursor, params, do_bnds, do_ranks):
92 temp_db_cursor.execute("CREATE TABLE import_status (indexed bool)")
93 bnd_mock = MockParamCapture()
94 monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_boundaries', bnd_mock)
95 rank_mock = MockParamCapture()
96 monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_by_rank', rank_mock)
98 assert 0 == call_nominatim('index', *params)
100 assert bnd_mock.called == do_bnds
101 assert rank_mock.called == do_ranks
104 @pytest.mark.parametrize("command,params", [
105 ('wiki-data', ('setup.php', '--import-wikipedia-articles')),
106 ('importance', ('update.php', '--recompute-importance')),
107 ('website', ('setup.php', '--setup-website')),
109 def test_refresh_legacy_command(monkeypatch, temp_db, command, params):
110 mock_run_legacy = MockParamCapture()
111 monkeypatch.setattr(nominatim.clicmd.refresh, 'run_legacy_script', mock_run_legacy)
113 assert 0 == call_nominatim('refresh', '--' + command)
115 assert mock_run_legacy.called == 1
116 assert len(mock_run_legacy.last_args) >= len(params)
117 assert mock_run_legacy.last_args[:len(params)] == params
119 @pytest.mark.parametrize("command,func", [
120 ('postcodes', 'update_postcodes'),
121 ('word-counts', 'recompute_word_counts'),
122 ('address-levels', 'load_address_levels_from_file'),
123 ('functions', 'create_functions'),
125 def test_refresh_command(monkeypatch, temp_db, command, func):
126 func_mock = MockParamCapture()
127 monkeypatch.setattr(nominatim.tools.refresh, func, func_mock)
129 assert 0 == call_nominatim('refresh', '--' + command)
130 assert func_mock.called == 1
133 def test_refresh_importance_computed_after_wiki_import(monkeypatch, temp_db):
134 mock_run_legacy = MockParamCapture()
135 monkeypatch.setattr(nominatim.clicmd.refresh, 'run_legacy_script', mock_run_legacy)
137 assert 0 == call_nominatim('refresh', '--importance', '--wiki-data')
139 assert mock_run_legacy.called == 2
140 assert mock_run_legacy.last_args == ('update.php', '--recompute-importance')
143 @pytest.mark.parametrize("params,func", [
144 (('--init', '--no-update-functions'), 'init_replication'),
145 (('--check-for-updates',), 'check_for_updates')
147 def test_replication_command(monkeypatch, temp_db, params, func):
148 func_mock = MockParamCapture()
149 monkeypatch.setattr(nominatim.tools.replication, func, func_mock)
151 assert 0 == call_nominatim('replication', *params)
152 assert func_mock.called == 1
155 def test_replication_update_bad_interval(monkeypatch, temp_db):
156 monkeypatch.setenv('NOMINATIM_REPLICATION_UPDATE_INTERVAL', 'xx')
158 assert call_nominatim('replication') == 1
161 def test_replication_update_bad_interval_for_geofabrik(monkeypatch, temp_db):
162 monkeypatch.setenv('NOMINATIM_REPLICATION_URL',
163 'https://download.geofabrik.de/europe/ireland-and-northern-ireland-updates')
165 assert call_nominatim('replication') == 1
168 @pytest.mark.parametrize("state, retval", [
169 (nominatim.tools.replication.UpdateState.UP_TO_DATE, 0),
170 (nominatim.tools.replication.UpdateState.NO_CHANGES, 3)
172 def test_replication_update_once_no_index(monkeypatch, temp_db, temp_db_conn,
173 status_table, state, retval):
174 status.set_status(temp_db_conn, date=dt.datetime.now(dt.timezone.utc), seq=1)
175 func_mock = MockParamCapture(retval=state)
176 monkeypatch.setattr(nominatim.tools.replication, 'update', func_mock)
178 assert retval == call_nominatim('replication', '--once', '--no-index')
181 def test_replication_update_continuous(monkeypatch, temp_db_conn, status_table):
182 status.set_status(temp_db_conn, date=dt.datetime.now(dt.timezone.utc), seq=1)
183 states = [nominatim.tools.replication.UpdateState.UP_TO_DATE,
184 nominatim.tools.replication.UpdateState.UP_TO_DATE]
185 monkeypatch.setattr(nominatim.tools.replication, 'update',
186 lambda *args, **kwargs: states.pop())
188 index_mock = MockParamCapture()
189 monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_boundaries', index_mock)
190 monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_by_rank', index_mock)
192 with pytest.raises(IndexError):
193 call_nominatim('replication')
195 assert index_mock.called == 4
198 def test_replication_update_continuous_no_change(monkeypatch, temp_db_conn, status_table):
199 status.set_status(temp_db_conn, date=dt.datetime.now(dt.timezone.utc), seq=1)
200 states = [nominatim.tools.replication.UpdateState.NO_CHANGES,
201 nominatim.tools.replication.UpdateState.UP_TO_DATE]
202 monkeypatch.setattr(nominatim.tools.replication, 'update',
203 lambda *args, **kwargs: states.pop())
205 index_mock = MockParamCapture()
206 monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_boundaries', index_mock)
207 monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_by_rank', index_mock)
209 sleep_mock = MockParamCapture()
210 monkeypatch.setattr(time, 'sleep', sleep_mock)
212 with pytest.raises(IndexError):
213 call_nominatim('replication')
215 assert index_mock.called == 2
216 assert sleep_mock.called == 1
217 assert sleep_mock.last_args[0] == 60
220 def test_serve_command(monkeypatch):
221 func = MockParamCapture()
222 monkeypatch.setattr(nominatim.cli, 'run_php_server', func)
224 call_nominatim('serve')
226 assert func.called == 1
228 @pytest.mark.parametrize("params", [
229 ('search', '--query', 'new'),
230 ('reverse', '--lat', '0', '--lon', '0'),
231 ('lookup', '--id', 'N1'),
232 ('details', '--node', '1'),
233 ('details', '--way', '1'),
234 ('details', '--relation', '1'),
235 ('details', '--place_id', '10001'),
238 def test_api_commands_simple(monkeypatch, params):
239 mock_run_api = MockParamCapture()
240 monkeypatch.setattr(nominatim.clicmd.api, 'run_api_script', mock_run_api)
242 assert 0 == call_nominatim(*params)
244 assert mock_run_api.called == 1
245 assert mock_run_api.last_args[0] == params[0]