from __future__ import annotations from scripts.debian_closure import ( PackageRecord, parse_control_stanzas, parse_dependency_field, resolve_closure, ) def package(name: str, dependencies: str = "", *, version: str = "1") -> PackageRecord: return PackageRecord( name=name, version=version, architecture="arm64", dependencies=parse_dependency_field(dependencies), provides=(), ) def test_control_parser_joins_continuation_lines(): stanzas = parse_control_stanzas( "Package: demo\nVersion: 1\nDepends: first,\n second | third\n\n" ) assert stanzas == [ {"Package": "demo", "Version": "1", "Depends": "first, second | third"} ] def test_dependency_parser_filters_other_architectures_and_normalizes_qualifiers(): groups = parse_dependency_field( "base:any (>= 1), wrong [amd64], choice [arm64] | fallback, native:native" ) assert [[item.name for item in group] for group in groups] == [ ["base"], ["choice", "fallback"], ["native"], ] def test_resolver_uses_installed_packages_and_recurses_only_for_missing_groups(): local = {"app": package("app", "base, codec (= 2), optional | fallback")} available = { "codec": package("codec", "runtime", version="2"), "runtime": package("runtime"), "fallback": package("fallback"), } selected, unresolved = resolve_closure( ["app"], {"base": "1", "optional": "5"}, local, available ) assert unresolved == [] assert set(selected) == {"app", "codec", "runtime"} def test_resolver_reports_an_unavailable_dependency(): selected, unresolved = resolve_closure( ["app"], {}, {"app": package("app", "missing")}, {} ) assert set(selected) == {"app"} assert unresolved == ["app cannot satisfy: missing"]