#!/usr/bin/env python3 # -*- coding: utf-8 -*- """Fixture tests for check-currency.py (R-731) — no network. The tag lists are the ones the 2026-09-30 audit read (felhom.eu/documentation/audits/catalog-currency-2026-09-30/10-shape-switch-detail.txt and 09-shape-switch-check.txt), cut to the tags that decide each case. Run: python3 scripts/test_check_currency.py """ import importlib.util import os import sys import unittest HERE = os.path.dirname(os.path.abspath(__file__)) spec = importlib.util.spec_from_file_location("check_currency", os.path.join(HERE, "check-currency.py")) cc = importlib.util.module_from_spec(spec) spec.loader.exec_module(cc) GRAMPS = ['26.4.3', '26.5.0', '26.9.0', '26.9.1', 'v25.1.0', 'v25.5.2', 'v25.6.0'] JELLYFIN = ['10.11.10', '10.11.11', '12.0-rc3', '12.0-rc3-amd64.20260722-020441', '12.0-rc7.20260831-232051', '12.0.20260908-012347', '12.1', '12.1-amd64.20260915-010956', '12.1.20260915-010956'] KIMAI = ['2.58.0', '2.66.0', '2.67.0', 'apache-2.56.0', 'apache-2.57.0'] SONARR = ['4.0.19', '4.0.20', '4.0.20.2983-ls301', 'amd64-5.14-2.0.0.5344-ls5', 'develop', 'latest'] TANDOOR = ['2.6.14', '2.6.15', 'dependabot-pip-drf-spectacular-sidecar-2025.10.1', 'beta-2.7.0'] POSTGRES = ['16-alpine', '16.4-alpine', '17-alpine', '18-alpine', '18', '19beta1-alpine'] class ShapeSwitch(unittest.TestCase): """The control must catch the three the same-shape rule missed, and stay silent on the two that fooled it.""" def test_the_three_real_switches_are_caught(self): self.assertEqual(cc.shape_switch(GRAMPS, "v25.6.0")[0], "26.9.1") self.assertEqual(cc.shape_switch(JELLYFIN, "10.11.11")[0], "12.1") self.assertEqual(cc.shape_switch(KIMAI, "apache-2.57.0")[0], "2.67.0") def test_the_same_shape_rule_alone_reads_them_current(self): # the defect the control exists for: nothing newer under the pin's own shape for tags, pin in ((GRAMPS, "v25.6.0"), (JELLYFIN, "10.11.11"), (KIMAI, "apache-2.57.0")): same = cc.newest_same_shape(tags, pin) self.assertFalse(same["all"][1] > same["cur"], pin) def test_arch_prefixed_and_branch_tags_are_not_releases(self): self.assertIsNone(cc.shape_switch(SONARR, "4.0.20")) # amd64-5.14-… fooled the first pass self.assertIsNone(cc.shape_switch(TANDOOR, "2.6.15")) # dependabot-… and beta-… too def test_a_build_stamped_tag_alone_is_not_a_release(self): # jellyfin publishes arch + date builds beside each release; one with no plain tag is not a release to move to self.assertIsNone(cc.shape_switch(['10.11.11', '13.0-amd64.20261001-010101', '13.0.20261001-010101'], "10.11.11")) def test_a_newer_same_shape_tag_is_behind_not_a_switch(self): self.assertIsNone(cc.shape_switch(POSTGRES, "16-alpine")) same = cc.newest_same_shape(POSTGRES, "16-alpine") self.assertEqual(same["all"][0], "18-alpine") # 19beta1 skipped as unstable self.assertEqual(same["maj"][0], "16-alpine") # 16.4-alpine is another shape def test_current_pin_with_nothing_newer_is_silent(self): self.assertIsNone(cc.shape_switch(['2.6.0', '2.5.9'], "2.6.0")) def test_release_core(self): self.assertEqual(cc.core("26.9.1"), (26, 9, 1)) self.assertEqual(cc.core("v1.2"), (1, 2, 0)) self.assertEqual(cc.core("2.67.0-apache"), (2, 67, 0)) for junk in ("12.0-rc3", "amd64-5.14-2.0.0.5344-ls5", "12.1.20260915-010956", "latest", "develop"): self.assertIsNone(cc.core(junk), junk) if __name__ == "__main__": unittest.main(verbosity=2)