#!/usr/bin/python3 # Copyright (C) 2026 Danilo M. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. """Run: /usr/bin/python3 desktop/modules/updates/test_updatesctl.py Imports updatesctl for vercmp, then drives it as a CLI against a fixture tree under a temp dir (UPDATESCTL_ROOT for system paths, HOME for the user's), never the live system. Plain asserts, no framework. """ import importlib.machinery import importlib.util import json import os import shutil import subprocess import tempfile from pathlib import Path SCRIPT = Path(__file__).resolve().parent / "updatesctl" loader = importlib.machinery.SourceFileLoader("updatesctl", str(SCRIPT)) spec = importlib.util.spec_from_loader("updatesctl", loader) u = importlib.util.module_from_spec(spec) loader.exec_module(u) # --- vercmp --- assert u.vercmp("1.14.10", "1.14.9") > 0 assert u.vercmp("2.1.278", "2.1.267") > 0 assert u.vercmp("2026_10_02", "2026_09_12") > 0 assert u.vercmp("v1.2", "1.2") == 0 assert u.vercmp("1.0", "1.0") == 0 # A pre-release is older than the release, a suffix is never behind. assert u.vercmp("0.12.3_beta.4", "0.12.3") < 0 assert u.vercmp("9.018.00_6.18.41", "9.018.00") > 0 assert u.vercmp("3.1-659215d", "3.1") > 0 assert u.vercmp("1.0.1", "1.0rc1") > 0 # --- fixture tree --- tmp = Path(tempfile.mkdtemp(prefix="updatesctl-test-")) home = tmp / "home" def w(path, text=""): path.parent.mkdir(parents=True, exist_ok=True) path.write_text(text) def info(repo_rel, version): w(home / "Programming/GIT/slackbuilds-superrepo" / repo_rel, f'PRGNAM="x"\nVERSION="{version}"\n') def sbo(rel, version): w(tmp / "var/lib/sbopkg/SBo-git" / rel, f'VERSION="{version}"\n') def pkgtxt(entries): return "".join(f"PACKAGE NAME: {full}.txz\nPACKAGE LOCATION: ./{loc}\n\n" for loc, full in entries) installed = [ "kitty-0.49.1-x86_64-1_danix", # built 0.49.2 -> upgrade "gamescope-3.16.30-x86_64-1_danix", # recipe bumped -> build "discord-1.0.159-x86_64-1_danix", # recipe behind -> upstream "claude-code-2.1.278-x86_64-1_SBo", # ahead of SBo -> upstream "nessus-10.12.4-x86_64-1_SBo", # SBo current -> build "neovim-0.12.6-x86_64-1_SBo", # current -> nothing "r8125-9.018.00_6.18.41-x86_64-1_danix", # suffix -> nothing "solvespace-3.1-659215d-x86_64-1_danix", # dash version -> nothing "glibc-2.44-x86_64-3", # mirror has -4 -> slackware upgrade "bash-5.3-x86_64-1", # testing/ newer, blacklisted -> nothing "dhcp-4.4.3-x86_64-1", # removed upstream -> slackware removed "foo-1.0-x86_64-1_SBo", # blacklisted build -> nothing ] for f in installed: w(tmp / "var/log/packages" / f) w(home / ".config/nvchecker/new_ver.json", json.dumps({"version": 2, "data": { "kitty": {"version": "0.49.2"}, "gamescope": {"version": "3.16.31"}, "discord": {"version": "1.0.162"}, "claude-code": {"version": "2.1.300"}, "nessus": {"version": "10.12.5"}, "neovim": {"version": "0.12.6"}, "r8125": {"version": "9.018.00"}, "solvespace": {"version": "3.1"}, "exploitdb": {"version": "2026_10_02"}, # not installed, my recipe behind "obsidian": {"version": "1.14.4"}, # not installed, SBo behind: hidden "Typora": {"version": "1.14.10"}, # AppImage behind "GIMP": {"version": "3.0.6"}, # flatpak behind }})) info("my-slackbuilds/kitty-bin/kitty-bin.info", "0.49.2") info("my-slackbuilds/gamescope/gamescope.info", "3.16.31") info("my-slackbuilds/network/discord/discord.info", "1.0.161") info("my-slackbuilds/r8125/r8125.info", "9.018.00") info("my-slackbuilds/solvespace/solvespace.info", "3.1") info("sbo-slackbuilds/system/exploitdb/exploitdb.info", "2026_09_12") sbo("development/claude-code-bin/claude-code-bin.info", "2.1.267") sbo("network/nessus/nessus.info", "10.12.5") sbo("development/neovim/neovim.info", "0.12.4") sbo("office/obsidian/obsidian.info", "1.13.7") w(home / ".local/state/appimage-updater/installed.json", json.dumps({"Typora": {"version": "1.14.9"}})) w(tmp / "bin/flatpak", "#!/bin/sh\nprintf 'org.gimp.GIMP\\t3.0.4\\n'\n") (tmp / "bin/flatpak").chmod(0o755) w(tmp / "etc/slackpkg/slackpkgplus.conf", "MIRRORPLUS['danix']=dir://repo/\n") w(tmp / "repo/PACKAGES.TXT", pkgtxt([ ("devel/kitty", "kitty-0.49.2-x86_64-1_danix"), ("games/gamescope", "gamescope-3.16.30-x86_64-1_danix"), ])) w(tmp / "etc/slackpkg/mirrors", "# a comment\nfile://mnt/mirror/\n") w(tmp / "etc/slackpkg/blacklist", '"testing/"\n[0-9]+_SBo\n') w(tmp / "mnt/mirror/PACKAGES.TXT", pkgtxt([ ("slackware64/l", "glibc-2.44-x86_64-4"), ("slackware64/a", "bash-5.3-x86_64-1"), ("testing/packages", "bash-5.4-x86_64-1"), ("slackware64/a", "foo-1.1-x86_64-1"), ("slackware64/l", "libtatsu-1.0.5-x86_64-1"), ])) w(tmp / "mnt/mirror/ChangeLog.txt", """\ Wed Oct 14 21:48:34 UTC 2026 l/glibc-2.44-x86_64-4.txz: Rebuilt. l/libtatsu-1.0.5-x86_64-1.txz: Upgraded. n/dhcp-4.4.3-x86_64-1.txz: Removed. +--------------------------+ Thu Oct 1 10:00:00 UTC 2026 x/oldthing-1.0-x86_64-1.txz: Removed. l/libtatsu-1.0.4-x86_64-1.txz: Added. +--------------------------+ Tue Sep 1 10:00:00 UTC 2026 x/oldthing-1.0-x86_64-1.txz: Added. """) def run(*args, timeout="5"): env = {"HOME": str(home), "UPDATESCTL_ROOT": str(tmp), "UPDATESCTL_NFS_TIMEOUT": timeout, "PATH": f"{tmp}/bin:/usr/bin:/bin"} r = subprocess.run(["/usr/bin/python3", str(SCRIPT), *args], capture_output=True, text=True, env=env, timeout=30) assert r.returncode == 0, r.stderr return json.loads(r.stdout) def rows(section): return {x["name"]: (x["repo"], x["from"], x["to"]) for x in section} d = run() assert d["errors"] == {}, d["errors"] assert d["checked"] > 0 assert rows(d["upgrade"]) == {"kitty": ("personal", "0.49.1", "0.49.2")}, d["upgrade"] assert rows(d["build"]) == { "gamescope": ("personal", "3.16.30", "3.16.31"), "nessus": ("SBo", "10.12.4", "10.12.5"), }, d["build"] assert rows(d["upstream"]) == { "discord": ("personal", "1.0.161", "1.0.162"), "claude-code": ("SBo", "2.1.278", "2.1.300"), "exploitdb": ("my-sbo", "2026_09_12", "2026_10_02"), }, d["upstream"] assert rows(d["apps"]) == { "Typora": ("AppImage", "1.14.9", "1.14.10"), "GIMP": ("flatpak", "3.0.4", "3.0.6"), }, d["apps"] shutil.rmtree(tmp) print("ok")