]> git.openstreetmap.org Git - nominatim.git/blob - test/python/test_cli.py
c4f3ef36e3dc3c095c4eedd1d3a53e9a69c735f5
[nominatim.git] / test / python / test_cli.py
1 """
2 Tests for command line interface wrapper.
3
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
6 the actual functions.
7 """
8 import psycopg2
9 import pytest
10 import time
11
12 import nominatim.cli
13 import nominatim.indexer.indexer
14 import nominatim.tools.refresh
15 import nominatim.tools.replication
16 from nominatim.errors import UsageError
17
18 def call_nominatim(*args):
19     return nominatim.cli.nominatim(module_dir='build/module',
20                                    osm2pgsql_path='build/osm2pgsql/osm2pgsql',
21                                    phplib_dir='lib',
22                                    data_dir='.',
23                                    phpcgi_path='/usr/bin/php-cgi',
24                                    cli_args=args)
25
26 class MockParamCapture:
27     """ Mock that records the parameters with which a function was called
28         as well as the number of calls.
29     """
30     def __init__(self, retval=0):
31         self.called = 0
32         self.return_value = retval
33
34     def __call__(self, *args, **kwargs):
35         self.called += 1
36         self.last_args = args
37         self.last_kwargs = kwargs
38         return self.return_value
39
40 @pytest.fixture
41 def mock_run_legacy(monkeypatch):
42     mock = MockParamCapture()
43     monkeypatch.setattr(nominatim.cli, 'run_legacy_script', mock)
44     return mock
45
46 @pytest.fixture
47 def mock_run_api(monkeypatch):
48     mock = MockParamCapture()
49     monkeypatch.setattr(nominatim.cli, 'run_api_script', mock)
50     return mock
51
52
53 def test_cli_help(capsys):
54     """ Running nominatim tool without arguments prints help.
55     """
56     assert 1 == call_nominatim()
57
58     captured = capsys.readouterr()
59     assert captured.out.startswith('usage:')
60
61
62 @pytest.mark.parametrize("command,script", [
63                          (('import', '--continue', 'load-data'), 'setup'),
64                          (('freeze',), 'setup'),
65                          (('special-phrases',), 'specialphrases'),
66                          (('add-data', '--tiger-data', 'tiger'), 'setup'),
67                          (('add-data', '--file', 'foo.osm'), 'update'),
68                          (('check-database',), 'check_import_finished'),
69                          (('warm',), 'warm'),
70                          (('export',), 'export')
71                          ])
72 def test_legacy_commands_simple(mock_run_legacy, command, script):
73     assert 0 == call_nominatim(*command)
74
75     assert mock_run_legacy.called == 1
76     assert mock_run_legacy.last_args[0] == script + '.php'
77
78
79 @pytest.mark.parametrize("name,oid", [('file', 'foo.osm'), ('diff', 'foo.osc'),
80                                       ('node', 12), ('way', 8), ('relation', 32)])
81 def test_add_data_command(mock_run_legacy, name, oid):
82     assert 0 == call_nominatim('add-data', '--' + name, str(oid))
83
84     assert mock_run_legacy.called == 1
85     assert mock_run_legacy.last_args == ('update.php', '--import-' + name, oid)
86
87
88 @pytest.mark.parametrize("params,do_bnds,do_ranks", [
89                           ([], 1, 1),
90                           (['--boundaries-only'], 1, 0),
91                           (['--no-boundaries'], 0, 1),
92                           (['--boundaries-only', '--no-boundaries'], 0, 0)])
93 def test_index_command(monkeypatch, temp_db_cursor, params, do_bnds, do_ranks):
94     temp_db_cursor.execute("CREATE TABLE import_status (indexed bool)")
95     bnd_mock = MockParamCapture()
96     monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_boundaries', bnd_mock)
97     rank_mock = MockParamCapture()
98     monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_by_rank', rank_mock)
99
100     assert 0 == call_nominatim('index', *params)
101
102     assert bnd_mock.called == do_bnds
103     assert rank_mock.called == do_ranks
104
105
106 @pytest.mark.parametrize("command,params", [
107                          ('wiki-data', ('setup.php', '--import-wikipedia-articles')),
108                          ('importance', ('update.php', '--recompute-importance')),
109                          ('website', ('setup.php', '--setup-website')),
110                          ])
111 def test_refresh_legacy_command(mock_run_legacy, temp_db, command, params):
112     assert 0 == call_nominatim('refresh', '--' + command)
113
114     assert mock_run_legacy.called == 1
115     assert len(mock_run_legacy.last_args) >= len(params)
116     assert mock_run_legacy.last_args[:len(params)] == params
117
118 @pytest.mark.parametrize("command,func", [
119                          ('postcodes', 'update_postcodes'),
120                          ('word-counts', 'recompute_word_counts'),
121                          ('address-levels', 'load_address_levels_from_file'),
122                          ('functions', 'create_functions'),
123                          ])
124 def test_refresh_command(monkeypatch, temp_db, command, func):
125     func_mock = MockParamCapture()
126     monkeypatch.setattr(nominatim.tools.refresh, func, func_mock)
127
128     assert 0 == call_nominatim('refresh', '--' + command)
129     assert func_mock.called == 1
130
131
132 def test_refresh_importance_computed_after_wiki_import(mock_run_legacy, temp_db):
133     assert 0 == call_nominatim('refresh', '--importance', '--wiki-data')
134
135     assert mock_run_legacy.called == 2
136     assert mock_run_legacy.last_args == ('update.php', '--recompute-importance')
137
138
139 @pytest.mark.parametrize("params,func", [
140                          (('--init', '--no-update-functions'), 'init_replication'),
141                          (('--check-for-updates',), 'check_for_updates')
142                          ])
143 def test_replication_command(monkeypatch, temp_db, params, func):
144     func_mock = MockParamCapture()
145     monkeypatch.setattr(nominatim.tools.replication, func, func_mock)
146
147     assert 0 == call_nominatim('replication', *params)
148     assert func_mock.called == 1
149
150
151 def test_replication_update_bad_interval(monkeypatch, temp_db):
152     monkeypatch.setenv('NOMINATIM_REPLICATION_UPDATE_INTERVAL', 'xx')
153
154     assert call_nominatim('replication') == 1
155
156
157 def test_replication_update_bad_interval_for_geofabrik(monkeypatch, temp_db):
158     monkeypatch.setenv('NOMINATIM_REPLICATION_URL',
159                        'https://download.geofabrik.de/europe/ireland-and-northern-ireland-updates')
160
161     assert call_nominatim('replication') == 1
162
163
164 @pytest.mark.parametrize("state, retval", [
165                          (nominatim.tools.replication.UpdateState.UP_TO_DATE, 0),
166                          (nominatim.tools.replication.UpdateState.NO_CHANGES, 3)
167                          ])
168 def test_replication_update_once_no_index(monkeypatch, temp_db, status_table, state, retval):
169     func_mock = MockParamCapture(retval=state)
170     monkeypatch.setattr(nominatim.tools.replication, 'update', func_mock)
171
172     assert retval == call_nominatim('replication', '--once', '--no-index')
173
174
175 def test_replication_update_continuous(monkeypatch, status_table):
176     states = [nominatim.tools.replication.UpdateState.UP_TO_DATE,
177               nominatim.tools.replication.UpdateState.UP_TO_DATE]
178     monkeypatch.setattr(nominatim.tools.replication, 'update',
179                         lambda *args, **kwargs: states.pop())
180
181     index_mock = MockParamCapture()
182     monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_boundaries', index_mock)
183     monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_by_rank', index_mock)
184
185     with pytest.raises(IndexError):
186         call_nominatim('replication')
187
188     assert index_mock.called == 4
189
190
191 def test_replication_update_continuous_no_change(monkeypatch, status_table):
192     states = [nominatim.tools.replication.UpdateState.NO_CHANGES,
193               nominatim.tools.replication.UpdateState.UP_TO_DATE]
194     monkeypatch.setattr(nominatim.tools.replication, 'update',
195                         lambda *args, **kwargs: states.pop())
196
197     index_mock = MockParamCapture()
198     monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_boundaries', index_mock)
199     monkeypatch.setattr(nominatim.indexer.indexer.Indexer, 'index_by_rank', index_mock)
200
201     sleep_mock = MockParamCapture()
202     monkeypatch.setattr(time, 'sleep', sleep_mock)
203
204     with pytest.raises(IndexError):
205         call_nominatim('replication')
206
207     assert index_mock.called == 2
208     assert sleep_mock.called == 1
209     assert sleep_mock.last_args[0] == 60
210
211
212 @pytest.mark.parametrize("params", [
213                          ('search', '--query', 'new'),
214                          ('reverse', '--lat', '0', '--lon', '0'),
215                          ('lookup', '--id', 'N1'),
216                          ('details', '--node', '1'),
217                          ('details', '--way', '1'),
218                          ('details', '--relation', '1'),
219                          ('details', '--place_id', '10001'),
220                          ('status',)
221                          ])
222 def test_api_commands_simple(mock_run_api, params):
223     assert 0 == call_nominatim(*params)
224
225     assert mock_run_api.called == 1
226     assert mock_run_api.last_args[0] == params[0]