]> git.openstreetmap.org Git - nominatim.git/blob - test/python/cli/test_cmd_replication.py
Merge remote-tracking branch 'upstream/master'
[nominatim.git] / test / python / cli / test_cmd_replication.py
1 # SPDX-License-Identifier: GPL-2.0-only
2 #
3 # This file is part of Nominatim. (https://nominatim.org)
4 #
5 # Copyright (C) 2022 by the Nominatim developer community.
6 # For a full list of authors see the git log.
7 """
8 Tests for replication command of command-line interface wrapper.
9 """
10 import datetime as dt
11 import time
12
13 import pytest
14
15 import nominatim.cli
16 import nominatim.indexer.indexer
17 import nominatim.tools.replication
18 from nominatim.db import status
19
20 @pytest.fixture
21 def tokenizer_mock(monkeypatch):
22     class DummyTokenizer:
23         def __init__(self, *args, **kwargs):
24             self.update_sql_functions_called = False
25             self.finalize_import_called = False
26
27         def update_sql_functions(self, *args):
28             self.update_sql_functions_called = True
29
30         def finalize_import(self, *args):
31             self.finalize_import_called = True
32
33     tok = DummyTokenizer()
34     monkeypatch.setattr(nominatim.tokenizer.factory, 'get_tokenizer_for_db',
35                         lambda *args: tok)
36     monkeypatch.setattr(nominatim.tokenizer.factory, 'create_tokenizer',
37                         lambda *args: tok)
38
39     return tok
40
41
42
43 @pytest.fixture
44 def init_status(temp_db_conn, status_table):
45     status.set_status(temp_db_conn, date=dt.datetime.now(dt.timezone.utc), seq=1)
46
47
48 @pytest.fixture
49 def index_mock(mock_func_factory, tokenizer_mock, init_status):
50     return mock_func_factory(nominatim.indexer.indexer.Indexer, 'index_full')
51
52
53 @pytest.fixture
54 def update_mock(mock_func_factory, init_status, tokenizer_mock):
55     return mock_func_factory(nominatim.tools.replication, 'update')
56
57
58 class TestCliReplication:
59
60     @pytest.fixture(autouse=True)
61     def setup_cli_call(self, cli_call, temp_db):
62         self.call_nominatim = lambda *args: cli_call('replication', *args)
63
64
65     @pytest.fixture(autouse=True)
66     def setup_update_function(self, monkeypatch):
67         def _mock_updates(states):
68             monkeypatch.setattr(nominatim.tools.replication, 'update',
69                             lambda *args, **kwargs: states.pop())
70
71         self.update_states = _mock_updates
72
73
74     @pytest.mark.parametrize("params,func", [
75                              (('--init',), 'init_replication'),
76                              (('--init', '--no-update-functions'), 'init_replication'),
77                              (('--check-for-updates',), 'check_for_updates')
78                              ])
79     def test_replication_command(self, mock_func_factory, params, func):
80         func_mock = mock_func_factory(nominatim.tools.replication, func)
81
82         if params == ('--init',):
83             umock = mock_func_factory(nominatim.tools.refresh, 'create_functions')
84
85         assert self.call_nominatim(*params) == 0
86         assert func_mock.called == 1
87         if params == ('--init',):
88             assert umock.called == 1
89
90
91     def test_replication_update_bad_interval(self, monkeypatch):
92         monkeypatch.setenv('NOMINATIM_REPLICATION_UPDATE_INTERVAL', 'xx')
93
94         assert self.call_nominatim() == 1
95
96
97     def test_replication_update_bad_interval_for_geofabrik(self, monkeypatch):
98         monkeypatch.setenv('NOMINATIM_REPLICATION_URL',
99                            'https://download.geofabrik.de/europe/italy-updates')
100
101         assert self.call_nominatim() == 1
102
103
104     def test_replication_update_continuous_no_index(self):
105         assert self.call_nominatim('--no-index') == 1
106
107     def test_replication_update_once_no_index(self, update_mock):
108         assert self.call_nominatim('--once', '--no-index') == 0
109
110         assert str(update_mock.last_args[1]['osm2pgsql']) == 'OSM2PGSQL NOT AVAILABLE'
111
112
113     def test_replication_update_custom_osm2pgsql(self, monkeypatch, update_mock):
114         monkeypatch.setenv('NOMINATIM_OSM2PGSQL_BINARY', '/secret/osm2pgsql')
115         assert self.call_nominatim('--once', '--no-index') == 0
116
117         assert str(update_mock.last_args[1]['osm2pgsql']) == '/secret/osm2pgsql'
118
119
120     @pytest.mark.parametrize("update_interval", [60, 3600])
121     def test_replication_catchup(self, placex_table, monkeypatch, index_mock, update_interval):
122         monkeypatch.setenv('NOMINATIM_REPLICATION_UPDATE_INTERVAL', str(update_interval))
123         self.update_states([nominatim.tools.replication.UpdateState.NO_CHANGES])
124
125         assert self.call_nominatim('--catch-up') == 0
126
127
128     def test_replication_update_custom_threads(self, update_mock):
129         assert self.call_nominatim('--once', '--no-index', '--threads', '4') == 0
130
131         assert update_mock.last_args[1]['threads'] == 4
132
133
134     def test_replication_update_continuous(self, index_mock):
135         self.update_states([nominatim.tools.replication.UpdateState.UP_TO_DATE,
136                             nominatim.tools.replication.UpdateState.UP_TO_DATE])
137
138         with pytest.raises(IndexError):
139             self.call_nominatim()
140
141         assert index_mock.called == 2
142
143
144     def test_replication_update_continuous_no_change(self, mock_func_factory,
145                                                      index_mock):
146         self.update_states([nominatim.tools.replication.UpdateState.NO_CHANGES,
147                             nominatim.tools.replication.UpdateState.UP_TO_DATE])
148
149         sleep_mock = mock_func_factory(time, 'sleep')
150
151         with pytest.raises(IndexError):
152             self.call_nominatim()
153
154         assert index_mock.called == 1
155         assert sleep_mock.called == 1
156         assert sleep_mock.last_args[0] == 60