mirror of
https://github.com/borgbackup/borg.git
synced 2026-06-10 01:10:53 -04:00
testsuite: add Archives unit tests, refs #9556
This commit is contained in:
parent
a918deefa9
commit
fdc00d9e8e
1 changed files with 611 additions and 0 deletions
611
src/borg/testsuite/archives_test.py
Normal file
611
src/borg/testsuite/archives_test.py
Normal file
|
|
@ -0,0 +1,611 @@
|
|||
from argparse import Namespace
|
||||
from datetime import datetime, timezone
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from borgstore.store import ItemInfo, ObjectNotFound as StoreObjectNotFound
|
||||
|
||||
from ..helpers.errors import CommandError, Error
|
||||
from ..helpers.parseformat import bin_to_hex
|
||||
from ..helpers.time import parse_timestamp
|
||||
from ..manifest import Archives, ArchiveInfo, ArchivesInterface
|
||||
from ..repository import Repository
|
||||
|
||||
|
||||
def _id(n):
|
||||
return bytes([n]) * 32
|
||||
|
||||
|
||||
TS = "2020-06-01T12:00:00.000000"
|
||||
TS2 = "2021-06-01T12:00:00.000000"
|
||||
|
||||
|
||||
def _item(id_bytes):
|
||||
return ItemInfo(name=bin_to_hex(id_bytes), exists=True, size=0, directory=False)
|
||||
|
||||
|
||||
def _make():
|
||||
repo = Mock()
|
||||
repo.store_list.return_value = []
|
||||
manifest = Mock()
|
||||
return Archives(repo, manifest), repo, manifest
|
||||
|
||||
|
||||
def _archive_meta(name, id_, ts=TS, *, username="", hostname="", tags=()):
|
||||
return {
|
||||
"id": id_,
|
||||
"name": name,
|
||||
"time": ts,
|
||||
"exists": True,
|
||||
"username": username,
|
||||
"hostname": hostname,
|
||||
"size": 0,
|
||||
"nfiles": 0,
|
||||
"comment": "",
|
||||
"tags": tags,
|
||||
}
|
||||
|
||||
|
||||
def _info(name, id_, ts=TS, *, username="", hostname="", tags=()):
|
||||
return ArchiveInfo(name=name, id=id_, ts=parse_timestamp(ts), tags=tags, user=username, host=hostname)
|
||||
|
||||
|
||||
def _stub_matching_info_tuples(infos):
|
||||
ar, _, _ = _make()
|
||||
ar._matching_info_tuples = Mock(side_effect=lambda match_patterns, match_end, deleted=False: list(infos))
|
||||
return ar
|
||||
|
||||
|
||||
def _stub_info_tuples(infos):
|
||||
ar, _, _ = _make()
|
||||
ar._info_tuples = Mock(side_effect=lambda deleted=False: iter(infos))
|
||||
return ar
|
||||
|
||||
|
||||
def test_archives_satisfies_archives_interface():
|
||||
ar, _, _ = _make()
|
||||
assert isinstance(ar, ArchivesInterface)
|
||||
|
||||
|
||||
def test_prepare_is_noop():
|
||||
ar, repo, manifest = _make()
|
||||
m = Mock()
|
||||
ar.prepare(manifest, m)
|
||||
repo.assert_not_called()
|
||||
manifest.assert_not_called()
|
||||
m.assert_not_called()
|
||||
|
||||
|
||||
def test_finish_returns_empty_dict():
|
||||
ar, _, manifest = _make()
|
||||
assert ar.finish(manifest) == {}
|
||||
|
||||
|
||||
def test_ids_empty():
|
||||
ar, _, _ = _make()
|
||||
assert list(ar.ids()) == []
|
||||
|
||||
|
||||
def test_ids_returns_binary_ids():
|
||||
ar, repo, _ = _make()
|
||||
repo.store_list.return_value = [_item(_id(1)), _item(_id(2))]
|
||||
assert list(ar.ids()) == [_id(1), _id(2)]
|
||||
|
||||
|
||||
def test_ids_store_object_not_found_gives_empty():
|
||||
ar, repo, _ = _make()
|
||||
repo.store_list.side_effect = StoreObjectNotFound("archives")
|
||||
assert list(ar.ids()) == []
|
||||
|
||||
|
||||
def test_ids_passes_deleted_flag():
|
||||
ar, repo, _ = _make()
|
||||
repo.store_list.return_value = [_item(_id(1))]
|
||||
result = list(ar.ids(deleted=True))
|
||||
assert result == [_id(1)]
|
||||
repo.store_list.assert_called_once_with("archives", deleted=True)
|
||||
|
||||
|
||||
def test_count_empty():
|
||||
ar, _, _ = _make()
|
||||
assert ar.count() == 0
|
||||
|
||||
|
||||
def test_count():
|
||||
ar, repo, _ = _make()
|
||||
repo.store_list.return_value = [_item(_id(1)), _item(_id(2))]
|
||||
assert ar.count() == 2
|
||||
|
||||
|
||||
def test_names():
|
||||
ar, _, _ = _make()
|
||||
metas = [_archive_meta("a", _id(1)), _archive_meta("b", _id(2))]
|
||||
ar._infos = Mock(side_effect=lambda deleted=False: iter(metas))
|
||||
assert list(ar.names()) == ["a", "b"]
|
||||
|
||||
|
||||
def test_exists_true():
|
||||
ar, _, _ = _make()
|
||||
ar._infos = Mock(side_effect=lambda deleted=False: iter([_archive_meta("a", _id(1))]))
|
||||
assert ar.exists("a") is True
|
||||
|
||||
|
||||
def test_exists_false():
|
||||
ar, _, _ = _make()
|
||||
ar._infos = Mock(side_effect=lambda deleted=False: iter([]))
|
||||
assert ar.exists("missing") is False
|
||||
|
||||
|
||||
def test_exists_id_true():
|
||||
ar, repo, _ = _make()
|
||||
repo.store_list.return_value = [_item(_id(1))]
|
||||
assert ar.exists_id(_id(1)) is True
|
||||
|
||||
|
||||
def test_exists_id_false():
|
||||
ar, repo, _ = _make()
|
||||
repo.store_list.return_value = []
|
||||
assert ar.exists_id(_id(99)) is False
|
||||
|
||||
|
||||
def test_exists_id_deleted():
|
||||
ar, repo, _ = _make()
|
||||
repo.store_list.return_value = [_item(_id(1))]
|
||||
assert ar.exists_id(_id(1), deleted=True) is True
|
||||
repo.store_list.assert_called_with("archives", deleted=True)
|
||||
|
||||
|
||||
def test_exists_name_and_id_true():
|
||||
ar, _, _ = _make()
|
||||
ar._infos = Mock(side_effect=lambda deleted=False: iter([_archive_meta("a", _id(1))]))
|
||||
assert ar.exists_name_and_id("a", _id(1)) is True
|
||||
|
||||
|
||||
def test_exists_name_and_id_false_wrong_name():
|
||||
ar, _, _ = _make()
|
||||
ar._infos = Mock(side_effect=lambda deleted=False: iter([_archive_meta("a", _id(1))]))
|
||||
assert ar.exists_name_and_id("b", _id(1)) is False
|
||||
|
||||
|
||||
def test_exists_name_and_id_false_wrong_id():
|
||||
ar, _, _ = _make()
|
||||
ar._infos = Mock(side_effect=lambda deleted=False: iter([_archive_meta("a", _id(1))]))
|
||||
assert ar.exists_name_and_id("a", _id(2)) is False
|
||||
|
||||
|
||||
def test_exists_name_and_ts_true():
|
||||
ar, _, _ = _make()
|
||||
ar._info_tuples = Mock(side_effect=lambda deleted=False: iter([_info("a", _id(1))]))
|
||||
assert ar.exists_name_and_ts("a", parse_timestamp(TS)) is True
|
||||
|
||||
|
||||
def test_exists_name_and_ts_false_wrong_ts():
|
||||
ar, _, _ = _make()
|
||||
ar._info_tuples = Mock(side_effect=lambda deleted=False: iter([_info("a", _id(1))]))
|
||||
assert ar.exists_name_and_ts("a", parse_timestamp(TS2)) is False
|
||||
|
||||
|
||||
def test_exists_name_and_ts_false_wrong_name():
|
||||
ar, _, _ = _make()
|
||||
ar._info_tuples = Mock(side_effect=lambda deleted=False: iter([_info("a", _id(1))]))
|
||||
assert ar.exists_name_and_ts("b", parse_timestamp(TS)) is False
|
||||
|
||||
|
||||
def test_get_archive_meta_object_not_found():
|
||||
ar, repo, _ = _make()
|
||||
repo.get.side_effect = Repository.ObjectNotFound(_id(1), "/fake/path")
|
||||
result = ar._get_archive_meta(_id(1))
|
||||
assert result == {
|
||||
"id": _id(1),
|
||||
"name": "archive-does-not-exist",
|
||||
"time": "1970-01-01T00:00:00.000000",
|
||||
"exists": False,
|
||||
"username": "",
|
||||
"hostname": "",
|
||||
"tags": (),
|
||||
}
|
||||
|
||||
|
||||
def test_get_archive_meta_success():
|
||||
ar, _, manifest = _make()
|
||||
manifest.repo_objs.parse.return_value = (None, b"data")
|
||||
manifest.key.unpack_archive.return_value = {
|
||||
"version": 2,
|
||||
"name": "myarchive",
|
||||
"time": "2021-03-15T10:00:00.000000",
|
||||
"username": "alice",
|
||||
"hostname": "myhost",
|
||||
"size": 1024,
|
||||
"nfiles": 3,
|
||||
"comment": "weekly",
|
||||
}
|
||||
|
||||
result = ar._get_archive_meta(_id(1))
|
||||
|
||||
assert result["exists"] is True
|
||||
assert result["id"] == _id(1)
|
||||
assert result["name"] == "myarchive"
|
||||
assert result["time"] == "2021-03-15T10:00:00.000000"
|
||||
assert result["username"] == "alice"
|
||||
assert result["hostname"] == "myhost"
|
||||
assert result["size"] == 1024
|
||||
assert result["nfiles"] == 3
|
||||
assert result["comment"] == "weekly"
|
||||
assert result["tags"] == ()
|
||||
|
||||
|
||||
def test_get_archive_meta_success_with_tags():
|
||||
ar, _, manifest = _make()
|
||||
manifest.repo_objs.parse.return_value = (None, b"data")
|
||||
manifest.key.unpack_archive.return_value = {
|
||||
"version": 2,
|
||||
"name": "tagged",
|
||||
"time": TS,
|
||||
"username": "",
|
||||
"hostname": "",
|
||||
"tags": ["beta", "alpha"],
|
||||
}
|
||||
|
||||
result = ar._get_archive_meta(_id(1))
|
||||
|
||||
assert result["tags"] == ("alpha", "beta")
|
||||
assert result["size"] == 0
|
||||
assert result["nfiles"] == 0
|
||||
assert result["comment"] == ""
|
||||
|
||||
|
||||
def test_get_archive_meta_bad_version():
|
||||
ar, _, manifest = _make()
|
||||
manifest.repo_objs.parse.return_value = (None, b"data")
|
||||
manifest.key.unpack_archive.return_value = {"version": 99}
|
||||
|
||||
with pytest.raises(Exception, match="Unknown archive metadata version"):
|
||||
ar._get_archive_meta(_id(1))
|
||||
|
||||
|
||||
def test_get_missing_returns_none():
|
||||
ar, _, _ = _make()
|
||||
ar._infos = Mock(side_effect=lambda deleted=False: iter([]))
|
||||
assert ar.get("nope") is None
|
||||
|
||||
|
||||
def test_get_returns_archive_info():
|
||||
ar, _, _ = _make()
|
||||
ar._infos = Mock(side_effect=lambda deleted=False: iter([_archive_meta("a", _id(1))]))
|
||||
info = ar.get("a")
|
||||
assert isinstance(info, ArchiveInfo)
|
||||
assert info.name == "a"
|
||||
assert info.id == _id(1)
|
||||
|
||||
|
||||
def test_get_raw():
|
||||
ar, _, _ = _make()
|
||||
ar._infos = Mock(side_effect=lambda deleted=False: iter([_archive_meta("a", _id(1))]))
|
||||
result = ar.get("a", raw=True)
|
||||
assert result["name"] == "a"
|
||||
assert result["id"] == _id(1)
|
||||
assert result["time"] == TS
|
||||
assert result["exists"] is True
|
||||
|
||||
|
||||
def test_get_by_id_missing_returns_none():
|
||||
ar, repo, _ = _make()
|
||||
repo.store_list.return_value = []
|
||||
assert ar.get_by_id(_id(99)) is None
|
||||
|
||||
|
||||
@pytest.mark.parametrize("raw", [False, True])
|
||||
def test_get_by_id(raw):
|
||||
ar, repo, _ = _make()
|
||||
repo.store_list.return_value = [_item(_id(1))]
|
||||
ar._get_archive_meta = Mock(side_effect=lambda id_: _archive_meta("a", _id(1)))
|
||||
result = ar.get_by_id(_id(1), raw=raw)
|
||||
if raw:
|
||||
assert result["name"] == "a"
|
||||
assert result["id"] == _id(1)
|
||||
assert result["time"] == TS
|
||||
assert result["exists"] is True
|
||||
else:
|
||||
assert isinstance(result, ArchiveInfo)
|
||||
assert result.name == "a"
|
||||
assert result.id == _id(1)
|
||||
|
||||
|
||||
def test_get_by_id_exists_false_returns_none():
|
||||
ar, repo, _ = _make()
|
||||
repo.store_list.return_value = [_item(_id(1))]
|
||||
meta = _archive_meta("a", _id(1))
|
||||
meta["exists"] = False
|
||||
ar._get_archive_meta = Mock(side_effect=lambda id_: meta)
|
||||
assert ar.get_by_id(_id(1)) is None
|
||||
|
||||
|
||||
def test_get_by_id_deleted():
|
||||
ar, repo, _ = _make()
|
||||
repo.store_list.return_value = [_item(_id(1))]
|
||||
ar._get_archive_meta = Mock(side_effect=lambda id_: _archive_meta("a", _id(1)))
|
||||
info = ar.get_by_id(_id(1), deleted=True)
|
||||
assert isinstance(info, ArchiveInfo)
|
||||
repo.store_list.assert_called_with("archives", deleted=True)
|
||||
|
||||
|
||||
def test_create_calls_store_store():
|
||||
ar, repo, _ = _make()
|
||||
ar.create("a", _id(1), TS)
|
||||
repo.store_store.assert_called_once_with(f"archives/{bin_to_hex(_id(1))}", b"")
|
||||
|
||||
|
||||
def test_create_with_datetime_ts():
|
||||
ar, repo, _ = _make()
|
||||
dt = datetime(2020, 6, 1, 12, 0, 0, tzinfo=timezone.utc)
|
||||
ar.create("a", _id(1), dt)
|
||||
repo.store_store.assert_called_once_with(f"archives/{bin_to_hex(_id(1))}", b"")
|
||||
|
||||
|
||||
def test_create_overwrite_kwarg_ignored():
|
||||
# borgstore store_store is ID-addressed and idempotent; overwrite is an ArchivesInterface
|
||||
# compatibility parameter that Archives intentionally ignores (unlike LegacyArchives).
|
||||
ar, repo, _ = _make()
|
||||
ar.create("a", _id(1), TS, overwrite=True)
|
||||
repo.store_store.assert_called_once_with(f"archives/{bin_to_hex(_id(1))}", b"")
|
||||
|
||||
|
||||
def test_delete_by_id():
|
||||
ar, repo, _ = _make()
|
||||
ar.delete_by_id(_id(1))
|
||||
repo.store_move.assert_called_once_with(f"archives/{bin_to_hex(_id(1))}", delete=True)
|
||||
|
||||
|
||||
def test_undelete_by_id():
|
||||
ar, repo, _ = _make()
|
||||
ar.undelete_by_id(_id(1))
|
||||
repo.store_move.assert_called_once_with(f"archives/{bin_to_hex(_id(1))}", undelete=True)
|
||||
|
||||
|
||||
def test_nuke_by_id():
|
||||
ar, repo, _ = _make()
|
||||
ar.nuke_by_id(_id(1))
|
||||
repo.store_delete.assert_called_once_with(f"archives/{bin_to_hex(_id(1))}", deleted=True)
|
||||
|
||||
|
||||
def test_list_no_filters():
|
||||
info = _info("a", _id(1))
|
||||
ar = _stub_matching_info_tuples([info])
|
||||
assert ar.list() == [info]
|
||||
|
||||
|
||||
def test_list_sort_by_str_raises():
|
||||
ar, _, _ = _make()
|
||||
with pytest.raises(TypeError, match="sort_by must be a sequence"):
|
||||
ar.list(sort_by="name")
|
||||
|
||||
|
||||
def test_list_sort_generator_not_materialised_regression():
|
||||
# _matching_info_tuples must materialise _info_tuples() via list() before returning;
|
||||
# if that list() call is removed, the raw generator reaches .sort() and raises AttributeError.
|
||||
ar = _stub_info_tuples([])
|
||||
assert ar.list(sort_by=["name"]) == []
|
||||
|
||||
|
||||
def test_list_sort_by():
|
||||
i1 = _info("b", _id(2), TS2)
|
||||
i2 = _info("a", _id(1), TS)
|
||||
ar = _stub_matching_info_tuples([i1, i2])
|
||||
result = ar.list(sort_by=["name"])
|
||||
assert result == [i2, i1]
|
||||
|
||||
|
||||
def test_list_reverse():
|
||||
i1 = _info("a", _id(1))
|
||||
i2 = _info("b", _id(2))
|
||||
ar = _stub_matching_info_tuples([i1, i2])
|
||||
assert ar.list(reverse=True) == [i2, i1]
|
||||
|
||||
|
||||
def test_list_first():
|
||||
infos = [_info(f"a{i}", _id(i + 1)) for i in range(5)]
|
||||
ar = _stub_matching_info_tuples(infos)
|
||||
assert ar.list(first=3) == infos[:3]
|
||||
|
||||
|
||||
def test_list_last():
|
||||
infos = [_info(f"a{i}", _id(i + 1)) for i in range(5)]
|
||||
ar = _stub_matching_info_tuples(infos)
|
||||
assert ar.list(last=2) == infos[-2:]
|
||||
|
||||
|
||||
def test_list_first_zero():
|
||||
infos = [_info(f"a{i}", _id(i + 1)) for i in range(3)]
|
||||
ar = _stub_matching_info_tuples(infos)
|
||||
assert ar.list(first=0) == infos
|
||||
|
||||
|
||||
def test_list_last_zero():
|
||||
infos = [_info(f"a{i}", _id(i + 1)) for i in range(3)]
|
||||
ar = _stub_matching_info_tuples(infos)
|
||||
assert ar.list(last=0) == infos
|
||||
|
||||
|
||||
def test_list_date_filter():
|
||||
i1 = _info("a", _id(1))
|
||||
ar = _stub_matching_info_tuples([i1])
|
||||
with patch("borg.manifest.filter_archives_by_date", return_value=[i1]) as mock_filter:
|
||||
result = ar.list(older="1d")
|
||||
assert result == [i1]
|
||||
mock_filter.assert_called_once_with([i1], oldest=None, newest=None, newer=None, older="1d")
|
||||
|
||||
|
||||
def test_list_deleted_passes_flag():
|
||||
ar, _, _ = _make()
|
||||
ar._info_tuples = Mock(side_effect=lambda deleted=False: iter([]))
|
||||
ar.list(deleted=True)
|
||||
ar._info_tuples.assert_called_once_with(deleted=True)
|
||||
|
||||
|
||||
def test_list_match_name():
|
||||
i1 = _info("archive-a", _id(1))
|
||||
i2 = _info("archive-b", _id(2))
|
||||
ar = _stub_info_tuples([i1, i2])
|
||||
assert ar.list(match=["archive-a"]) == [i1]
|
||||
|
||||
|
||||
def test_list_match_name_prefix():
|
||||
i1 = _info("archive-a", _id(1))
|
||||
i2 = _info("other", _id(2))
|
||||
ar = _stub_info_tuples([i1, i2])
|
||||
assert ar.list(match=["name:archive-a"]) == [i1]
|
||||
|
||||
|
||||
def test_list_match_user():
|
||||
i1 = _info("a", _id(1), username="alice")
|
||||
i2 = _info("b", _id(2), username="bob")
|
||||
ar = _stub_info_tuples([i1, i2])
|
||||
assert ar.list(match=["user:alice"]) == [i1]
|
||||
|
||||
|
||||
def test_list_match_host():
|
||||
i1 = _info("a", _id(1), hostname="laptop")
|
||||
i2 = _info("b", _id(2), hostname="server")
|
||||
ar = _stub_info_tuples([i1, i2])
|
||||
assert ar.list(match=["host:laptop"]) == [i1]
|
||||
|
||||
|
||||
def test_list_match_tags():
|
||||
i1 = _info("a", _id(1), tags=("prod", "db"))
|
||||
i2 = _info("b", _id(2), tags=("dev",))
|
||||
ar = _stub_info_tuples([i1, i2])
|
||||
assert ar.list(match=["tags:prod"]) == [i1]
|
||||
|
||||
|
||||
def test_list_match_aid():
|
||||
i1 = _info("a", _id(1))
|
||||
ar = _stub_info_tuples([i1])
|
||||
prefix = bin_to_hex(_id(1))[:4]
|
||||
assert ar.list(match=[f"aid:{prefix}"]) == [i1]
|
||||
|
||||
|
||||
def test_list_match_aid_ambiguous():
|
||||
# Two distinct IDs that share the same leading byte — a realistic prefix collision.
|
||||
id1 = bytes([0x01, 0x00]) + bytes(30)
|
||||
id2 = bytes([0x01, 0x01]) + bytes(30)
|
||||
i1 = _info("a", id1)
|
||||
i2 = _info("b", id2)
|
||||
ar = _stub_info_tuples([i1, i2])
|
||||
prefix = bin_to_hex(id1)[:2] # "01" — matches both IDs
|
||||
with pytest.raises(CommandError, match=r"precisely one"):
|
||||
ar.list(match=[f"aid:{prefix}"])
|
||||
|
||||
|
||||
def test_list_match_multiple_patterns():
|
||||
i1 = _info("archive-a", _id(1), username="alice", hostname="laptop")
|
||||
i2 = _info("archive-b", _id(2), username="alice", hostname="server")
|
||||
i3 = _info("archive-c", _id(3), username="bob", hostname="laptop")
|
||||
ar = _stub_info_tuples([i1, i2, i3])
|
||||
result = ar.list(match=["user:alice", "host:laptop"])
|
||||
assert result == [i1]
|
||||
|
||||
|
||||
def test_list_match_end_custom():
|
||||
i1 = _info("archive-a", _id(1))
|
||||
i2 = _info("other", _id(2))
|
||||
ar = _stub_info_tuples([i1, i2])
|
||||
result = ar.list(match=["archive"], match_end="")
|
||||
assert result == [i1]
|
||||
|
||||
|
||||
def test_get_one_exact_match():
|
||||
i1 = _info("backup", _id(1))
|
||||
ar = _stub_info_tuples([i1])
|
||||
assert ar.get_one(["backup"]) == i1
|
||||
|
||||
|
||||
def test_get_one_no_match_raises():
|
||||
ar = _stub_info_tuples([])
|
||||
with pytest.raises(CommandError, match=r"matched 0\."):
|
||||
ar.get_one(["missing"])
|
||||
|
||||
|
||||
def test_get_one_multiple_matches_raises():
|
||||
i1 = _info("a", _id(1))
|
||||
i2 = _info("a", _id(2))
|
||||
ar = _stub_info_tuples([i1, i2])
|
||||
with pytest.raises(CommandError, match=r"matched 2\."):
|
||||
ar.get_one(["a"])
|
||||
|
||||
|
||||
def test_get_one_deleted_passes_flag():
|
||||
i1 = _info("a", _id(1))
|
||||
ar, _, _ = _make()
|
||||
ar._info_tuples = Mock(side_effect=lambda deleted=False: iter([i1]))
|
||||
ar.get_one(["a"], deleted=True)
|
||||
ar._info_tuples.assert_called_once_with(deleted=True)
|
||||
|
||||
|
||||
def test_list_considering_raises_if_name_set():
|
||||
ar, _, _ = _make()
|
||||
args = Mock()
|
||||
args.name = "archive"
|
||||
with pytest.raises(Error):
|
||||
ar.list_considering(args)
|
||||
|
||||
|
||||
def test_list_considering_delegates():
|
||||
i1 = _info("b", _id(2), TS2)
|
||||
i2 = _info("a", _id(1), TS)
|
||||
ar = _stub_matching_info_tuples([i1, i2])
|
||||
args = Namespace(
|
||||
name=None,
|
||||
sort_by="name",
|
||||
match_archives=None,
|
||||
first=None,
|
||||
last=None,
|
||||
older=None,
|
||||
newer=None,
|
||||
oldest=None,
|
||||
newest=None,
|
||||
deleted=False,
|
||||
)
|
||||
result = ar.list_considering(args)
|
||||
assert result == [i2, i1]
|
||||
|
||||
|
||||
def test_list_considering_with_match_archives():
|
||||
i1 = _info("archive-a", _id(1))
|
||||
i2 = _info("other", _id(2))
|
||||
ar = _stub_info_tuples([i1, i2])
|
||||
args = Namespace(
|
||||
name=None,
|
||||
sort_by="name",
|
||||
match_archives=["archive-a"],
|
||||
first=None,
|
||||
last=None,
|
||||
older=None,
|
||||
newer=None,
|
||||
oldest=None,
|
||||
newest=None,
|
||||
deleted=False,
|
||||
)
|
||||
result = ar.list_considering(args)
|
||||
assert result == [i1]
|
||||
|
||||
|
||||
def test_list_considering_multi_key_sort():
|
||||
i1 = _info("b", _id(1), TS2)
|
||||
i2 = _info("a", _id(2), TS2)
|
||||
i3 = _info("c", _id(3), TS)
|
||||
ar = _stub_matching_info_tuples([i1, i2, i3])
|
||||
args = Namespace(
|
||||
name=None,
|
||||
sort_by="ts,name",
|
||||
match_archives=None,
|
||||
first=None,
|
||||
last=None,
|
||||
older=None,
|
||||
newer=None,
|
||||
oldest=None,
|
||||
newest=None,
|
||||
deleted=False,
|
||||
)
|
||||
result = ar.list_considering(args)
|
||||
assert result == [i3, i2, i1]
|
||||
Loading…
Reference in a new issue