114 lines
3.4 KiB
Python
114 lines
3.4 KiB
Python
"""Tests for metadata parsing (tolerant of real-world dump quirks)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from sjaur.errors import CacheCorruptError
|
|
from sjaur.metadata import format_timestamp, parse_packages
|
|
|
|
|
|
def test_parse_minimal_entry():
|
|
packages, skipped = parse_packages([{"Name": "firefox"}])
|
|
assert skipped == 0
|
|
(package,) = packages
|
|
assert package.name == "firefox"
|
|
assert package.version == ""
|
|
assert package.description == ""
|
|
assert package.maintainer == ""
|
|
assert package.votes == 0
|
|
assert package.popularity == 0.0
|
|
assert package.out_of_date is None
|
|
assert package.is_orphan
|
|
assert package.aur_url == "https://aur.archlinux.org/packages/firefox"
|
|
|
|
|
|
def test_parse_full_entry():
|
|
entry = {
|
|
"Name": "cower",
|
|
"PackageBase": "cower",
|
|
"Version": "14-2",
|
|
"Description": "A simple AUR agent",
|
|
"URL": "http://example.com",
|
|
"NumVotes": 590,
|
|
"Popularity": 24.59,
|
|
"OutOfDate": None,
|
|
"Maintainer": "falconindy",
|
|
"FirstSubmitted": 1293676237,
|
|
"LastModified": 1441804093,
|
|
"Depends": ["curl", "openssl"],
|
|
"MakeDepends": ["perl"],
|
|
"Keywords": ["aur"],
|
|
"License": ["MIT"],
|
|
}
|
|
packages, skipped = parse_packages([entry])
|
|
assert skipped == 0
|
|
(package,) = packages
|
|
assert package.name == "cower"
|
|
assert package.version == "14-2"
|
|
assert package.votes == 590
|
|
assert package.popularity == 24.59
|
|
assert package.out_of_date is None
|
|
assert package.maintainer == "falconindy"
|
|
assert package.depends == ("curl", "openssl")
|
|
assert package.make_depends == ("perl",)
|
|
assert package.keywords == ("aur",)
|
|
assert package.licenses == ("MIT",)
|
|
assert not package.is_orphan
|
|
|
|
|
|
def test_out_of_date_timestamp_is_kept():
|
|
packages, _ = parse_packages([{"Name": "x", "OutOfDate": 1720000000}])
|
|
assert packages[0].out_of_date == 1720000000
|
|
|
|
|
|
def test_missing_fields_are_omitted_by_server():
|
|
# The dump omits fields a package does not have; lists must be empty, not None.
|
|
packages, _ = parse_packages([{"Name": "x", "Depends": None, "Keywords": []}])
|
|
assert packages[0].depends == ()
|
|
assert packages[0].keywords == ()
|
|
|
|
|
|
def test_malformed_entries_are_skipped_and_counted():
|
|
packages, skipped = parse_packages(
|
|
[
|
|
{"Name": "ok"},
|
|
"not a dict",
|
|
42,
|
|
{"Version": "1.0"}, # no Name
|
|
{"Name": " "}, # blank Name
|
|
None,
|
|
]
|
|
)
|
|
assert [p.name for p in packages] == ["ok"]
|
|
assert skipped == 5
|
|
|
|
|
|
def test_non_list_payload_is_rejected():
|
|
with pytest.raises(CacheCorruptError):
|
|
parse_packages({"Name": "firefox"})
|
|
|
|
|
|
def test_type_mismatches_do_not_crash():
|
|
entry = {
|
|
"Name": "weird",
|
|
"Version": 123,
|
|
"NumVotes": "many",
|
|
"Popularity": None,
|
|
"Depends": "python", # wrong container type
|
|
"Keywords": [1, None, "ok"],
|
|
}
|
|
packages, _ = parse_packages([entry])
|
|
package = packages[0]
|
|
assert package.version == ""
|
|
assert package.votes == 0
|
|
assert package.popularity == 0.0
|
|
assert package.depends == ()
|
|
assert package.keywords == ("ok",)
|
|
|
|
|
|
def test_format_timestamp():
|
|
assert format_timestamp(None) == "unknown"
|
|
assert format_timestamp(0) == "unknown"
|
|
assert format_timestamp(1441804093) == "2015-09-09 13:08 UTC"
|