import importlib.util import json import os import unittest import osbuild class TestDescriptions(unittest.TestCase): def test_canonical(self): """Degenerate case. Make sure we always return the same canonical description when passing empty or null values.""" cases = [ {}, { "assembler": None }, { "stages": [] }, { "build": {} }, { "build": None } ] for pipeline in cases: with self.subTest(pipeline): self.assertEqual(osbuild.load(pipeline, {}).description(), {}) def test_stage(self): name = "org.osbuild.test" options = { "one": 1 } cases = [ (osbuild.Stage(name, {}, None, None, {}), {"name": name}), (osbuild.Stage(name, {}, None, None, None), {"name": name}), (osbuild.Stage(name, {}, None, None, options), {"name": name, "options": options}), ] for stage, description in cases: with self.subTest(description): self.assertEqual(stage.description(), description) def test_assembler(self): name = "org.osbuild.test" options = { "one": 1 } cases = [ (osbuild.Assembler(name, None, None, {}), {"name": name}), (osbuild.Assembler(name, None, None, None), {"name": name}), (osbuild.Assembler(name, None, None, options), {"name": name, "options": options}), ] for assembler, description in cases: with self.subTest(description): self.assertEqual(assembler.description(), description) def test_pipeline(self): build = osbuild.Pipeline("org.osbuild.test") build.add_stage("org.osbuild.test", {}, { "one": 1 }) pipeline = osbuild.Pipeline("org.osbuild.test", build) pipeline.add_stage("org.osbuild.test", {}, { "one": 2 }) pipeline.set_assembler("org.osbuild.test") self.assertEqual(pipeline.description(), { "build": { "pipeline": { "stages": [ { "name": "org.osbuild.test", "options": { "one": 1 } } ] }, "runner": "org.osbuild.test" }, "stages": [ { "name": "org.osbuild.test", "options": { "one": 2 } } ], "assembler": { "name": "org.osbuild.test" } }) def test_stageinfo(self): def list_stages(base): return [(base, f) for f in os.listdir(base) if f.startswith("org.osbuild")] def load_module(base, name): loader = importlib.machinery.SourceFileLoader(name, f"{base}/{name}") spec = importlib.util.spec_from_loader(loader.name, loader) mod = importlib.util.module_from_spec(spec) loader.exec_module(mod) return mod stages = list_stages("stages") stages += list_stages("assemblers") for stage in stages: base, name = stage m = load_module(base, name) try: json.loads("{" + m.STAGE_OPTS + "}") except json.decoder.JSONDecodeError as e: msg = f"Stage '{base}/{name}' has invalid STAGE_OPTS\n\t" + str(e) self.fail(msg) if __name__ == "__main__": unittest.main()