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
89 @pytest.mark.parametrize("name,oid", [('file', 'foo.osm'), ('diff', 'foo.osc'),
90 ('node', 12), ('way', 8), ('relation', 32)])
91 def test_add_data_command(mock_run_legacy, name, oid):
92 assert 0 == call_nominatim('add-data', '--' + name, str(oid))
94 assert mock_run_legacy.called == 1
95 assert mock_run_legacy.last_args == ('update.php', '--import-' + name, oid)
98 @pytest.mark.parametrize("params,do_bnds,do_ranks", [
100 (['--boundaries-only'], 1, 0),
101 (['--no-boundaries'], 0, 1),
102 (['--boundaries-only', '--no-boundaries'], 0, 0)])
103 def test_index_command(monkeypatch, temp_db_cursor, params, do_bnds, do_ranks):
104 temp_db_cursor.execute("CREATE TABLE import_status (indexed bool)")
105 bnd_mock = MockParamCapture()
106 monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_boundaries', bnd_mock)
107 rank_mock = MockParamCapture()
108 monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_by_rank', rank_mock)
110 assert 0 == call_nominatim('index', *params)
112 assert bnd_mock.called == do_bnds
113 assert rank_mock.called == do_ranks
116 @pytest.mark.parametrize("command,params", [
117 ('wiki-data', ('setup.php', '--import-wikipedia-articles')),
118 ('importance', ('update.php', '--recompute-importance')),
119 ('website', ('setup.php', '--setup-website')),
121 def test_refresh_legacy_command(monkeypatch, temp_db, command, params):
122 mock_run_legacy = MockParamCapture()
123 monkeypatch.setattr(nominatim.clicmd.refresh, 'run_legacy_script', mock_run_legacy)
125 assert 0 == call_nominatim('refresh', '--' + command)
127 assert mock_run_legacy.called == 1
128 assert len(mock_run_legacy.last_args) >= len(params)
129 assert mock_run_legacy.last_args[:len(params)] == params
131 @pytest.mark.parametrize("command,func", [
132 ('postcodes', 'update_postcodes'),
133 ('word-counts', 'recompute_word_counts'),
134 ('address-levels', 'load_address_levels_from_file'),
135 ('functions', 'create_functions'),
137 def test_refresh_command(monkeypatch, temp_db, command, func):
138 func_mock = MockParamCapture()
139 monkeypatch.setattr(nominatim.tools.refresh, func, func_mock)
141 assert 0 == call_nominatim('refresh', '--' + command)
142 assert func_mock.called == 1
145 def test_refresh_importance_computed_after_wiki_import(monkeypatch, temp_db):
146 mock_run_legacy = MockParamCapture()
147 monkeypatch.setattr(nominatim.clicmd.refresh, 'run_legacy_script', mock_run_legacy)
149 assert 0 == call_nominatim('refresh', '--importance', '--wiki-data')
151 assert mock_run_legacy.called == 2
152 assert mock_run_legacy.last_args == ('update.php', '--recompute-importance')
155 @pytest.mark.parametrize("params,func", [
156 (('--init', '--no-update-functions'), 'init_replication'),
157 (('--check-for-updates',), 'check_for_updates')
159 def test_replication_command(monkeypatch, temp_db, params, func):
160 func_mock = MockParamCapture()
161 monkeypatch.setattr(nominatim.tools.replication, func, func_mock)
163 assert 0 == call_nominatim('replication', *params)
164 assert func_mock.called == 1
167 def test_replication_update_bad_interval(monkeypatch, temp_db):
168 monkeypatch.setenv('NOMINATIM_REPLICATION_UPDATE_INTERVAL', 'xx')
170 assert call_nominatim('replication') == 1
173 def test_replication_update_bad_interval_for_geofabrik(monkeypatch, temp_db):
174 monkeypatch.setenv('NOMINATIM_REPLICATION_URL',
175 'https://download.geofabrik.de/europe/ireland-and-northern-ireland-updates')
177 assert call_nominatim('replication') == 1
180 @pytest.mark.parametrize("state, retval", [
181 (nominatim.tools.replication.UpdateState.UP_TO_DATE, 0),
182 (nominatim.tools.replication.UpdateState.NO_CHANGES, 3)
184 def test_replication_update_once_no_index(monkeypatch, temp_db, temp_db_conn,
185 status_table, state, retval):
186 status.set_status(temp_db_conn, date=dt.datetime.now(dt.timezone.utc), seq=1)
187 func_mock = MockParamCapture(retval=state)
188 monkeypatch.setattr(nominatim.tools.replication, 'update', func_mock)
190 assert retval == call_nominatim('replication', '--once', '--no-index')
193 def test_replication_update_continuous(monkeypatch, temp_db_conn, status_table):
194 status.set_status(temp_db_conn, date=dt.datetime.now(dt.timezone.utc), seq=1)
195 states = [nominatim.tools.replication.UpdateState.UP_TO_DATE,
196 nominatim.tools.replication.UpdateState.UP_TO_DATE]
197 monkeypatch.setattr(nominatim.tools.replication, 'update',
198 lambda *args, **kwargs: states.pop())
200 index_mock = MockParamCapture()
201 monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_boundaries', index_mock)
202 monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_by_rank', index_mock)
204 with pytest.raises(IndexError):
205 call_nominatim('replication')
207 assert index_mock.called == 4
210 def test_replication_update_continuous_no_change(monkeypatch, temp_db_conn, status_table):
211 status.set_status(temp_db_conn, date=dt.datetime.now(dt.timezone.utc), seq=1)
212 states = [nominatim.tools.replication.UpdateState.NO_CHANGES,
213 nominatim.tools.replication.UpdateState.UP_TO_DATE]
214 monkeypatch.setattr(nominatim.tools.replication, 'update',
215 lambda *args, **kwargs: states.pop())
217 index_mock = MockParamCapture()
218 monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_boundaries', index_mock)
219 monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_by_rank', index_mock)
221 sleep_mock = MockParamCapture()
222 monkeypatch.setattr(time, 'sleep', sleep_mock)
224 with pytest.raises(IndexError):
225 call_nominatim('replication')
227 assert index_mock.called == 2
228 assert sleep_mock.called == 1
229 assert sleep_mock.last_args[0] == 60
232 def test_serve_command(monkeypatch):
233 func = MockParamCapture()
234 monkeypatch.setattr(nominatim.cli, 'run_php_server', func)
236 call_nominatim('serve')
238 assert func.called == 1
240 @pytest.mark.parametrize("params", [
241 ('search', '--query', 'new'),
242 ('reverse', '--lat', '0', '--lon', '0'),
243 ('lookup', '--id', 'N1'),
244 ('details', '--node', '1'),
245 ('details', '--way', '1'),
246 ('details', '--relation', '1'),
247 ('details', '--place_id', '10001'),
250 def test_api_commands_simple(monkeypatch, params):
251 mock_run_api = MockParamCapture()
252 monkeypatch.setattr(nominatim.clicmd.api, 'run_api_script', mock_run_api)
254 assert 0 == call_nominatim(*params)
256 assert mock_run_api.called == 1
257 assert mock_run_api.last_args[0] == params[0]