import argparse from unittest import mock import subprocess import pytest from locutus.info import run_info def make_args(config, profile): args = argparse.Namespace() args.config = config args.profile = profile return args @mock.patch('locutus.info.LocutusConfig') @mock.patch('subprocess.run') def test_info_basic_output(mock_run, mock_config, capsys): mock_config.return_value.toml_path = '/tmp/test.toml' mock_config.return_value.rc_path = '/tmp/test.rc' mock_config.return_value.get_repo.return_value = '/repo' mock_config.return_value.get_passphrase.return_value = 'hunter2' mock_config.return_value.includes = ['/etc', '/home'] mock_config.return_value.excludes = ['*.cache'] mock_config.return_value.prune = {'keep_last': 3, 'keep_daily': 1} args = make_args('/tmp/test.toml', '/tmp/test.rc') mock_run.return_value.returncode = 0 run_info(args) out = capsys.readouterr().out assert 'Config: /tmp/test.toml' in out assert 'Profile: /tmp/test.rc' in out assert 'Repo: /repo' in out assert 'Passphrase: set' in out assert 'Includes:' in out and '/etc' in out and '/home' in out assert 'Excludes:' in out and '*.cache' in out assert 'Prune: keep_last=3, keep_daily=1' in out assert '[borg info output below]' in out mock_run.assert_called_with( ['borg', 'info', '/repo'], env=mock.ANY, check=True ) @mock.patch('locutus.info.LocutusConfig') @mock.patch('subprocess.run') def test_info_no_repo(mock_run, mock_config, capsys): mock_config.return_value.toml_path = '/tmp/test.toml' mock_config.return_value.rc_path = '/tmp/test.rc' mock_config.return_value.get_repo.return_value = None mock_config.return_value.get_passphrase.return_value = None mock_config.return_value.includes = [] mock_config.return_value.excludes = [] mock_config.return_value.prune = {} args = make_args('/tmp/test.toml', '/tmp/test.rc') run_info(args) out = capsys.readouterr().out assert 'Repo: (not set)' in out assert 'Passphrase: (not set)' in out assert '[borg info output below]' in out mock_run.assert_not_called() @mock.patch('locutus.info.LocutusConfig') @mock.patch( 'subprocess.run', side_effect=subprocess.CalledProcessError(1, ['borg', 'info']), ) def test_info_borg_info_fails(mock_run, mock_config, capsys): mock_config.return_value.toml_path = '/tmp/test.toml' mock_config.return_value.rc_path = '/tmp/test.rc' mock_config.return_value.get_repo.return_value = '/repo' mock_config.return_value.get_passphrase.return_value = 'hunter2' mock_config.return_value.includes = [] mock_config.return_value.excludes = [] mock_config.return_value.prune = {} args = make_args('/tmp/test.toml', '/tmp/test.rc') run_info(args) err = capsys.readouterr().err assert 'borg info failed:' in err @mock.patch('locutus.info.LocutusConfig') @mock.patch('subprocess.run', side_effect=Exception('fail')) def test_info_borg_info_generic_exception(mock_run, mock_config, capsys): mock_config.return_value.toml_path = '/tmp/test.toml' mock_config.return_value.rc_path = '/tmp/test.rc' mock_config.return_value.get_repo.return_value = '/repo' mock_config.return_value.get_passphrase.return_value = 'hunter2' mock_config.return_value.includes = [] mock_config.return_value.excludes = [] mock_config.return_value.prune = {} args = make_args('/tmp/test.toml', '/tmp/test.rc') run_info(args) err = capsys.readouterr().err assert 'borg info failed: fail' in err