2024-06-09 15:52:20 +03:00
# SPDX-License-Identifier: GPL-3.0-or-later
2022-01-03 18:23:58 +03:00
#
# This file is part of Nominatim. (https://nominatim.org)
#
2024-06-09 15:52:20 +03:00
# Copyright (C) 2024 by the Nominatim developer community.
2022-01-03 18:23:58 +03:00
# For a full list of authors see the git log.
2021-01-27 00:45:24 +03:00
"""
Tests for replication functionality .
"""
import datetime as dt
2021-01-30 17:50:34 +03:00
import time
2021-01-27 00:45:24 +03:00
import pytest
2021-01-28 16:34:17 +03:00
from osmium . replication . server import OsmosisState
2021-01-27 00:45:24 +03:00
2024-06-09 15:52:20 +03:00
import nominatim_db . tools . replication
2024-06-27 22:26:12 +03:00
import nominatim_db . db . status as status
from nominatim_db . errors import UsageError
2021-01-27 00:45:24 +03:00
OSM_NODE_DATA = """ \
< osm version = " 0.6 " generator = " OpenStreetMap server " copyright = " OpenStreetMap and contributors " attribution = " http://www.openstreetmap.org/copyright " license = " http://opendatacommons.org/licenses/odbl/1-0/ " >
< node id = " 100 " visible = " true " version = " 1 " changeset = " 2047 " timestamp = " 2006-01-27T22:09:10Z " user = " Foo " uid = " 111 " lat = " 48.7586670 " lon = " 8.1343060 " >
< / node >
< / osm >
"""
2021-05-20 00:07:39 +03:00
@pytest.fixture ( autouse = True )
def setup_status_table ( status_table ) :
pass
2021-01-30 17:50:34 +03:00
### init replication
2021-01-27 00:45:24 +03:00
2021-05-20 00:07:39 +03:00
def test_init_replication_bad_base_url ( monkeypatch , place_row , temp_db_conn ) :
2021-01-27 00:45:24 +03:00
place_row ( osm_type = ' N ' , osm_id = 100 )
2024-06-09 15:52:20 +03:00
monkeypatch . setattr ( status , " get_url " , lambda u : OSM_NODE_DATA )
2021-01-27 00:45:24 +03:00
2021-01-30 18:20:10 +03:00
with pytest . raises ( UsageError , match = " Failed to reach replication service " ) :
2024-06-09 15:52:20 +03:00
nominatim_db . tools . replication . init_replication ( temp_db_conn , ' https://test.io ' )
2021-01-27 00:45:24 +03:00
2021-05-20 00:07:39 +03:00
def test_init_replication_success ( monkeypatch , place_row , temp_db_conn , temp_db_cursor ) :
2021-01-27 00:45:24 +03:00
place_row ( osm_type = ' N ' , osm_id = 100 )
2024-06-09 15:52:20 +03:00
monkeypatch . setattr ( status , " get_url " , lambda u : OSM_NODE_DATA )
monkeypatch . setattr ( nominatim_db . tools . replication . ReplicationServer ,
2021-01-27 00:45:24 +03:00
" timestamp_to_sequence " ,
lambda self , date : 234 )
2024-06-09 15:52:20 +03:00
nominatim_db . tools . replication . init_replication ( temp_db_conn , ' https://test.io ' )
2021-01-27 00:45:24 +03:00
2021-04-23 21:53:00 +03:00
expected_date = dt . datetime . strptime ( ' 2006-01-27T19:09:10 ' , status . ISODATE_FORMAT ) \
. replace ( tzinfo = dt . timezone . utc )
2021-05-19 13:11:04 +03:00
assert temp_db_cursor . row_set ( " SELECT * FROM import_status " ) \
== { ( expected_date , 234 , True ) }
2021-01-28 16:34:17 +03:00
2021-01-30 17:50:34 +03:00
### checking for updates
2021-05-20 00:07:39 +03:00
def test_check_for_updates_empty_status_table ( temp_db_conn ) :
2024-06-09 15:52:20 +03:00
assert nominatim_db . tools . replication . check_for_updates ( temp_db_conn , ' https://test.io ' ) == 254
2021-01-28 16:34:17 +03:00
2021-05-20 00:07:39 +03:00
def test_check_for_updates_seq_not_set ( temp_db_conn ) :
2021-01-30 17:50:34 +03:00
status . set_status ( temp_db_conn , dt . datetime . now ( dt . timezone . utc ) )
2021-01-28 16:34:17 +03:00
2024-06-09 15:52:20 +03:00
assert nominatim_db . tools . replication . check_for_updates ( temp_db_conn , ' https://test.io ' ) == 254
2021-01-28 16:34:17 +03:00
2021-05-20 00:07:39 +03:00
def test_check_for_updates_no_state ( monkeypatch , temp_db_conn ) :
2021-01-30 17:50:34 +03:00
status . set_status ( temp_db_conn , dt . datetime . now ( dt . timezone . utc ) , seq = 345 )
2021-01-28 16:34:17 +03:00
2024-06-09 15:52:20 +03:00
monkeypatch . setattr ( nominatim_db . tools . replication . ReplicationServer ,
2021-01-28 16:34:17 +03:00
" get_state_info " , lambda self : None )
2024-06-09 15:52:20 +03:00
assert nominatim_db . tools . replication . check_for_updates ( temp_db_conn , ' https://test.io ' ) == 253
2021-01-28 16:34:17 +03:00
2021-01-30 17:50:34 +03:00
@pytest.mark.parametrize ( " server_sequence,result " , [ ( 344 , 2 ) , ( 345 , 2 ) , ( 346 , 0 ) ] )
2021-05-20 00:07:39 +03:00
def test_check_for_updates_no_new_data ( monkeypatch , temp_db_conn ,
2021-01-28 16:34:17 +03:00
server_sequence , result ) :
2021-01-30 17:50:34 +03:00
date = dt . datetime . now ( dt . timezone . utc )
2021-01-28 16:34:17 +03:00
status . set_status ( temp_db_conn , date , seq = 345 )
2024-06-09 15:52:20 +03:00
monkeypatch . setattr ( nominatim_db . tools . replication . ReplicationServer ,
2021-01-28 16:34:17 +03:00
" get_state_info " ,
lambda self : OsmosisState ( server_sequence , date ) )
2024-06-09 15:52:20 +03:00
assert nominatim_db . tools . replication . check_for_updates ( temp_db_conn , ' https://test.io ' ) == result
2021-01-30 17:50:34 +03:00
### updating
@pytest.fixture
def update_options ( tmpdir ) :
return dict ( base_url = ' https://test.io ' ,
2021-05-20 00:07:39 +03:00
indexed_only = False ,
update_interval = 3600 ,
import_file = tmpdir / ' foo.osm ' ,
max_diff_size = 1 )
2021-01-30 17:50:34 +03:00
2023-06-19 13:02:51 +03:00
def test_update_empty_status_table ( dsn ) :
2021-01-30 18:20:10 +03:00
with pytest . raises ( UsageError ) :
2024-06-09 15:52:20 +03:00
nominatim_db . tools . replication . update ( dsn , { } )
2021-01-30 17:50:34 +03:00
2023-06-19 13:02:51 +03:00
def test_update_already_indexed ( temp_db_conn , dsn ) :
2021-01-30 17:50:34 +03:00
status . set_status ( temp_db_conn , dt . datetime . now ( dt . timezone . utc ) , seq = 34 , indexed = False )
2024-06-09 15:52:20 +03:00
assert nominatim_db . tools . replication . update ( dsn , dict ( indexed_only = True ) ) \
== nominatim_db . tools . replication . UpdateState . MORE_PENDING
2021-01-30 17:50:34 +03:00
2023-06-19 13:02:51 +03:00
def test_update_no_data_no_sleep ( monkeypatch , temp_db_conn , dsn , update_options ) :
2021-01-30 17:50:34 +03:00
date = dt . datetime . now ( dt . timezone . utc ) - dt . timedelta ( days = 1 )
status . set_status ( temp_db_conn , date , seq = 34 )
2024-06-09 15:52:20 +03:00
monkeypatch . setattr ( nominatim_db . tools . replication . ReplicationServer ,
2021-01-30 17:50:34 +03:00
" apply_diffs " ,
lambda * args , * * kwargs : None )
sleeptime = [ ]
2021-05-20 00:07:39 +03:00
monkeypatch . setattr ( time , ' sleep ' , sleeptime . append )
2021-01-30 17:50:34 +03:00
2024-06-09 15:52:20 +03:00
assert nominatim_db . tools . replication . update ( dsn , update_options ) \
== nominatim_db . tools . replication . UpdateState . NO_CHANGES
2021-01-30 17:50:34 +03:00
assert not sleeptime
2023-06-19 13:02:51 +03:00
def test_update_no_data_sleep ( monkeypatch , temp_db_conn , dsn , update_options ) :
2021-01-30 17:50:34 +03:00
date = dt . datetime . now ( dt . timezone . utc ) - dt . timedelta ( minutes = 30 )
status . set_status ( temp_db_conn , date , seq = 34 )
2024-06-09 15:52:20 +03:00
monkeypatch . setattr ( nominatim_db . tools . replication . ReplicationServer ,
2021-01-30 17:50:34 +03:00
" apply_diffs " ,
lambda * args , * * kwargs : None )
sleeptime = [ ]
2021-05-20 00:07:39 +03:00
monkeypatch . setattr ( time , ' sleep ' , sleeptime . append )
2021-01-30 17:50:34 +03:00
2024-06-09 15:52:20 +03:00
assert nominatim_db . tools . replication . update ( dsn , update_options ) \
== nominatim_db . tools . replication . UpdateState . NO_CHANGES
2021-01-30 17:50:34 +03:00
assert len ( sleeptime ) == 1
assert sleeptime [ 0 ] < 3600
assert sleeptime [ 0 ] > 0