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 import repo
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()