medias 0.5.1

TV media player on bare DRM/KMS: Vulkan UI plane over libmpv video, for local files, UPnP/DLNA servers and YouTube, controlled by HDMI-CEC remote, evdev or terminal
"""Checks of dist.py's ar, tar and .deb writers; no compiler or dpkg needed."""

import hashlib
import io
import sys
import tarfile
import tempfile
import unittest
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent))
import dist  # noqa: E402
import repo  # noqa: E402


def ar_members(data):
    assert data.startswith(b"!<arch>\n")
    pos, members = 8, []
    while pos < len(data):
        header = data[pos:pos + 60]
        assert header[58:60] == b"`\n"
        name, size = header[:16].decode().rstrip(), int(header[48:58])
        members.append((name, data[pos + 60:pos + 60 + size]))
        pos += 60 + size + size % 2
    return members


class Ar(unittest.TestCase):
    def test_odd_member_padded(self):
        data = dist.ar_archive([("a", b"xyz"), ("b", b"12")], 0)
        self.assertEqual(ar_members(data), [("a", b"xyz"), ("b", b"12")])


class WithParents(unittest.TestCase):
    def test_directories_precede_files(self):
        entries = dist.with_parents({"./usr/bin/x": (b"1", 0o755)})
        self.assertEqual([e[0] for e in entries], ["./", "./usr/", "./usr/bin/", "./usr/bin/x"])


class Deb(unittest.TestCase):
    def test_layout(self):
        with tempfile.TemporaryDirectory() as tmp:
            binary = Path(tmp) / "medias"
            binary.write_bytes(b"\x7fELF fake")
            deb = dist.build_deb(binary, Path(tmp), "medias", "1.2.3", "Short: long text",
                                 "arm64", ["libc6 (>= 2.34)", "libmpv2"], "A <a@b>", 1_700_000_000)
            self.assertEqual(deb.name, "medias_1.2.3-1_arm64.deb")
            members = dict(ar_members(deb.read_bytes()))
        self.assertEqual(list(members), ["debian-binary", "control.tar.xz", "data.tar.xz"])
        self.assertEqual(members["debian-binary"], b"2.0\n")

        with tarfile.open(fileobj=io.BytesIO(members["control.tar.xz"])) as tar:
            control = tar.extractfile("./control").read().decode()
            md5sums = tar.extractfile("./md5sums").read().decode()
            self.assertEqual(tar.getmember("./postinst").mode, 0o755)
            self.assertEqual(tar.extractfile("./conffiles").read(), b"/etc/default/medias\n")
        self.assertIn("Architecture: arm64\n", control)
        self.assertIn("Version: 1.2.3-1\n", control)
        self.assertIn("Depends: libc6 (>= 2.34), libmpv2\n", control)
        self.assertIn("Description: Short\n Long text.\n", control)

        with tarfile.open(fileobj=io.BytesIO(members["data.tar.xz"])) as tar:
            names = tar.getnames()
            self.assertEqual(len(names), len(set(names)))
            exe = tar.getmember("./usr/bin/medias")
            self.assertEqual((exe.mode, exe.uid, exe.uname), (0o755, 0, "root"))
            self.assertIn("./usr/lib/systemd/system/medias@.service", names)
        self.assertIn(f"{hashlib.md5(b'\x7fELF fake').hexdigest()}  usr/bin/medias\n", md5sums)


class Repo(unittest.TestCase):
    def test_sources_embeds_key(self):
        text = repo.sources_text("https://h/m", "trixie", "-----BEGIN-----\n\nAAA\n-----END-----\n")
        self.assertEqual(text, "Types: deb\nURIs: https://h/m\nSuites: trixie\nComponents: main\n"
                               "Architectures: amd64 arm64\nSigned-By:\n -----BEGIN-----\n .\n AAA\n -----END-----\n")

    def test_release_hashes(self):
        with tempfile.TemporaryDirectory() as tmp:
            index = Path(tmp) / "dists" / "trixie" / "main" / "binary-amd64" / "Packages"
            index.parent.mkdir(parents=True)
            index.write_bytes(b"Package: x\n")
            text = repo.release_text(Path(tmp), "trixie", [index.relative_to(index.parents[2])], 0)
        digest = hashlib.sha256(b"Package: x\n").hexdigest()
        self.assertIn("Date: Thu, 01 Jan 1970 00:00:00 GMT\n", text)
        self.assertIn(f"SHA256:\n {digest} {11:>16} main/binary-amd64/Packages\n", text)


if __name__ == "__main__":
    unittest.main()