Files
locutus/test/test_list.py
Alexander Wainwright f79664c5e5 Initial commit
2025-06-24 17:46:38 +10:00

180 lines
5.4 KiB
Python

import argparse
from unittest import mock
import pytest
from locutus.list import run_list
def make_args(config, profile, target=None):
args = argparse.Namespace()
args.config = config
args.profile = profile
if target is not None:
args.target = target
return args
@mock.patch('locutus.list.LocutusConfig')
@mock.patch('subprocess.run')
def test_list_prints_chrono_and_numbers_reverse(
mock_subproc, mock_config, capsys
):
mock_config.return_value.get_repo.return_value = '/repo'
mock_config.return_value.env = {}
# Oldest to newest
archives = ['archA', 'archB', 'archC']
mock_subproc.return_value.stdout = '\n'.join(archives) + '\n'
mock_subproc.return_value.returncode = 0
args = make_args('dummy.toml', 'dummy.rc')
rc = run_list(args)
assert rc == 0
out = capsys.readouterr().out.strip().splitlines()
# Should print:
# 2: archA
# 1: archB
# 0: archC
assert out[0].strip() == '2: archA'
assert out[1].strip() == '1: archB'
assert out[2].strip() == '0: archC'
@mock.patch('locutus.list.LocutusConfig')
@mock.patch('subprocess.run')
def test_list_by_index_most_recent(mock_subproc, mock_config, capsys):
mock_config.return_value.get_repo.return_value = '/repo'
mock_config.return_value.env = {}
# Oldest to newest
archives = ['oldest', 'middle', 'newest']
# First subprocess.run: get archives (reversed in code)
mock_subproc.side_effect = [
mock.Mock(stdout='\n'.join(archives) + '\n', returncode=0),
mock.Mock(stdout='file1\nfile2\n', returncode=0),
]
args = make_args('dummy.toml', 'dummy.rc', target='0')
rc = run_list(args)
assert rc == 0
out = capsys.readouterr().out
# Should show file list for "newest"
assert 'file1' in out and 'file2' in out
call_args = mock_subproc.call_args_list[1][0][0]
# Should call borg list ...::newest
assert call_args == ['borg', 'list', '/repo::newest']
@mock.patch('locutus.list.LocutusConfig')
@mock.patch('subprocess.run')
def test_list_by_index_out_of_range(mock_subproc, mock_config, capsys):
mock_config.return_value.get_repo.return_value = '/repo'
mock_config.return_value.env = {}
archives = ['archA', 'archB']
mock_subproc.return_value.stdout = '\n'.join(archives) + '\n'
mock_subproc.return_value.returncode = 0
args = make_args('dummy.toml', 'dummy.rc', target='3') # out of range
rc = run_list(args)
assert rc == 1
err = capsys.readouterr().err
assert 'Archive index out of range' in err
@mock.patch('locutus.list.LocutusConfig')
@mock.patch('subprocess.run')
def test_list_by_name(mock_subproc, mock_config, capsys):
mock_config.return_value.get_repo.return_value = '/repo'
mock_config.return_value.env = {}
# Only need one subprocess.run (direct by name)
mock_subproc.return_value.stdout = 'filex\nfiley\n'
mock_subproc.return_value.returncode = 0
args = make_args('dummy.toml', 'dummy.rc', target='archive-explicit')
rc = run_list(args)
assert rc == 0
out = capsys.readouterr().out
assert 'filex' in out and 'filey' in out
call_args = mock_subproc.call_args[0][0]
assert call_args == ['borg', 'list', '/repo::archive-explicit']
@mock.patch('locutus.list.LocutusConfig')
def test_list_no_repo(mock_config, capsys):
mock_config.return_value.get_repo.return_value = None
mock_config.return_value.env = {}
args = make_args('dummy.toml', 'dummy.rc')
rc = run_list(args)
assert rc == 1
err = capsys.readouterr().err
assert 'No BORG_REPO configured' in err
@mock.patch('locutus.list.LocutusConfig')
@mock.patch('subprocess.run', side_effect=Exception('fail'))
def test_list_unexpected_exception(mock_subproc, mock_config, capsys):
mock_config.return_value.get_repo.return_value = '/repo'
mock_config.return_value.env = {}
args = make_args('dummy.toml', 'dummy.rc')
rc = run_list(args)
assert rc == 1
err = capsys.readouterr().err
assert 'borg list failed' in err
@mock.patch('locutus.list.LocutusConfig')
@mock.patch(
'subprocess.run',
side_effect=pytest.importorskip('subprocess').CalledProcessError(
1, ['borg', 'list']
),
)
def test_list_calledprocesserror(mock_subproc, mock_config, capsys):
mock_config.return_value.get_repo.return_value = '/repo'
mock_config.return_value.env = {}
args = make_args('dummy.toml', 'dummy.rc')
rc = run_list(args)
assert rc == 1
err = capsys.readouterr().err
assert 'borg list failed' in err
@mock.patch('locutus.list.LocutusConfig')
@mock.patch('subprocess.run')
def test_list_no_archives(mock_subproc, mock_config, capsys):
mock_config.return_value.get_repo.return_value = '/repo'
mock_config.return_value.env = {}
mock_subproc.return_value.stdout = ''
mock_subproc.return_value.returncode
@mock.patch('locutus.list.LocutusConfig')
@mock.patch('subprocess.run')
def test_list_no_archives_main(mock_subproc, mock_config, capsys):
mock_config.return_value.get_repo.return_value = '/repo'
mock_config.return_value.env = {}
mock_subproc.return_value.stdout = '' # No archives
mock_subproc.return_value.returncode = 0
args = make_args('dummy.toml', 'dummy.rc')
rc = run_list(args)
assert rc == 0
out = capsys.readouterr().out
assert 'No archives found' in out
@mock.patch('locutus.list.LocutusConfig')
@mock.patch('subprocess.run')
def test_list_by_index_no_archives(mock_subproc, mock_config, capsys):
mock_config.return_value.get_repo.return_value = '/repo'
mock_config.return_value.env = {}
mock_subproc.return_value.stdout = '' # No archives
mock_subproc.return_value.returncode = 0
args = make_args('dummy.toml', 'dummy.rc', target='0')
rc = run_list(args)
assert rc == 1
out = capsys.readouterr().out
assert 'No archives found' in out