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 import nominatim.tools.freeze
21 from nominatim.errors import UsageError
22 from nominatim.db import status
24 def call_nominatim(*args):
25 return nominatim.cli.nominatim(module_dir='build/module',
26 osm2pgsql_path='build/osm2pgsql/osm2pgsql',
29 phpcgi_path='/usr/bin/php-cgi',
31 config_dir='settings',
34 class MockParamCapture:
35 """ Mock that records the parameters with which a function was called
36 as well as the number of calls.
38 def __init__(self, retval=0):
40 self.return_value = retval
42 def __call__(self, *args, **kwargs):
45 self.last_kwargs = kwargs
46 return self.return_value
49 def mock_run_legacy(monkeypatch):
50 mock = MockParamCapture()
51 monkeypatch.setattr(nominatim.cli, 'run_legacy_script', mock)
55 def mock_func_factory(monkeypatch):
56 def get_mock(module, func):
57 mock = MockParamCapture()
58 monkeypatch.setattr(module, func, mock)
63 def test_cli_help(capsys):
64 """ Running nominatim tool without arguments prints help.
66 assert 1 == call_nominatim()
68 captured = capsys.readouterr()
69 assert captured.out.startswith('usage:')
72 @pytest.mark.parametrize("command,script", [
73 (('import', '--continue', 'load-data'), 'setup'),
74 (('special-phrases',), 'specialphrases'),
75 (('add-data', '--tiger-data', 'tiger'), 'setup'),
76 (('add-data', '--file', 'foo.osm'), 'update'),
77 (('export',), 'export')
79 def test_legacy_commands_simple(mock_run_legacy, command, script):
80 assert 0 == call_nominatim(*command)
82 assert mock_run_legacy.called == 1
83 assert mock_run_legacy.last_args[0] == script + '.php'
86 def test_freeze_command(mock_func_factory, temp_db):
87 mock_drop = mock_func_factory(nominatim.tools.freeze, 'drop_update_tables')
88 mock_flatnode = mock_func_factory(nominatim.tools.freeze, 'drop_flatnode_file')
90 assert 0 == call_nominatim('freeze')
92 assert mock_drop.called == 1
93 assert mock_flatnode.called == 1
96 @pytest.mark.parametrize("params", [('--warm', ),
97 ('--warm', '--reverse-only'),
98 ('--warm', '--search-only'),
99 ('--check-database', )])
100 def test_admin_command_legacy(mock_func_factory, params):
101 mock_run_legacy = mock_func_factory(nominatim.clicmd.admin, 'run_legacy_script')
103 assert 0 == call_nominatim('admin', *params)
105 assert mock_run_legacy.called == 1
107 @pytest.mark.parametrize("func, params", [('analyse_indexing', ('--analyse-indexing', ))])
108 def test_admin_command_tool(temp_db, mock_func_factory, func, params):
109 mock = mock_func_factory(nominatim.tools.admin, func)
111 assert 0 == call_nominatim('admin', *params)
112 assert mock.called == 1
114 @pytest.mark.parametrize("name,oid", [('file', 'foo.osm'), ('diff', 'foo.osc'),
115 ('node', 12), ('way', 8), ('relation', 32)])
116 def test_add_data_command(mock_run_legacy, name, oid):
117 assert 0 == call_nominatim('add-data', '--' + name, str(oid))
119 assert mock_run_legacy.called == 1
120 assert mock_run_legacy.last_args == ('update.php', '--import-' + name, oid)
123 @pytest.mark.parametrize("params,do_bnds,do_ranks", [
125 (['--boundaries-only'], 1, 0),
126 (['--no-boundaries'], 0, 1),
127 (['--boundaries-only', '--no-boundaries'], 0, 0)])
128 def test_index_command(mock_func_factory, temp_db_cursor, params, do_bnds, do_ranks):
129 temp_db_cursor.execute("CREATE TABLE import_status (indexed bool)")
130 bnd_mock = mock_func_factory(nominatim.indexer.indexer.Indexer, 'index_boundaries')
131 rank_mock = mock_func_factory(nominatim.indexer.indexer.Indexer, 'index_by_rank')
133 assert 0 == call_nominatim('index', *params)
135 assert bnd_mock.called == do_bnds
136 assert rank_mock.called == do_ranks
139 @pytest.mark.parametrize("command,params", [
140 ('wiki-data', ('setup.php', '--import-wikipedia-articles')),
141 ('importance', ('update.php', '--recompute-importance')),
142 ('website', ('setup.php', '--setup-website')),
144 def test_refresh_legacy_command(mock_func_factory, temp_db, command, params):
145 mock_run_legacy = mock_func_factory(nominatim.clicmd.refresh, 'run_legacy_script')
147 assert 0 == call_nominatim('refresh', '--' + command)
149 assert mock_run_legacy.called == 1
150 assert len(mock_run_legacy.last_args) >= len(params)
151 assert mock_run_legacy.last_args[:len(params)] == params
153 @pytest.mark.parametrize("command,func", [
154 ('postcodes', 'update_postcodes'),
155 ('word-counts', 'recompute_word_counts'),
156 ('address-levels', 'load_address_levels_from_file'),
157 ('functions', 'create_functions'),
159 def test_refresh_command(mock_func_factory, temp_db, command, func):
160 func_mock = mock_func_factory(nominatim.tools.refresh, func)
162 assert 0 == call_nominatim('refresh', '--' + command)
163 assert func_mock.called == 1
166 def test_refresh_importance_computed_after_wiki_import(mock_func_factory, temp_db):
167 mock_run_legacy = mock_func_factory(nominatim.clicmd.refresh, 'run_legacy_script')
169 assert 0 == call_nominatim('refresh', '--importance', '--wiki-data')
171 assert mock_run_legacy.called == 2
172 assert mock_run_legacy.last_args == ('update.php', '--recompute-importance')
175 @pytest.mark.parametrize("params,func", [
176 (('--init', '--no-update-functions'), 'init_replication'),
177 (('--check-for-updates',), 'check_for_updates')
179 def test_replication_command(mock_func_factory, temp_db, params, func):
180 func_mock = mock_func_factory(nominatim.tools.replication, func)
182 assert 0 == call_nominatim('replication', *params)
183 assert func_mock.called == 1
186 def test_replication_update_bad_interval(monkeypatch, temp_db):
187 monkeypatch.setenv('NOMINATIM_REPLICATION_UPDATE_INTERVAL', 'xx')
189 assert call_nominatim('replication') == 1
192 def test_replication_update_bad_interval_for_geofabrik(monkeypatch, temp_db):
193 monkeypatch.setenv('NOMINATIM_REPLICATION_URL',
194 'https://download.geofabrik.de/europe/ireland-and-northern-ireland-updates')
196 assert call_nominatim('replication') == 1
199 @pytest.mark.parametrize("state", [nominatim.tools.replication.UpdateState.UP_TO_DATE,
200 nominatim.tools.replication.UpdateState.NO_CHANGES])
201 def test_replication_update_once_no_index(mock_func_factory, temp_db, temp_db_conn,
202 status_table, state):
203 status.set_status(temp_db_conn, date=dt.datetime.now(dt.timezone.utc), seq=1)
204 func_mock = mock_func_factory(nominatim.tools.replication, 'update')
206 assert 0 == call_nominatim('replication', '--once', '--no-index')
209 def test_replication_update_continuous(monkeypatch, temp_db_conn, status_table):
210 status.set_status(temp_db_conn, date=dt.datetime.now(dt.timezone.utc), seq=1)
211 states = [nominatim.tools.replication.UpdateState.UP_TO_DATE,
212 nominatim.tools.replication.UpdateState.UP_TO_DATE]
213 monkeypatch.setattr(nominatim.tools.replication, 'update',
214 lambda *args, **kwargs: states.pop())
216 index_mock = MockParamCapture()
217 monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_boundaries', index_mock)
218 monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_by_rank', index_mock)
220 with pytest.raises(IndexError):
221 call_nominatim('replication')
223 assert index_mock.called == 4
226 def test_replication_update_continuous_no_change(monkeypatch, temp_db_conn, status_table):
227 status.set_status(temp_db_conn, date=dt.datetime.now(dt.timezone.utc), seq=1)
228 states = [nominatim.tools.replication.UpdateState.NO_CHANGES,
229 nominatim.tools.replication.UpdateState.UP_TO_DATE]
230 monkeypatch.setattr(nominatim.tools.replication, 'update',
231 lambda *args, **kwargs: states.pop())
233 index_mock = MockParamCapture()
234 monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_boundaries', index_mock)
235 monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_by_rank', index_mock)
237 sleep_mock = MockParamCapture()
238 monkeypatch.setattr(time, 'sleep', sleep_mock)
240 with pytest.raises(IndexError):
241 call_nominatim('replication')
243 assert index_mock.called == 2
244 assert sleep_mock.called == 1
245 assert sleep_mock.last_args[0] == 60
248 def test_serve_command(mock_func_factory):
249 func = mock_func_factory(nominatim.cli, 'run_php_server')
251 call_nominatim('serve')
253 assert func.called == 1
255 @pytest.mark.parametrize("params", [
256 ('search', '--query', 'new'),
257 ('reverse', '--lat', '0', '--lon', '0'),
258 ('lookup', '--id', 'N1'),
259 ('details', '--node', '1'),
260 ('details', '--way', '1'),
261 ('details', '--relation', '1'),
262 ('details', '--place_id', '10001'),
265 def test_api_commands_simple(mock_func_factory, params):
266 mock_run_api = mock_func_factory(nominatim.clicmd.api, 'run_api_script')
268 assert 0 == call_nominatim(*params)
270 assert mock_run_api.called == 1
271 assert mock_run_api.last_args[0] == params[0]