def test_check_receivexlog_installed(self, command_mock): """ Test for the check method of the StreamingWalArchiver class """ backup_manager = build_backup_manager() backup_manager.server.postgres.server_txt_version = "9.2" command_mock.side_effect = CommandFailedException archiver = StreamingWalArchiver(backup_manager) result = archiver.get_remote_status() assert result == { "pg_receivexlog_installed": False, "pg_receivexlog_path": None, "pg_receivexlog_compatible": None, 'pg_receivexlog_synchronous': None, "pg_receivexlog_version": None, "pg_receivexlog_supports_slots": None, } backup_manager.server.postgres.server_txt_version = "9.2" command_mock.side_effect = None command_mock.return_value.cmd = '/some/path/to/pg_receivexlog' command_mock.return_value.side_effect = CommandFailedException archiver.reset_remote_status() result = archiver.get_remote_status() assert result == { "pg_receivexlog_installed": True, "pg_receivexlog_path": "/some/path/to/pg_receivexlog", "pg_receivexlog_compatible": None, 'pg_receivexlog_synchronous': None, "pg_receivexlog_version": None, "pg_receivexlog_supports_slots": None, }
def test_streamingwalarchiver_check_receivexlog_installed( self, command_mock, which_mock): """ Test for the check method of the StreamingWalArchiver class """ backup_manager = build_backup_manager() backup_manager.server.postgres.server_txt_version = "9.2" which_mock.return_value = None archiver = StreamingWalArchiver(backup_manager) result = archiver.get_remote_status() which_mock.assert_called_with('pg_receivexlog', ANY) assert result == { "pg_receivexlog_installed": False, "pg_receivexlog_path": None, "pg_receivexlog_compatible": None, "pg_receivexlog_version": None, } backup_manager.server.postgres.server_txt_version = "9.2" which_mock.return_value = '/some/path/to/pg_receivexlog' command_mock.return_value.side_effect = CommandFailedException result = archiver.get_remote_status() assert result == { "pg_receivexlog_installed": True, "pg_receivexlog_path": "/some/path/to/pg_receivexlog", "pg_receivexlog_compatible": None, "pg_receivexlog_version": None, }
def test_get_next_batch(self, from_file_mock, isfile_mock, glob_mock): """ Test the FileWalArchiver.get_next_batch method """ # WAL batch, with 000000010000000000000001 that is currently being # written glob_mock.return_value = ['000000010000000000000001'] isfile_mock.return_value = True # This is an hack, instead of a WalFileInfo we use a simple string to # ease all the comparisons. The resulting string is the name enclosed # in colons. e.g. ":000000010000000000000001:" from_file_mock.side_effect = lambda wal_name, compression: ( ':%s:' % wal_name) backup_manager = build_backup_manager( name='TestServer' ) archiver = StreamingWalArchiver(backup_manager) backup_manager.server.archivers = [archiver] batch = archiver.get_next_batch() assert ['000000010000000000000001'] == batch.skip # WAL batch, with 000000010000000000000002 that is currently being # written and 000000010000000000000001 can be archived glob_mock.return_value = [ '000000010000000000000001', '000000010000000000000002', ] batch = archiver.get_next_batch() assert [':000000010000000000000001:'] == batch assert ['000000010000000000000002'] == batch.skip # WAL batch, with two partial files. glob_mock.return_value = [ '000000010000000000000001.partial', '000000010000000000000002.partial', ] batch = archiver.get_next_batch() assert ['000000010000000000000001.partial'] == batch.errors assert ['000000010000000000000002.partial'] == batch.skip # WAL batch with errors wrong_file_name = 'test_wrong_wal_file.2' glob_mock.return_value = ['test_wrong_wal_file.2'] batch = archiver.get_next_batch() assert [wrong_file_name] == batch.errors
def test_when_streaming_connection_rejected(self, command_mock, which_mock): """ Test the StreamingWalArchiver behaviour when the streaming connection is rejected by the PostgreSQL server and pg_receivexlog is installed. """ # When the streaming connection is not available, the # server_txt_version property will have a None value. backup_manager = build_backup_manager() backup_manager.server.streaming.server_txt_version = None archiver = StreamingWalArchiver(backup_manager) which_mock.return_value = "/some/path/to/pg_receivexlog" command_mock.return_value.out = "pg_receivexlog (PostgreSQL) 9.2" result = archiver.get_remote_status() assert result["pg_receivexlog_compatible"] is None
def test_when_streaming_connection_rejected(self, command_mock, which_mock): """ Test the StreamingWalArchiver behaviour when the streaming connection is rejected by the PostgreSQL server and pg_receivexlog is installed. """ # When the streaming connection is not available, the # server_txt_version property will have a None value. backup_manager = build_backup_manager() backup_manager.server.streaming.server_major_version = None archiver = StreamingWalArchiver(backup_manager) which_mock.return_value = "/some/path/to/pg_receivexlog" command_mock.return_value.out = "pg_receivexlog (PostgreSQL) 9.2" result = archiver.get_remote_status() assert result["pg_receivexlog_compatible"] is None
def test_get_next_batch(self, from_file_mock, isfile_mock, glob_mock, caplog): """ Test the FileWalArchiver.get_next_batch method """ # WAL batch, with 000000010000000000000001 that is currently being # written glob_mock.return_value = ['000000010000000000000001'] isfile_mock.return_value = True # This is an hack, instead of a WalFileInfo we use a simple string to # ease all the comparisons. The resulting string is the name enclosed # in colons. e.g. ":000000010000000000000001:" from_file_mock.side_effect = lambda wal_name, compression: (':%s:' % wal_name) backup_manager = build_backup_manager(name='TestServer') archiver = StreamingWalArchiver(backup_manager) backup_manager.server.archivers = [archiver] batch = archiver.get_next_batch() assert ['000000010000000000000001'] == batch.skip # WAL batch, with 000000010000000000000002 that is currently being # written and 000000010000000000000001 can be archived glob_mock.return_value = [ '000000010000000000000001', '000000010000000000000002', ] batch = archiver.get_next_batch() assert [':000000010000000000000001:'] == batch assert ['000000010000000000000002'] == batch.skip # WAL batch, with two partial files. glob_mock.return_value = [ '000000010000000000000001.partial', '000000010000000000000002.partial', ] batch = archiver.get_next_batch() assert [':000000010000000000000001.partial:'] == batch assert ['000000010000000000000002.partial'] == batch.skip assert ('Archiving partial files for server %s: ' '000000010000000000000001.partial' % archiver.config.name) in caplog.text # WAL batch, with history files. glob_mock.return_value = [ '00000001.history', '000000010000000000000002.partial', ] batch = archiver.get_next_batch() assert [':00000001.history:'] == batch assert ['000000010000000000000002.partial'] == batch.skip # WAL batch with errors wrong_file_name = 'test_wrong_wal_file.2' glob_mock.return_value = ['test_wrong_wal_file.2'] batch = archiver.get_next_batch() assert [wrong_file_name] == batch.errors
def test_check(self, remote_mock, capsys): """ Test management of check_postgres view output :param remote_mock: mock get_remote_status function :param capsys: retrieve output from consolle """ # Create a backup_manager backup_manager = build_backup_manager() # Set up mock responses streaming = backup_manager.server.streaming streaming.server_txt_version = "9.5" # Instantiate a StreamingWalArchiver obj archiver = StreamingWalArchiver(backup_manager) # Prepare the output check strategy strategy = CheckOutputStrategy() # Case: correct configuration remote_mock.return_value = { "pg_receivexlog_installed": True, "pg_receivexlog_compatible": True, "pg_receivexlog_path": "fake/path", } # Expect out: all parameters: OK archiver.check(strategy) (out, err) = capsys.readouterr() assert out == "\tpg_receivexlog: OK\n" "\tpg_receivexlog compatible: OK\n" # Case: pg_receivexlog is not compatible remote_mock.return_value = { "pg_receivexlog_installed": True, "pg_receivexlog_compatible": False, "pg_receivexlog_path": "fake/path", "pg_receivexlog_version": "9.2", } # Expect out: some parameters: FAILED strategy = CheckOutputStrategy() archiver.check(strategy) (out, err) = capsys.readouterr() assert ( out == "\tpg_receivexlog: OK\n" "\tpg_receivexlog compatible: FAILED " "(PostgreSQL version: 9.5, pg_receivexlog version: 9.2)\n" ) # Case: pg_receivexlog returned error remote_mock.return_value = { "pg_receivexlog_installed": True, "pg_receivexlog_compatible": None, "pg_receivexlog_path": "fake/path", "pg_receivexlog_version": None, } # Expect out: all parameters: OK archiver.check(strategy) (out, err) = capsys.readouterr() assert ( out == "\tpg_receivexlog: OK\n" "\tpg_receivexlog compatible: FAILED " "(PostgreSQL version: 9.5, pg_receivexlog version: None)\n" )
def test_check_receivexlog_installed(self, find_command): """ Test for the check method of the StreamingWalArchiver class """ backup_manager = build_backup_manager() find_command.side_effect = CommandFailedException archiver = StreamingWalArchiver(backup_manager) result = archiver.get_remote_status() assert result == { "pg_receivexlog_installed": False, "pg_receivexlog_path": None, "pg_receivexlog_compatible": None, "pg_receivexlog_synchronous": None, "pg_receivexlog_version": None, "pg_receivexlog_supports_slots": None, } backup_manager.server.streaming.server_major_version = "9.2" find_command.side_effect = None find_command.return_value.cmd = "/some/path/to/pg_receivexlog" find_command.return_value.out = "" archiver.reset_remote_status() result = archiver.get_remote_status() assert result == { "pg_receivexlog_installed": True, "pg_receivexlog_path": "/some/path/to/pg_receivexlog", "pg_receivexlog_compatible": None, "pg_receivexlog_synchronous": None, "pg_receivexlog_version": None, "pg_receivexlog_supports_slots": None, }
def test_is_synchronous(self): backup_manager = build_backup_manager(name="TestServer") archiver = StreamingWalArchiver(backup_manager) # 'barman_receive_wal' is not in the list of synchronous standby # names, so we expect is_synchronous to be false backup_manager.server.postgres.get_remote_status.return_value = { "synchronous_standby_names": ["a", "b", "c"] } assert not archiver._is_synchronous() # 'barman_receive_wal' is in the list of synchronous standby # names, so we expect is_synchronous to be true backup_manager.server.postgres.get_remote_status.return_value = { "synchronous_standby_names": ["a", "barman_receive_wal"] } assert archiver._is_synchronous() # '*' is in the list of synchronous standby names, so we expect # is_synchronous to be true even if 'barman_receive_wal' is not # explicitly referenced backup_manager.server.postgres.get_remote_status.return_value = { "synchronous_standby_names": ["a", "b", "*"] } assert archiver._is_synchronous() # There is only a '*' in the list of synchronous standby names, # so we expect every name to match backup_manager.server.postgres.get_remote_status.return_value = { "synchronous_standby_names": ["*"] } assert archiver._is_synchronous()
def test_streamingwalarchiver_check_receivexlog_is_compatible( self, command_mock, which_mock): """ Test for the compatibility checks between versions of pg_receivexlog and PostgreSQL """ # pg_receivexlog 9.2 is compatible only with PostgreSQL 9.2 backup_manager = build_backup_manager() backup_manager.server.streaming.server_txt_version = "9.2.0" archiver = StreamingWalArchiver(backup_manager) which_mock.return_value = '/some/path/to/pg_receivexlog' command_mock.return_value.out = "pg_receivexlog (PostgreSQL) 9.2" result = archiver.get_remote_status() assert result["pg_receivexlog_compatible"] is True command_mock.return_value.out = "pg_receivexlog (PostgreSQL) 9.5" result = archiver.get_remote_status() assert result["pg_receivexlog_compatible"] is False # Every pg_receivexlog is compatible with older PostgreSQL backup_manager.server.streaming.server_txt_version = "9.3.0" command_mock.return_value.out = "pg_receivexlog (PostgreSQL) 9.5" result = archiver.get_remote_status() assert result["pg_receivexlog_compatible"] is True backup_manager.server.streaming.server_txt_version = "9.5.0" command_mock.return_value.out = "pg_receivexlog (PostgreSQL) 9.3" result = archiver.get_remote_status() assert result["pg_receivexlog_compatible"] is False # Check for minor versions backup_manager.server.streaming.server_txt_version = "9.4.5" command_mock.return_value.out = "pg_receivexlog (PostgreSQL) 9.4.4" result = archiver.get_remote_status() assert result["pg_receivexlog_compatible"] is True
def test_check(self, remote_mock, capsys): """ Test management of check_postgres view output :param remote_mock: mock get_remote_status function :param capsys: retrieve output from consolle """ # Create a backup_manager backup_manager = build_backup_manager() # Set up mock responses streaming = backup_manager.server.streaming streaming.server_txt_version = '9.5' # Instantiate a StreamingWalArchiver obj archiver = StreamingWalArchiver(backup_manager) # Prepare the output check strategy strategy = CheckOutputStrategy() # Case: correct configuration remote_mock.return_value = { 'pg_receivexlog_installed': True, 'pg_receivexlog_compatible': True, 'pg_receivexlog_path': 'fake/path', } # Expect out: all parameters: OK backup_manager.server.process_manager.list.return_value = [] archiver.check(strategy) (out, err) = capsys.readouterr() assert out == \ "\tpg_receivexlog: OK\n" \ "\tpg_receivexlog compatible: OK\n" \ "\treceive-wal running: FAILED " \ "(See the Barman log file for more details)\n" # Case: pg_receivexlog is not compatible remote_mock.return_value = { 'pg_receivexlog_installed': True, 'pg_receivexlog_compatible': False, 'pg_receivexlog_path': 'fake/path', 'pg_receivexlog_version': '9.2', } # Expect out: some parameters: FAILED strategy = CheckOutputStrategy() archiver.check(strategy) (out, err) = capsys.readouterr() assert out == \ "\tpg_receivexlog: OK\n" \ "\tpg_receivexlog compatible: FAILED " \ "(PostgreSQL version: 9.5, pg_receivexlog version: 9.2)\n" \ "\treceive-wal running: FAILED " \ "(See the Barman log file for more details)\n" # Case: pg_receivexlog returned error remote_mock.return_value = { 'pg_receivexlog_installed': True, 'pg_receivexlog_compatible': None, 'pg_receivexlog_path': 'fake/path', 'pg_receivexlog_version': None, } # Expect out: all parameters: OK archiver.check(strategy) (out, err) = capsys.readouterr() assert out == \ "\tpg_receivexlog: OK\n" \ "\tpg_receivexlog compatible: FAILED " \ "(PostgreSQL version: 9.5, pg_receivexlog version: None)\n" \ "\treceive-wal running: FAILED " \ "(See the Barman log file for more details)\n" # Case: receive-wal running backup_manager.server.process_manager.list.return_value = [ ProcessInfo(pid=1, server_name=backup_manager.config.name, task="receive-wal") ] archiver.check(strategy) (out, err) = capsys.readouterr() assert out == \ "\tpg_receivexlog: OK\n" \ "\tpg_receivexlog compatible: FAILED " \ "(PostgreSQL version: 9.5, pg_receivexlog version: None)\n" \ "\treceive-wal running: OK\n"
def test_receive_wal(self, receivexlog_mock, remote_mock, tmpdir): backup_manager = build_backup_manager( main_conf={"backup_directory": tmpdir}, ) streaming_mock = backup_manager.server.streaming streaming_mock.server_txt_version = "9.4.0" streaming_mock.get_connection_string.return_value = ( "host=pg01.nowhere user=postgres port=5432 " "application_name=barman_receive_wal" ) streaming_mock.get_remote_status.return_value = { "streaming_supported": True, "timeline": 1, } postgres_mock = backup_manager.server.postgres replication_slot_status = MagicMock(restart_lsn="F/A12D687", active=False) postgres_mock.get_remote_status.return_value = { "current_xlog": "000000010000000F0000000A", "current_lsn": "F/A12D687", "replication_slot": replication_slot_status, "xlog_segment_size": 16777216, } backup_manager.server.streaming.conn_parameters = { "host": "pg01.nowhere", "user": "******", "port": "5432", } streaming_dir = tmpdir.join("streaming") streaming_dir.ensure(dir=True) # Test: normal run archiver = StreamingWalArchiver(backup_manager) archiver.server.streaming.server_version = 90400 remote_mock.return_value = { "pg_receivexlog_installed": True, "pg_receivexlog_compatible": True, "pg_receivexlog_synchronous": None, "pg_receivexlog_path": "fake/path", "pg_receivexlog_supports_slots": True, "pg_receivexlog_version": "9.4", } # Test: execute a reset request partial = streaming_dir.join("000000010000000100000001.partial") partial.ensure() archiver.receive_wal(reset=True) assert not partial.check() assert streaming_dir.join("000000010000000F0000000A.partial").check() archiver.receive_wal(reset=False) receivexlog_mock.assert_called_once_with( app_name="barman_receive_wal", synchronous=None, connection=ANY, destination=streaming_dir.strpath, err_handler=ANY, out_handler=ANY, path=ANY, slot_name=None, command="fake/path", version="9.4", ) receivexlog_mock.return_value.execute.assert_called_once_with() # Test: pg_receivexlog from 9.2 receivexlog_mock.reset_mock() remote_mock.return_value = { "pg_receivexlog_installed": True, "pg_receivexlog_compatible": True, "pg_receivexlog_synchronous": False, "pg_receivexlog_path": "fake/path", "pg_receivexlog_supports_slots": False, "pg_receivexlog_version": "9.2", } archiver.receive_wal(reset=False) receivexlog_mock.assert_called_once_with( app_name="barman_receive_wal", synchronous=False, connection=ANY, destination=streaming_dir.strpath, err_handler=ANY, out_handler=ANY, path=ANY, command="fake/path", slot_name=None, version="9.2", ) receivexlog_mock.return_value.execute.assert_called_once_with() # Test: incompatible pg_receivexlog with pytest.raises(ArchiverFailure): remote_mock.return_value = { "pg_receivexlog_installed": True, "pg_receivexlog_compatible": False, "pg_receivexlog_supports_slots": False, "pg_receivexlog_synchronous": False, "pg_receivexlog_path": "fake/path", } archiver.receive_wal() # Test: missing pg_receivexlog with pytest.raises(ArchiverFailure): remote_mock.return_value = { "pg_receivexlog_installed": False, "pg_receivexlog_compatible": True, "pg_receivexlog_supports_slots": False, "pg_receivexlog_synchronous": False, "pg_receivexlog_path": "fake/path", } archiver.receive_wal() # Test: impossible to connect with streaming protocol with pytest.raises(ArchiverFailure): backup_manager.server.streaming.get_remote_status.return_value = { "streaming_supported": None } remote_mock.return_value = { "pg_receivexlog_installed": True, "pg_receivexlog_supports_slots": False, "pg_receivexlog_compatible": True, "pg_receivexlog_synchronous": False, "pg_receivexlog_path": "fake/path", } archiver.receive_wal() # Test: PostgreSQL too old with pytest.raises(ArchiverFailure): backup_manager.server.streaming.get_remote_status.return_value = { "streaming_supported": False } remote_mock.return_value = { "pg_receivexlog_installed": True, "pg_receivexlog_compatible": True, "pg_receivexlog_synchronous": False, "pg_receivexlog_path": "fake/path", } archiver.receive_wal() # Test: general failure executing pg_receivexlog with pytest.raises(ArchiverFailure): remote_mock.return_value = { "pg_receivexlog_installed": True, "pg_receivexlog_compatible": True, "pg_receivexlog_synchronous": False, "pg_receivexlog_path": "fake/path", } receivexlog_mock.return_value.execute.side_effect = CommandFailedException archiver.receive_wal()
def test_check_receivexlog_is_compatible(self, command_mock, which_mock): """ Test for the compatibility checks between versions of pg_receivexlog and PostgreSQL """ # pg_receivexlog 9.2 is compatible only with PostgreSQL 9.2 backup_manager = build_backup_manager() backup_manager.server.streaming.server_major_version = "9.2" archiver = StreamingWalArchiver(backup_manager) which_mock.return_value = "/some/path/to/pg_receivexlog" command_mock.return_value.out = "pg_receivexlog (PostgreSQL) 9.2.1" result = archiver.get_remote_status() assert result["pg_receivexlog_compatible"] is True command_mock.return_value.out = "pg_receivexlog (PostgreSQL) 9.5.3" archiver.reset_remote_status() result = archiver.get_remote_status() assert result["pg_receivexlog_compatible"] is False # Every pg_receivexlog is compatible with older PostgreSQL backup_manager.server.streaming.server_major_version = "9.3" command_mock.return_value.out = "pg_receivexlog (PostgreSQL) 9.5.3" archiver.reset_remote_status() result = archiver.get_remote_status() assert result["pg_receivexlog_compatible"] is True backup_manager.server.streaming.server_major_version = "9.5" command_mock.return_value.out = "pg_receivexlog (PostgreSQL) 9.3.0" archiver.reset_remote_status() result = archiver.get_remote_status() assert result["pg_receivexlog_compatible"] is False # Check for minor versions backup_manager.server.streaming.server_major_version = "9.4" command_mock.return_value.out = "pg_receivexlog (PostgreSQL) 9.4.4" archiver.reset_remote_status() result = archiver.get_remote_status() assert result["pg_receivexlog_compatible"] is True assert result["pg_receivexlog_synchronous"] is False
def test_init(self): """ Basic init test for the StreamingWalArchiver class """ backup_manager = build_backup_manager() StreamingWalArchiver(backup_manager)
def test_receive_wal(self, receivexlog_mock, remote_mock): backup_manager = build_backup_manager() backup_manager.server.streaming.server_txt_version = "9.4.0" backup_manager.server.streaming.get_remote_status.return_value = {"streaming_supported": True} # Test: normal run archiver = StreamingWalArchiver(backup_manager) remote_mock.return_value = { "pg_receivexlog_installed": True, "pg_receivexlog_compatible": True, "pg_receivexlog_path": "fake/path", } archiver.receive_wal() receivexlog_mock.assert_called_once_with( "fake/path", "host=pg01.nowhere user=postgres port=5432", "/some/barman/home/main/streaming" ) receivexlog_mock.return_value.execute.assert_called_once_with() # Test: incompatible pg_receivexlog with pytest.raises(ArchiverFailure): remote_mock.return_value = { "pg_receivexlog_installed": True, "pg_receivexlog_compatible": False, "pg_receivexlog_path": "fake/path", } archiver.receive_wal() # Test: missing pg_receivexlog with pytest.raises(ArchiverFailure): remote_mock.return_value = { "pg_receivexlog_installed": False, "pg_receivexlog_compatible": True, "pg_receivexlog_path": "fake/path", } archiver.receive_wal() # Test: impossible to connect with streaming protocol with pytest.raises(ArchiverFailure): backup_manager.server.streaming.get_remote_status.return_value = {"streaming_supported": None} remote_mock.return_value = { "pg_receivexlog_installed": True, "pg_receivexlog_compatible": True, "pg_receivexlog_path": "fake/path", } archiver.receive_wal() # Test: PostgreSQL too old with pytest.raises(ArchiverFailure): backup_manager.server.streaming.get_remote_status.return_value = {"streaming_supported": False} remote_mock.return_value = { "pg_receivexlog_installed": True, "pg_receivexlog_compatible": True, "pg_receivexlog_path": "fake/path", } archiver.receive_wal() # Test: general failure executing pg_receivexlog with pytest.raises(ArchiverFailure): remote_mock.return_value = { "pg_receivexlog_installed": True, "pg_receivexlog_compatible": True, "pg_receivexlog_path": "fake/path", } receivexlog_mock.return_value.execute.side_effect = CommandFailedException archiver.receive_wal()
def test_check(self, remote_mock, capsys): """ Test management of check_postgres view output :param remote_mock: mock get_remote_status function :param capsys: retrieve output from consolle """ # Create a backup_manager backup_manager = build_backup_manager() # Set up mock responses streaming = backup_manager.server.streaming streaming.server_txt_version = "9.5" # Instantiate a StreamingWalArchiver obj archiver = StreamingWalArchiver(backup_manager) # Prepare the output check strategy strategy = CheckOutputStrategy() # Case: correct configuration remote_mock.return_value = { "pg_receivexlog_installed": True, "pg_receivexlog_compatible": True, "pg_receivexlog_path": "fake/path", "incoming_wals_count": 0, } # Expect out: all parameters: OK backup_manager.server.process_manager.list.return_value = [] archiver.check(strategy) (out, err) = capsys.readouterr() assert ( out == "\tpg_receivexlog: OK\n" "\tpg_receivexlog compatible: OK\n" "\treceive-wal running: FAILED " "(See the Barman log file for more details)\n" ) # Case: pg_receivexlog is not compatible remote_mock.return_value = { "pg_receivexlog_installed": True, "pg_receivexlog_compatible": False, "pg_receivexlog_path": "fake/path", "pg_receivexlog_version": "9.2", "incoming_wals_count": 0, } # Expect out: some parameters: FAILED strategy = CheckOutputStrategy() archiver.check(strategy) (out, err) = capsys.readouterr() assert ( out == "\tpg_receivexlog: OK\n" "\tpg_receivexlog compatible: FAILED " "(PostgreSQL version: 9.5, pg_receivexlog version: 9.2)\n" "\treceive-wal running: FAILED " "(See the Barman log file for more details)\n" ) # Case: pg_receivexlog returned error remote_mock.return_value = { "pg_receivexlog_installed": True, "pg_receivexlog_compatible": None, "pg_receivexlog_path": "fake/path", "pg_receivexlog_version": None, "incoming_wals_count": 0, } # Expect out: all parameters: OK archiver.check(strategy) (out, err) = capsys.readouterr() assert ( out == "\tpg_receivexlog: OK\n" "\tpg_receivexlog compatible: FAILED " "(PostgreSQL version: 9.5, pg_receivexlog version: None)\n" "\treceive-wal running: FAILED " "(See the Barman log file for more details)\n" ) # Case: receive-wal running backup_manager.server.process_manager.list.return_value = [ ProcessInfo( pid=1, server_name=backup_manager.config.name, task="receive-wal" ) ] archiver.check(strategy) (out, err) = capsys.readouterr() assert ( out == "\tpg_receivexlog: OK\n" "\tpg_receivexlog compatible: FAILED " "(PostgreSQL version: 9.5, pg_receivexlog version: None)\n" "\treceive-wal running: OK\n" ) # Case: streaming connection not configured backup_manager.server.streaming = None archiver.check(strategy) (out, err) = capsys.readouterr() assert ( out == "\tpg_receivexlog: OK\n" "\tpg_receivexlog compatible: FAILED " "(PostgreSQL version: Unknown, pg_receivexlog version: None)\n" "\treceive-wal running: OK\n" ) # Case: too many wal files in the incoming queue archiver.config.max_incoming_wals_queue = 10 remote_mock.return_value = { "pg_receivexlog_installed": True, "pg_receivexlog_compatible": None, "pg_receivexlog_path": "fake/path", "pg_receivexlog_version": None, "incoming_wals_count": 20, } # Expect out: the wals incoming queue is too big archiver.check(strategy) (out, err) = capsys.readouterr() assert ( out == "\tpg_receivexlog: OK\n" "\tpg_receivexlog compatible: FAILED " "(PostgreSQL version: Unknown, pg_receivexlog version: None)\n" "\treceive-wal running: OK\n" )
def test_receive_wal(self, receivexlog_mock, remote_mock, tmpdir): backup_manager = build_backup_manager( main_conf={ 'backup_directory': tmpdir }, ) backup_manager.server.streaming.server_txt_version = "9.4.0" backup_manager.server.streaming.get_remote_status.return_value = { "streaming_supported": True } backup_manager.server.streaming.conn_parameters = { 'host': 'pg01.nowhere', 'user': '******', 'port': '5432', } streaming_dir = tmpdir.join('streaming') streaming_dir.ensure(dir=True) # Test: normal run archiver = StreamingWalArchiver(backup_manager) remote_mock.return_value = { 'pg_receivexlog_installed': True, 'pg_receivexlog_compatible': True, 'pg_receivexlog_path': 'fake/path', 'pg_receivexlog_version': '9.4', } # Test: execute a reset request partial = streaming_dir.join('test.partial') partial.ensure() archiver.receive_wal(reset=True) assert not partial.check() archiver.receive_wal(reset=False) receivexlog_mock.assert_called_once_with( 'fake/path', conn_string='host=pg01.nowhere user=postgres port=5432 ' 'application_name=barman_receive_wal', dest=streaming_dir.strpath, out_handler=ANY, err_handler=ANY, ) receivexlog_mock.return_value.execute.assert_called_once_with() # Test: pg_receivexlog from 9.2 receivexlog_mock.reset_mock() remote_mock.return_value = { 'pg_receivexlog_installed': True, 'pg_receivexlog_compatible': True, 'pg_receivexlog_path': 'fake/path', 'pg_receivexlog_version': '9.2', } archiver.receive_wal(reset=False) receivexlog_mock.assert_called_once_with( 'fake/path', host='pg01.nowhere', user='******', port='5432', dest=streaming_dir.strpath, out_handler=ANY, err_handler=ANY, ) receivexlog_mock.return_value.execute.assert_called_once_with() # Test: incompatible pg_receivexlog with pytest.raises(ArchiverFailure): remote_mock.return_value = { 'pg_receivexlog_installed': True, 'pg_receivexlog_compatible': False, 'pg_receivexlog_path': 'fake/path' } archiver.receive_wal() # Test: missing pg_receivexlog with pytest.raises(ArchiverFailure): remote_mock.return_value = { 'pg_receivexlog_installed': False, 'pg_receivexlog_compatible': True, 'pg_receivexlog_path': 'fake/path' } archiver.receive_wal() # Test: impossible to connect with streaming protocol with pytest.raises(ArchiverFailure): backup_manager.server.streaming.get_remote_status.return_value = { 'streaming_supported': None } remote_mock.return_value = { 'pg_receivexlog_installed': True, 'pg_receivexlog_compatible': True, 'pg_receivexlog_path': 'fake/path' } archiver.receive_wal() # Test: PostgreSQL too old with pytest.raises(ArchiverFailure): backup_manager.server.streaming.get_remote_status.return_value = { 'streaming_supported': False } remote_mock.return_value = { 'pg_receivexlog_installed': True, 'pg_receivexlog_compatible': True, 'pg_receivexlog_path': 'fake/path' } archiver.receive_wal() # Test: general failure executing pg_receivexlog with pytest.raises(ArchiverFailure): remote_mock.return_value = { 'pg_receivexlog_installed': True, 'pg_receivexlog_compatible': True, 'pg_receivexlog_path': 'fake/path' } receivexlog_mock.return_value.execute.side_effect = \ CommandFailedException archiver.receive_wal()
def test_receive_wal(self, receivexlog_mock, remote_mock, tmpdir): backup_manager = build_backup_manager( main_conf={ 'backup_directory': tmpdir }, ) streaming_mock = backup_manager.server.streaming streaming_mock.server_txt_version = "9.4.0" streaming_mock.get_connection_string.return_value = ( 'host=pg01.nowhere user=postgres port=5432 ' 'application_name=barman_receive_wal') streaming_mock.get_remote_status.return_value = { "streaming_supported": True } backup_manager.server.streaming.conn_parameters = { 'host': 'pg01.nowhere', 'user': '******', 'port': '5432', } streaming_dir = tmpdir.join('streaming') streaming_dir.ensure(dir=True) # Test: normal run archiver = StreamingWalArchiver(backup_manager) archiver.server.streaming.server_version = 90400 remote_mock.return_value = { 'pg_receivexlog_installed': True, 'pg_receivexlog_compatible': True, 'pg_receivexlog_synchronous': None, 'pg_receivexlog_path': 'fake/path', 'pg_receivexlog_supports_slots': True, 'pg_receivexlog_version': '9.4', } # Test: execute a reset request partial = streaming_dir.join('test.partial') partial.ensure() archiver.receive_wal(reset=True) assert not partial.check() archiver.receive_wal(reset=False) receivexlog_mock.assert_called_once_with( app_name='barman_receive_wal', synchronous=None, connection=ANY, destination=streaming_dir.strpath, err_handler=ANY, out_handler=ANY, path=ANY, slot_name=None, command='fake/path', version='9.4') receivexlog_mock.return_value.execute.assert_called_once_with() # Test: pg_receivexlog from 9.2 receivexlog_mock.reset_mock() remote_mock.return_value = { 'pg_receivexlog_installed': True, 'pg_receivexlog_compatible': True, 'pg_receivexlog_synchronous': False, 'pg_receivexlog_path': 'fake/path', 'pg_receivexlog_supports_slots': False, 'pg_receivexlog_version': '9.2', } archiver.receive_wal(reset=False) receivexlog_mock.assert_called_once_with( app_name='barman_receive_wal', synchronous=False, connection=ANY, destination=streaming_dir.strpath, err_handler=ANY, out_handler=ANY, path=ANY, command='fake/path', slot_name=None, version='9.2' ) receivexlog_mock.return_value.execute.assert_called_once_with() # Test: incompatible pg_receivexlog with pytest.raises(ArchiverFailure): remote_mock.return_value = { 'pg_receivexlog_installed': True, 'pg_receivexlog_compatible': False, 'pg_receivexlog_supports_slots': False, 'pg_receivexlog_synchronous': False, 'pg_receivexlog_path': 'fake/path' } archiver.receive_wal() # Test: missing pg_receivexlog with pytest.raises(ArchiverFailure): remote_mock.return_value = { 'pg_receivexlog_installed': False, 'pg_receivexlog_compatible': True, 'pg_receivexlog_supports_slots': False, 'pg_receivexlog_synchronous': False, 'pg_receivexlog_path': 'fake/path' } archiver.receive_wal() # Test: impossible to connect with streaming protocol with pytest.raises(ArchiverFailure): backup_manager.server.streaming.get_remote_status.return_value = { 'streaming_supported': None } remote_mock.return_value = { 'pg_receivexlog_installed': True, 'pg_receivexlog_supports_slots': False, 'pg_receivexlog_compatible': True, 'pg_receivexlog_synchronous': False, 'pg_receivexlog_path': 'fake/path' } archiver.receive_wal() # Test: PostgreSQL too old with pytest.raises(ArchiverFailure): backup_manager.server.streaming.get_remote_status.return_value = { 'streaming_supported': False } remote_mock.return_value = { 'pg_receivexlog_installed': True, 'pg_receivexlog_compatible': True, 'pg_receivexlog_synchronous': False, 'pg_receivexlog_path': 'fake/path' } archiver.receive_wal() # Test: general failure executing pg_receivexlog with pytest.raises(ArchiverFailure): remote_mock.return_value = { 'pg_receivexlog_installed': True, 'pg_receivexlog_compatible': True, 'pg_receivexlog_synchronous': False, 'pg_receivexlog_path': 'fake/path' } receivexlog_mock.return_value.execute.side_effect = \ CommandFailedException archiver.receive_wal()
def test_get_next_batch( self, from_file_mock, isfile_mock, exists_mock, glob_mock, caplog ): """ Test the FileWalArchiver.get_next_batch method """ # See all logs caplog.set_level(0) # WAL batch, with 000000010000000000000001 that is currently being # written glob_mock.return_value = ["000000010000000000000001"] isfile_mock.return_value = True # This is an hack, instead of a WalFileInfo we use a simple string to # ease all the comparisons. The resulting string is the name enclosed # in colons. e.g. ":000000010000000000000001:" from_file_mock.side_effect = lambda wal_name, compression: (":%s:" % wal_name) backup_manager = build_backup_manager(name="TestServer") archiver = StreamingWalArchiver(backup_manager) backup_manager.server.archivers = [archiver] caplog_reset(caplog) batch = archiver.get_next_batch() assert ["000000010000000000000001"] == batch.skip assert "" == caplog.text # WAL batch, with 000000010000000000000002 that is currently being # written and 000000010000000000000001 can be archived caplog_reset(caplog) glob_mock.return_value = [ "000000010000000000000001", "000000010000000000000002", ] batch = archiver.get_next_batch() assert [":000000010000000000000001:"] == batch assert ["000000010000000000000002"] == batch.skip assert "" == caplog.text # WAL batch, with two partial files. caplog_reset(caplog) glob_mock.return_value = [ "000000010000000000000001.partial", "000000010000000000000002.partial", ] batch = archiver.get_next_batch() assert [":000000010000000000000001.partial:"] == batch assert ["000000010000000000000002.partial"] == batch.skip assert ( "Archiving partial files for server %s: " "000000010000000000000001.partial" % archiver.config.name ) in caplog.text # WAL batch, with history files. caplog_reset(caplog) glob_mock.return_value = [ "00000001.history", "000000010000000000000002.partial", ] batch = archiver.get_next_batch() assert [":00000001.history:"] == batch assert ["000000010000000000000002.partial"] == batch.skip assert "" == caplog.text # WAL batch with errors wrong_file_name = "test_wrong_wal_file.2" glob_mock.return_value = ["test_wrong_wal_file.2"] batch = archiver.get_next_batch() assert [wrong_file_name] == batch.errors # WAL batch, with two partial files, but one has been just renamed. caplog_reset(caplog) exists_mock.side_effect = [False, True] glob_mock.return_value = [ "000000010000000000000001.partial", "000000010000000000000002.partial", ] batch = archiver.get_next_batch() assert len(batch) == 0 assert ["000000010000000000000002.partial"] == batch.skip assert "" in caplog.text