From 900629606b4cedbf07f3aeb1556ca8ebe8709237 Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Thu, 15 May 2025 16:40:11 -0700 Subject: [PATCH] Allow nested ProfileGroups OK, this is getting kinda close to over-engineering, but what the heck. With this, a profile group can contain another profile group. There is no infinite recursion protection yet. Signed-off-by: Adam Williamson --- fifloader.py | 21 +++++++++++++++++---- unittests/data/templates.fif.json | 2 +- unittests/test_fifloader.py | 5 +++++ 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/fifloader.py b/fifloader.py index b7da6512..59905667 100755 --- a/fifloader.py +++ b/fifloader.py @@ -222,6 +222,22 @@ def merge_inputs(inputs, validate=False, clean=False): return (machines, flavors, products, profiles, pgroups, testsuites, jobtemplates) +def recurse_pgroup(pgroup, baseprio, pgroups, seen): + """Recursion handler allowing nested profile groups. Takes the + top-level profile group name and priority, the full ProfileGroups + dict, and a set for infinite recursion checking. + """ + profiles = {} + for (item, prio) in pgroups[pgroup].items(): + if item in seen: + sys.exit(f"Infinite recursion between profile groups {pgroup} and {item}") + seen.add(item) + if item in pgroups: + profiles.update(recurse_pgroup(item, prio+baseprio, pgroups, seen)) + else: + profiles[item] = prio+baseprio + return profiles + def generate_job_templates(products, profiles, pgroups, testsuites): """Given machines, products, profiles and testsuites (after merging and handling of flavors, but still in intermediate format), @@ -231,10 +247,7 @@ def generate_job_templates(products, profiles, pgroups, testsuites): for (name, suite) in testsuites.items(): suiteprofs = {} for (pgroup, baseprio) in suite.get('profile_groups', {}).items(): - if pgroup not in pgroups: - sys.exit(f"Error: profile group {pgroup} does not exist!") - for (gotprof, pprio) in pgroups[pgroup].items(): - suiteprofs[gotprof] = pprio+baseprio + suiteprofs.update(recurse_pgroup(pgroup, baseprio, pgroups, set())) suiteprofs.update(suite.get('profiles', {})) if not suiteprofs: print("Warning: no profiles for test suite {}".format(name)) diff --git a/unittests/data/templates.fif.json b/unittests/data/templates.fif.json index e2f569a0..db9e5090 100644 --- a/unittests/data/templates.fif.json +++ b/unittests/data/templates.fif.json @@ -67,7 +67,7 @@ }, "ProfileGroups": { "fedora-server-2arch": { - "fedora-Server-dvd-iso-ppc64le-*-ppc64le": 0, + "fedora-server-1arch": 0, "fedora-Server-dvd-iso-x86_64-*-64bit": 1 }, "fedora-server-1arch": { diff --git a/unittests/test_fifloader.py b/unittests/test_fifloader.py index 9adf1e69..9b582a7c 100644 --- a/unittests/test_fifloader.py +++ b/unittests/test_fifloader.py @@ -129,6 +129,11 @@ def test_generate_job_templates(): assert len(aboots) == 4 assert {t['machine_name'] for t in aboots} == {'ppc64le', '64bit'} + # test the recursion check + pgroups['fedora-server-1arch']['fedora-server-2arch'] = 0 + with pytest.raises(SystemExit, match=r"^Infinite recursion.*"): + templates = fifloader.generate_job_templates(products, profiles, pgroups, testsuites) + def test_reverse_qol(): """Test for reverse_qol.""" (machines, flavors, products, _, _, testsuites, _) = _get_merged()