From 078dadc4d0067a9df950e33e05c8c9c4c3a2dcdc Mon Sep 17 00:00:00 2001 From: Axel Heider Date: Thu, 1 Feb 2024 02:30:49 +0100 Subject: [PATCH 01/15] cleanup Bamboo reference in comments Signed-off-by: Axel Heider --- seL4-platforms/builds.py | 8 ++++++++ sel4test-hw/build.py | 4 ++-- sel4test-sim/builds.yml | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/seL4-platforms/builds.py b/seL4-platforms/builds.py index 4f7aa2fa..f7df3920 100644 --- a/seL4-platforms/builds.py +++ b/seL4-platforms/builds.py @@ -83,10 +83,18 @@ def update_settings(self): if p.arch != "x86": self.settings[p.cmake_toolchain_setting(m)] = "TRUE" self.settings["PLATFORM"] = p.get_platform(m) + # somewhat misnamed now; sets test output to parsable xml: + # See sel4test/settings.cmake, if Sel4testAllowSettingsOverride is not + # set then BAMBOO controls the setting for LibSel4TestPrintXML self.settings["BAMBOO"] = "TRUE" + self.files = p.image_names(m, self.image_base_name) + if self.req == 'sim': + # See sel4test/settings.cmake, if Sel4testAllowSettingsOverride is + # bot set then SIMULATION controls the settings for + # Sel4testSimulation and Sel4testHaveCache. self.settings["SIMULATION"] = "TRUE" def get_platform(self) -> Platform: diff --git a/sel4test-hw/build.py b/sel4test-hw/build.py index 4682b4ac..3cf2d480 100644 --- a/sel4test-hw/build.py +++ b/sel4test-hw/build.py @@ -57,7 +57,7 @@ def build_filter(build: Build) -> bool: return False if plat.arch == 'arm': - # Bamboo says: don't build release for hikey when in aarch64 arm_hyp mode + # ToDo: why is release for hikey in aarch64 arm_hyp mode is not supported if build.is_hyp() and build.get_mode() == 64 and build.is_release() and \ plat.name == 'HIKEY': return False @@ -85,7 +85,7 @@ def build_filter(build: Build) -> bool: return False if plat.arch == 'x86': - # Bamboo config says no VTX for SMP or verification + # ToDo: explant why we don't do VTX for SMP or verification if build.is_hyp() and (build.is_smp() or build.is_verification()): return False diff --git a/sel4test-sim/builds.yml b/sel4test-sim/builds.yml index 762a7a6d..d5dba89f 100644 --- a/sel4test-sim/builds.yml +++ b/sel4test-sim/builds.yml @@ -46,7 +46,7 @@ build-filter: arch: [arm, x86] - has_simulation: true arch: [riscv] - # Bamboo has no "release" simulation for RISCV, and it doesn't seem to work either: + # "release" simulation for RISCV does not work debug: [debug] From 300c1190d2ead793d7738248c73c1c1f1f708bf0 Mon Sep 17 00:00:00 2001 From: Axel Heider Date: Fri, 12 Apr 2024 17:41:38 +0200 Subject: [PATCH 02/15] python: simplify flow Signed-off-by: Axel Heider --- seL4-platforms/builds.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/seL4-platforms/builds.py b/seL4-platforms/builds.py index f7df3920..796a1709 100644 --- a/seL4-platforms/builds.py +++ b/seL4-platforms/builds.py @@ -739,11 +739,10 @@ def build_for_variant(base_build: Build, variant, filter_fun=lambda x: True) -> build.name = build.name + "_" + variant_name(variant) mode = var_dict.get("mode") or build.get_mode() - if mode in build.get_platform().modes: - build.mode = mode - else: + if mode not in build.get_platform().modes: return None + build.mode = mode # build.mode is now unique, more settings could apply build.update_settings() From 7329b7ae2baa10c046de55d9644dc39602c3a2f4 Mon Sep 17 00:00:00 2001 From: Axel Heider Date: Wed, 10 Apr 2024 17:35:48 +0200 Subject: [PATCH 03/15] python: drop default for image_base_name Thus must be set by projects. Signed-off-by: Axel Heider --- seL4-platforms/builds.py | 4 +++- sel4test-hw/builds.yml | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/seL4-platforms/builds.py b/seL4-platforms/builds.py index 796a1709..ff909c0a 100644 --- a/seL4-platforms/builds.py +++ b/seL4-platforms/builds.py @@ -62,7 +62,7 @@ def __init__(self, entries: dict, default={}): self.settings = {} self.timeout = 900 self.no_hw_test = False - self.image_base_name = "sel4test-driver" + self.image_base_name = None [self.name] = entries.keys() attribs = copy.deepcopy(default) # this potentially overwrites the default settings dict, we restore it later @@ -200,6 +200,8 @@ def is_domains(self) -> bool: return self.settings.get('DOMAINS') is not None def validate(self): + if not self.image_base_name: + raise ValidationException("Build: no image base name") if not self.get_mode(): raise ValidationException("Build: no unique mode") if not self.get_platform(): diff --git a/sel4test-hw/builds.yml b/sel4test-hw/builds.yml index 1acac464..ea601201 100644 --- a/sel4test-hw/builds.yml +++ b/sel4test-hw/builds.yml @@ -5,6 +5,7 @@ --- default: + image_base_name: 'sel4test-driver' success: '' # see seltest-sim/builds.yml for full schema example From 174ab8ce3d5bf031c372efc4eaaacc2104443d40 Mon Sep 17 00:00:00 2001 From: Axel Heider Date: Thu, 1 Feb 2024 02:29:49 +0100 Subject: [PATCH 04/15] clarify CMake unused argument issue Signed-off-by: Axel Heider --- camkes-test/build.py | 5 ++++- camkes-vm/build.py | 10 ++++++---- rump-hello/build.py | 4 +++- sel4bench/build.py | 7 ++++--- webserver/build.py | 5 ++++- 5 files changed, 21 insertions(+), 10 deletions(-) diff --git a/camkes-test/build.py b/camkes-test/build.py index 8f0346fc..9d83ca07 100644 --- a/camkes-test/build.py +++ b/camkes-test/build.py @@ -48,12 +48,15 @@ def run_build(manifest_dir: str, build: Union[Build, SimBuild]): app = apps[build.app] build.files = build.get_platform().image_names(build.get_mode(), "capdl-loader") build.settings['CAMKES_APP'] = build.app - del build.settings['BAMBOO'] # not used in this test, avoid warning if app.get('has_cakeml'): build.settings['CAKEMLDIR'] = '/cakeml' build.settings['CAKEML_BIN'] = f"/cake-x64-{build.get_mode()}/cake" + # remove parameters from setting that CMake does not use and thus would + # raise a nasty warning + del build.settings['BAMBOO'] + script = [ ["../init-build.sh"] + build.settings_args(), ["ninja"], diff --git a/camkes-vm/build.py b/camkes-vm/build.py index d7d18347..85b107f2 100644 --- a/camkes-vm/build.py +++ b/camkes-vm/build.py @@ -28,15 +28,17 @@ def run_build(manifest_dir: str, build: Build): build.files = plat.image_names(build.get_mode(), "capdl-loader") build.settings['CAMKES_VM_APP'] = build.app or build.name - del build.settings['BAMBOO'] # not used in this test, avoid warning - - if plat.arch == 'x86': - del build.settings['PLATFORM'] # not used for x86 in this test, avoid warning # if vm_platform is set, the init-build.sh script expects a different platform name. if build.vm_platform: build.settings['PLATFORM'] = build.vm_platform + # remove parameters from setting that CMake does not use and thus would + # raise a nasty warning + del build.settings['BAMBOO'] + if plat.arch == 'x86': + del build.settings['PLATFORM'] + script = [ ["../init-build.sh"] + build.settings_args(), ["ninja"], diff --git a/rump-hello/build.py b/rump-hello/build.py index c4c78b21..1bf2940b 100644 --- a/rump-hello/build.py +++ b/rump-hello/build.py @@ -18,7 +18,9 @@ def adjust_build(build: Build): build.files = build.get_platform().image_names(build.get_mode(), "roottask") - del build.settings['BAMBOO'] # not used in this test, avoid warning + # remove parameters from setting that CMake does not use and thus would + # raise a nasty warning + del build.settings['BAMBOO'] def run_build(manifest_dir: str, build: Build): diff --git a/sel4bench/build.py b/sel4bench/build.py index aac89d94..a4a092eb 100644 --- a/sel4bench/build.py +++ b/sel4bench/build.py @@ -25,14 +25,15 @@ def adjust_build_settings(build: Build): - if 'BAMBOO' in build.settings: - del build.settings['BAMBOO'] # not used in this build, avoid warning - # see discussion on https://github.com/seL4/sel4bench/pull/20 for hifive exclusion if build.is_smp() or build.get_platform().name == 'HIFIVE': build.settings['HARDWARE'] = 'FALSE' build.settings['FAULT'] = 'FALSE' + # remove parameters from setting that CMake does not use and thus would + # raise a nasty warning + del build.settings['BAMBOO'] + def hw_build(manifest_dir: str, build: Build): """Do one hardware build.""" diff --git a/webserver/build.py b/webserver/build.py index 946b7906..b9a60b55 100644 --- a/webserver/build.py +++ b/webserver/build.py @@ -27,7 +27,10 @@ def run_build(manifest_dir: str, build: Build): plat = build.get_platform() build.files = plat.image_names(build.get_mode(), "capdl-loader") - del build.settings['BAMBOO'] # not used in this test, avoid warning + + # remove parameters from setting that CMake does not use and thus would + # raise a nasty warning + del build.settings['BAMBOO'] script = [ ["../init-build.sh"] + build.settings_args(), From 2ef09978a7098a55a1328a37c407abe3c6737a4c Mon Sep 17 00:00:00 2001 From: Axel Heider Date: Sun, 28 Jan 2024 18:28:59 +0100 Subject: [PATCH 05/15] python: reorder imports Signed-off-by: Axel Heider --- camkes-test/build.py | 13 ++++++------- camkes-vm/build.py | 6 +++--- cparser-run/build.py | 6 +++--- march-of-platform/march.py | 3 ++- rump-hello/build.py | 6 +++--- seL4-platforms/builds.py | 13 +++++++------ seL4-platforms/platforms.py | 5 +++-- sel4bench/build.py | 15 +++++++-------- sel4test-hw/build.py | 9 ++++----- sel4test-sim/build.py | 6 +++--- tutorials/build.py | 8 ++++---- webserver/build.py | 6 +++--- 12 files changed, 48 insertions(+), 48 deletions(-) diff --git a/camkes-test/build.py b/camkes-test/build.py index 9d83ca07..5c6ef25f 100644 --- a/camkes-test/build.py +++ b/camkes-test/build.py @@ -8,15 +8,14 @@ Expects seL4-platforms/ to be co-located or otherwise in the PYTHONPATH. """ -from builds import Build, run_build_script, run_builds, load_builds, release_mq_locks, SKIP -from pprint import pprint -from typing import List, Union - -import json -import os import sys +import os +import json +from builds import Build, run_build_script, run_builds, load_builds, release_mq_locks, SKIP from platforms import load_yaml, gh_output +from pprint import pprint + # See also builds.yml for how builds are split up in this test. We use the build # matrix and filtering for the hardware builds, and an explicit list for the @@ -115,7 +114,7 @@ def sim_build_filter(build: SimBuild): return (not name or build.name == name) and (not plat or plat == 'sim') -def to_json(builds: List[Build]) -> str: +def to_json(builds: list[Build]) -> str: """Return a GitHub build matrix as GitHub output assignment.""" matrix = {"include": [{"name": b.name, "platform": b.get_platform().name} for b in builds]} diff --git a/camkes-vm/build.py b/camkes-vm/build.py index 85b107f2..182d6af0 100644 --- a/camkes-vm/build.py +++ b/camkes-vm/build.py @@ -8,12 +8,12 @@ Expects seL4-platforms/ to be co-located or otherwise in the PYTHONPATH. """ +import sys +import os + from builds import Build, run_build_script, run_builds, load_builds, release_mq_locks, SKIP, sim_script from pprint import pprint -import os -import sys - # See also builds.yml for how builds are split up in this test. We use the build # matrix and filtering for the hardware builds, and an explicit list for the diff --git a/cparser-run/build.py b/cparser-run/build.py index 26a7e392..31171e3a 100644 --- a/cparser-run/build.py +++ b/cparser-run/build.py @@ -8,12 +8,12 @@ Expects seL4-platforms/ to be co-located or otherwise in the PYTHONPATH. """ +import sys +import os + from builds import run_build_script, run_builds, load_builds from pprint import pprint -import os -import sys - def run_cparser(manifest_dir: str, build): """Single run of the C Parser test, for one build definition""" diff --git a/march-of-platform/march.py b/march-of-platform/march.py index fbb64a6a..6d442f4c 100755 --- a/march-of-platform/march.py +++ b/march-of-platform/march.py @@ -2,8 +2,9 @@ # # SPDX-License-Identifier: BSD-2-Clause -from platforms import platforms, gh_output import sys +from platforms import platforms, gh_output + if __name__ == '__main__': if len(sys.argv) == 2: diff --git a/rump-hello/build.py b/rump-hello/build.py index 1bf2940b..3b326256 100644 --- a/rump-hello/build.py +++ b/rump-hello/build.py @@ -8,13 +8,13 @@ Expects seL4-platforms/ to be co-located or otherwise in the PYTHONPATH. """ +import sys +import os + from builds import Build, run_build_script, run_builds, load_builds, sim_script from builds import release_mq_locks, SKIP from pprint import pprint -import os -import sys - def adjust_build(build: Build): build.files = build.get_platform().image_names(build.get_mode(), "roottask") diff --git a/seL4-platforms/builds.py b/seL4-platforms/builds.py index ff909c0a..4da88f24 100644 --- a/seL4-platforms/builds.py +++ b/seL4-platforms/builds.py @@ -12,18 +12,19 @@ `default_junit_results` for a standard place to leave a jUnit summary file. """ +import sys +import os +import subprocess +import shutil +import copy +import time + from junitparser.junitparser import Failure, Error from platforms import ValidationException, Platform, platforms, load_yaml, mcs_unsupported from typing import Optional, List, Tuple, Union from junitparser import JUnitXml -import copy -import time -import os -import shutil -import subprocess -import sys # exported names: __all__ = [ diff --git a/seL4-platforms/platforms.py b/seL4-platforms/platforms.py index 31a231d8..27a66ec2 100644 --- a/seL4-platforms/platforms.py +++ b/seL4-platforms/platforms.py @@ -15,10 +15,11 @@ """ from io import StringIO +import os +import yaml from typing import Optional from pprint import pprint -import yaml -import os + # exported names: __all__ = [ diff --git a/sel4bench/build.py b/sel4bench/build.py index a4a092eb..bf38a588 100644 --- a/sel4bench/build.py +++ b/sel4bench/build.py @@ -8,6 +8,13 @@ Expects seL4-platforms/ to be co-located or otherwise in the PYTHONPATH. """ +import sys +import os +import subprocess +import json +import time +from datetime import datetime + from builds import Build, Run, run_build_script, run_builds, load_builds, load_yaml from builds import release_mq_locks, filtered, get_env_filters, printc, ANSI_RED from builds import SKIP, SUCCESS, REPEAT, FAILURE @@ -15,14 +22,6 @@ from pprint import pprint from typing import List, Optional -from datetime import datetime - -import json -import os -import sys -import subprocess -import time - def adjust_build_settings(build: Build): # see discussion on https://github.com/seL4/sel4bench/pull/20 for hifive exclusion diff --git a/sel4test-hw/build.py b/sel4test-hw/build.py index 3cf2d480..4502592c 100644 --- a/sel4test-hw/build.py +++ b/sel4test-hw/build.py @@ -8,17 +8,16 @@ Expects seL4-platforms/ to be co-located or otherwise in the PYTHONPATH. """ +import sys +import os +import json + from builds import Build, run_build_script, run_builds, load_builds, junit_results from builds import release_mq_locks, SKIP from platforms import Platform, gh_output - from pprint import pprint from typing import List -import json -import os -import sys - def hw_build(manifest_dir: str, build: Build): """Run one hardware build.""" diff --git a/sel4test-sim/build.py b/sel4test-sim/build.py index 2037bb65..ff6c35dd 100644 --- a/sel4test-sim/build.py +++ b/sel4test-sim/build.py @@ -8,12 +8,12 @@ Expects seL4-platforms/ to be co-located or otherwise in the PYTHONPATH. """ +import sys +import os + from builds import Build, run_build_script, run_builds, load_builds, junit_results from pprint import pprint -import os -import sys - def run_simulation(manifest_dir: str, build: Build): """Run one simulation build and test.""" diff --git a/tutorials/build.py b/tutorials/build.py index 62612267..c6ccb6c8 100644 --- a/tutorials/build.py +++ b/tutorials/build.py @@ -8,14 +8,14 @@ Expects seL4-platforms/ to be co-located or otherwise in the PYTHONPATH. """ +import sys +import os +import json + from builds import Build, load_builds, run_build_script, run_builds, junit_results from platforms import load_yaml, gh_output from pprint import pprint -import json -import os -import sys - def run_simulation(manifest_dir: str, build: Build): """Run one tutorial test.""" diff --git a/webserver/build.py b/webserver/build.py index b9a60b55..bcea060f 100644 --- a/webserver/build.py +++ b/webserver/build.py @@ -8,12 +8,12 @@ Expects seL4-platforms/ to be co-located or otherwise in the PYTHONPATH. """ +import sys +import os + from builds import Build, run_build_script, run_builds, load_builds, release_mq_locks, SKIP, sim_script from pprint import pprint -import os -import sys - # See also builds.yml for how builds are split up in this test. We use the build # matrix and filtering for the hardware builds, and an explicit list for the From 0ccaa86f9e48ddc20b0c72aa696f6e0d65eeaa16 Mon Sep 17 00:00:00 2001 From: Axel Heider Date: Mon, 29 Jan 2024 02:11:19 +0100 Subject: [PATCH 06/15] python: improve type hints usage "annotations" exists in __future__ since 3.7.0b1 and was planned to become mandatory in 3.10. But this has been postponed. Signed-off-by: Axel Heider --- camkes-test/build.py | 10 ++++---- camkes-vm/build.py | 4 +-- cparser-run/build.py | 2 +- l4v-deploy/common.py | 4 +-- rump-hello/build.py | 4 +-- seL4-platforms/builds.py | 50 ++++++++++++++++++------------------- seL4-platforms/platforms.py | 6 ++--- sel4bench/build.py | 13 +++++----- sel4test-hw/build.py | 7 +++--- sel4test-sim/build.py | 2 +- tutorials/build.py | 2 +- webserver/build.py | 4 +-- 12 files changed, 53 insertions(+), 55 deletions(-) diff --git a/camkes-test/build.py b/camkes-test/build.py index 5c6ef25f..a6a35409 100644 --- a/camkes-test/build.py +++ b/camkes-test/build.py @@ -32,7 +32,7 @@ def __init__(self, sim: dict): self.name = sim['match'] + post self.__dict__.update(**sim) - def __repr__(self): + def __repr__(self) -> str: return f"SimBuild('{self.name}', " '{' \ f" 'match': '{self.match}'," \ f" 'exclude': '{self.exclude}'," \ @@ -40,7 +40,7 @@ def __repr__(self): ' })' -def run_build(manifest_dir: str, build: Union[Build, SimBuild]): +def run_build(manifest_dir: str, build: Build | SimBuild) -> int: """Run one CAmkES test. Can be either Build or SimBuild.""" if isinstance(build, Build): @@ -78,7 +78,7 @@ def run_build(manifest_dir: str, build: Union[Build, SimBuild]): return run_build_script(manifest_dir, build, script) -def hw_run(manifest_dir: str, build: Build): +def hw_run(manifest_dir: str, build: Build) -> int: """Run one hardware test.""" if build.is_disabled(): @@ -91,7 +91,7 @@ def hw_run(manifest_dir: str, build: Build): return run_build_script(manifest_dir, build, script, final_script=final) -def build_filter(build: Build): +def build_filter(build: Build) -> bool: if not build.app: return False @@ -108,7 +108,7 @@ def build_filter(build: Build): return True -def sim_build_filter(build: SimBuild): +def sim_build_filter(build: SimBuild) -> bool: name = os.environ.get('INPUT_NAME') plat = os.environ.get('INPUT_PLATFORM') return (not name or build.name == name) and (not plat or plat == 'sim') diff --git a/camkes-vm/build.py b/camkes-vm/build.py index 182d6af0..05002097 100644 --- a/camkes-vm/build.py +++ b/camkes-vm/build.py @@ -21,7 +21,7 @@ # The only thing this really has in common with a "Build" is the "name" field. -def run_build(manifest_dir: str, build: Build): +def run_build(manifest_dir: str, build: Build) -> int: """Run one CAmkES VM test.""" plat = build.get_platform() @@ -51,7 +51,7 @@ def run_build(manifest_dir: str, build: Build): return run_build_script(manifest_dir, build, script) -def hw_run(manifest_dir: str, build: Build): +def hw_run(manifest_dir: str, build: Build) -> int: """Run one hardware test.""" if build.is_disabled(): diff --git a/cparser-run/build.py b/cparser-run/build.py index 31171e3a..11e3cda2 100644 --- a/cparser-run/build.py +++ b/cparser-run/build.py @@ -15,7 +15,7 @@ from pprint import pprint -def run_cparser(manifest_dir: str, build): +def run_cparser(manifest_dir: str, build) -> int: """Single run of the C Parser test, for one build definition""" script = [ diff --git a/l4v-deploy/common.py b/l4v-deploy/common.py index d94f3f85..a0a1b3f7 100644 --- a/l4v-deploy/common.py +++ b/l4v-deploy/common.py @@ -19,12 +19,12 @@ def loud_command(*args, **kwargs): return run_command(*args, **kwargs) -def indent(s, indent=' '): +def indent(s, indent=' ') -> str: '''Indent all lines in a string''' return '\n'.join(indent + line for line in s.splitlines()) -def format_commit_message(msg): +def format_commit_message(msg: str) -> str: '''Add a standard header and footer to a commit message''' msg = "[CI] " + msg return msg diff --git a/rump-hello/build.py b/rump-hello/build.py index 3b326256..140827d6 100644 --- a/rump-hello/build.py +++ b/rump-hello/build.py @@ -23,7 +23,7 @@ def adjust_build(build: Build): del build.settings['BAMBOO'] -def run_build(manifest_dir: str, build: Build): +def run_build(manifest_dir: str, build: Build) -> int: """Run one rumprun-hello test.""" adjust_build(build) @@ -41,7 +41,7 @@ def run_build(manifest_dir: str, build: Build): return run_build_script(manifest_dir, build, script) -def hw_run(manifest_dir: str, build: Build): +def hw_run(manifest_dir: str, build: Build) -> int: """Run one hardware test.""" adjust_build(build) diff --git a/seL4-platforms/builds.py b/seL4-platforms/builds.py index 4da88f24..40f6d212 100644 --- a/seL4-platforms/builds.py +++ b/seL4-platforms/builds.py @@ -12,6 +12,7 @@ `default_junit_results` for a standard place to leave a jUnit summary file. """ +from typing import Union import sys import os import subprocess @@ -22,7 +23,6 @@ from junitparser.junitparser import Failure, Error from platforms import ValidationException, Platform, platforms, load_yaml, mcs_unsupported -from typing import Optional, List, Tuple, Union from junitparser import JUnitXml @@ -102,7 +102,7 @@ def get_platform(self) -> Platform: """Return the Platform object for this build definition.""" return platforms[self.platform] - def get_mode(self) -> Optional[int]: + def get_mode(self) -> int: """Return the mode (32/64) for this build; taken from platform if not defined""" if not self.mode and self.get_platform().get_mode(): return self.get_platform().get_mode() @@ -228,7 +228,7 @@ def __repr__(self) -> str: def is_disabled(self) -> bool: return self.no_hw_test or self.get_platform().no_hw_test - def get_req(self) -> List[str]: + def get_req(self) -> list[str]: req = self.req or self.get_platform().req if not req or req == []: return [] @@ -252,13 +252,13 @@ class Run: Build class. So far we only vary machine requirements (req) and name in a Run. """ - def __init__(self, build: Build, suffix: Optional[str] = None, - req: Optional[str] = None): + def __init__(self, build: Build, suffix: str = None, + req: str = None): self.build = build self.name = build.name + suffix if suffix else build.name self.req = req - def get_req(self) -> List[str]: + def get_req(self) -> list[str]: return self.req or self.build.get_req() def hw_run(self, log): @@ -358,7 +358,7 @@ def hw_run(self, log): ] -def repeat_on_boot_failure(log: Optional[List[str]]) -> int: +def repeat_on_boot_failure(log: list[str]) -> int: """Try to repeat the test run if the board failed to boot.""" if log: @@ -374,7 +374,7 @@ def repeat_on_boot_failure(log: Optional[List[str]]) -> int: return SUCCESS, None -def release_mq_locks(runs: List[Union[Run, Build]]): +def release_mq_locks(runs: list[Union[Run, Build]]): """Release locks from this job; runs the commands instead of returning a list.""" def run(command): @@ -415,7 +415,7 @@ def get_machine(req): return req[job_index % len(req)] -def job_key(): +def job_key() -> str: return os.environ.get('GITHUB_REPOSITORY') + "-" + \ os.environ.get('GITHUB_WORKFLOW') + "-" + \ os.environ.get('GITHUB_RUN_ID') + "-" + \ @@ -425,15 +425,15 @@ def job_key(): def mq_run(success_str: str, machine: str, - files: List[str], + files: list[str], retries: int = -1, lock_timeout: int = 8, completion_timeout: int = -1, - log: Optional[str] = None, + log: str = None, lock_held=False, keep_alive=False, - key: Optional[str] = None, - error_str: Optional[str] = None): + key: str = None, + error_str: str = None): """Machine queue mq.sh run command with arguments. Expects success marker, machine name, and boot image file(s). @@ -462,22 +462,22 @@ def mq_run(success_str: str, return command -def mq_lock(machine: str) -> List[str]: +def mq_lock(machine: str) -> list[str]: """Get lock for a machine. Allow lock to be reclaimed after 30min.""" return ['time', 'mq.sh', 'sem', '-wait', machine, '-k', job_key(), '-T', '1800'] -def mq_release(machine: str) -> List[str]: +def mq_release(machine: str) -> list[str]: """Release lock on a machine.""" return ['mq.sh', 'sem', '-signal', machine, '-k', job_key()] -def mq_cancel(machine: str) -> List[str]: +def mq_cancel(machine: str) -> list[str]: """Cancel processes waiting on lock for a machine.""" return ['mq.sh', 'sem', '-cancel', machine, '-k', job_key()] -def mq_print_lock(machine: str) -> List[str]: +def mq_print_lock(machine: str) -> list[str]: """Print lock status for machine.""" return ['mq.sh', 'sem', '-info', machine] @@ -496,8 +496,8 @@ def success_from_bool(success: bool) -> int: return FAILURE -def run_cmd(cmd, run: Union[Run, Build], prev_output: Optional[str] = None) -> int: - """If the command is a List[str], echo + run command with arguments, otherwise +def run_cmd(cmd, run: Union[Run, Build], prev_output: str = None) -> int: + """If the command is a list[str], echo + run command with arguments, otherwise expect a function, and run that function on the supplied Run plus outputs from previous command.""" @@ -526,7 +526,7 @@ def printc(color: str, content: str): print(color + content + ANSI_RESET) -def summarise_junit(file_path: str) -> Tuple[int, List[str]]: +def summarise_junit(file_path: str) -> tuple[int, list[str]]: """Parse jUnit output and show a summary. Returns True if there were no failures or errors, raises exception @@ -727,7 +727,7 @@ def build_for_platform(platform, default={}): return Build({platform: the_build}) -def build_for_variant(base_build: Build, variant, filter_fun=lambda x: True) -> Optional[Build]: +def build_for_variant(base_build: Build, variant, filter_fun=lambda x: True) -> Build: """Make a build definition from a supplied base build and a build variant. Optionally takes a filter/validation function to reject specific build @@ -786,7 +786,7 @@ def build_for_variant(base_build: Build, variant, filter_fun=lambda x: True) -> def get_env_filters() -> list: """Process input env variables and return a build filter (list of dict)""" - def get(var: str) -> Optional[str]: + def get(var: str) -> Union[str, None]: return os.environ.get('INPUT_' + var.upper()) def to_list(string: str) -> list: @@ -800,7 +800,7 @@ def to_list(string: str) -> list: return [filter] -def filtered(build: Build, build_filters: dict) -> Optional[Build]: +def filtered(build: Build, build_filters: dict) -> Build: """Return build if build matches filter criteria, otherwise None.""" def match_dict(build: Build, f): @@ -868,8 +868,8 @@ def match_dict(build: Build, f): return None -def load_builds(file_name: Optional[str], filter_fun=lambda x: True, - yml: Optional[dict] = None) -> List[Build]: +def load_builds(file_name: str, filter_fun=lambda x: True, + yml: dict = None) -> list[Build]: """Load a list of build definitions from yaml. Use provided yaml dict, or if None, load from file. One of file_name, yml diff --git a/seL4-platforms/platforms.py b/seL4-platforms/platforms.py index 27a66ec2..f2ec7f8e 100644 --- a/seL4-platforms/platforms.py +++ b/seL4-platforms/platforms.py @@ -14,10 +14,10 @@ modes, platforms, a list of unsupported platforms, and a list of named machines. """ +from typing import Union from io import StringIO import os import yaml -from typing import Optional from pprint import pprint @@ -140,7 +140,7 @@ def can_aarch_hyp_64(self) -> bool: """Does the platform support ARM_HYP in mode 64?""" return 64 in self.aarch_hyp - def get_mode(self) -> Optional[int]: + def get_mode(self) -> Union[int, None]: """Return mode (32/64) of this platform if unique, otherwise None""" if len(self.modes) == 1: return self.modes[0] @@ -195,7 +195,7 @@ def getISA(self, mode: int) -> str: return self.march.capitalize() -def load_yaml(file_name): +def load_yaml(file_name: str): """Load a yaml file""" with open(file_name, 'r') as file: return yaml.safe_load(file) diff --git a/sel4bench/build.py b/sel4bench/build.py index bf38a588..a3faa26c 100644 --- a/sel4bench/build.py +++ b/sel4bench/build.py @@ -20,7 +20,6 @@ from builds import SKIP, SUCCESS, REPEAT, FAILURE from pprint import pprint -from typing import List, Optional def adjust_build_settings(build: Build): @@ -34,7 +33,7 @@ def adjust_build_settings(build: Build): del build.settings['BAMBOO'] -def hw_build(manifest_dir: str, build: Build): +def hw_build(manifest_dir: str, build: Build) -> int: """Do one hardware build.""" adjust_build_settings(build) @@ -68,7 +67,7 @@ def extract_json(results: str, run: Run) -> int: return SUCCESS if res.returncode == 0 else REPEAT -def hw_run(manifest_dir: str, run: Run): +def hw_run(manifest_dir: str, run: Run) -> int: """Run one hardware test.""" if run.build.is_disabled(): @@ -118,7 +117,7 @@ def build_filter(build: Build) -> bool: return True -def make_runs(builds: List[Build]) -> List[Run]: +def make_runs(builds: list[Build]) -> list[Run]: """Split PC99 builds into runs for haswell3 and skylake, no changes to the rest""" # could filter more generically, but we're really only interested in REQ here, @@ -141,7 +140,7 @@ def make_runs(builds: List[Build]) -> List[Run]: return runs -def get_results(run: Run) -> List[float]: +def get_results(run: Run) -> list[float]: """Get the benchmark results from JSON for a specific run.""" with open(f"{run.name}.json") as f: @@ -185,7 +184,7 @@ def get_results(run: Run) -> List[float]: return [irq_invoke, irq_invoke_s, ipc_call, ipc_call_s, ipc_reply, ipc_reply_s, notify, notify_s] -def get_run(runs: List[Run], name: str) -> Optional[Run]: +def get_run(runs: list[Run], name: str) -> Run: """Get a run by name.""" for run in runs: @@ -196,7 +195,7 @@ def get_run(runs: List[Run], name: str) -> Optional[Run]: return None -def gen_web(runs: List[Run], yml, file_name: str): +def gen_web(runs: list[Run], yml, file_name: str): """Generate web page for benchmark results according to the set defined in builds.yml""" manifest_sha = os.getenv('INPUT_MANIFEST_SHA') diff --git a/sel4test-hw/build.py b/sel4test-hw/build.py index 4502592c..ec204251 100644 --- a/sel4test-hw/build.py +++ b/sel4test-hw/build.py @@ -16,10 +16,9 @@ from builds import release_mq_locks, SKIP from platforms import Platform, gh_output from pprint import pprint -from typing import List -def hw_build(manifest_dir: str, build: Build): +def hw_build(manifest_dir: str, build: Build) -> int: """Run one hardware build.""" if build.get_platform().name == "RPI4": @@ -37,7 +36,7 @@ def hw_build(manifest_dir: str, build: Build): return run_build_script(manifest_dir, build, script) -def hw_run(manifest_dir: str, build: Build): +def hw_run(manifest_dir: str, build: Build) -> int: """Run one hardware test.""" if build.is_disabled(): @@ -103,7 +102,7 @@ def build_filter(build: Build) -> bool: def to_json(builds: List[Build]) -> str: """Return a GitHub build matrix per enabled hardware platform as GitHub output assignment.""" - def run_for_plat(plat: Platform) -> List[dict]: + def run_for_plat(plat: Platform) -> list[dict]: if plat.no_hw_test or plat.no_hw_build: return [] diff --git a/sel4test-sim/build.py b/sel4test-sim/build.py index ff6c35dd..8ff2034e 100644 --- a/sel4test-sim/build.py +++ b/sel4test-sim/build.py @@ -15,7 +15,7 @@ from pprint import pprint -def run_simulation(manifest_dir: str, build: Build): +def run_simulation(manifest_dir: str, build: Build) -> int: """Run one simulation build and test.""" expect = '"%s" {exit 0} timeout {exit 1}' % build.success diff --git a/tutorials/build.py b/tutorials/build.py index c6ccb6c8..041c2153 100644 --- a/tutorials/build.py +++ b/tutorials/build.py @@ -17,7 +17,7 @@ from pprint import pprint -def run_simulation(manifest_dir: str, build: Build): +def run_simulation(manifest_dir: str, build: Build) -> int: """Run one tutorial test.""" script = [ diff --git a/webserver/build.py b/webserver/build.py index bcea060f..1e0eef44 100644 --- a/webserver/build.py +++ b/webserver/build.py @@ -21,7 +21,7 @@ # The only thing this really has in common with a "Build" is the "name" field. -def run_build(manifest_dir: str, build: Build): +def run_build(manifest_dir: str, build: Build) -> int: """Run one seL4 web server app test.""" plat = build.get_platform() @@ -44,7 +44,7 @@ def run_build(manifest_dir: str, build: Build): return run_build_script(manifest_dir, build, script) -def hw_run(manifest_dir: str, build: Build): +def hw_run(manifest_dir: str, build: Build) -> int: """Run one hardware test.""" if build.is_disabled(): From 48df20000ab1c89ec1e538fdc19f015d31b93f18 Mon Sep 17 00:00:00 2001 From: Axel Heider Date: Mon, 15 Jan 2024 12:52:42 +0100 Subject: [PATCH 07/15] python: create main() function Signed-off-by: Axel Heider --- camkes-test/build.py | 29 ++++++++++++++++++----------- camkes-vm/build.py | 24 +++++++++++++++--------- cparser-run/build.py | 15 ++++++++++----- march-of-platform/march.py | 24 ++++++++++++++---------- rump-hello/build.py | 22 +++++++++++++--------- seL4-platforms/platforms.py | 8 +++++++- sel4bench/build.py | 26 +++++++++++++++----------- sel4test-hw/build.py | 24 ++++++++++++++---------- sel4test-sim/build.py | 14 +++++++++----- tutorials/build.py | 20 ++++++++++++-------- webserver/build.py | 24 +++++++++++++++--------- 11 files changed, 142 insertions(+), 88 deletions(-) diff --git a/camkes-test/build.py b/camkes-test/build.py index a6a35409..13cb2083 100644 --- a/camkes-test/build.py +++ b/camkes-test/build.py @@ -121,24 +121,31 @@ def to_json(builds: list[Build]) -> str: return "matrix=" + json.dumps(matrix) -# If called as main, run all builds from builds.yml -if __name__ == '__main__': +def main(argv: list) -> int: yml = load_yaml(os.path.dirname(__file__) + "/builds.yml") apps = yml['apps'] sim_builds = [SimBuild(s) for s in yml['sim']] hw_builds = load_builds(None, build_filter, yml) builds = [b for b in sim_builds if sim_build_filter(b)] + hw_builds - if len(sys.argv) > 1 and sys.argv[1] == '--dump': + if len(argv) > 1 and argv[1] == '--dump': pprint(builds) - sys.exit(0) - elif len(sys.argv) > 1 and sys.argv[1] == '--matrix': + return 0 + + if len(argv) > 1 and argv[1] == '--matrix': gh_output(to_json(builds)) - sys.exit(0) - elif len(sys.argv) > 1 and sys.argv[1] == '--hw': - sys.exit(run_builds(builds, hw_run)) - elif len(sys.argv) > 1 and sys.argv[1] == '--post': + return 0 + + if len(argv) > 1 and argv[1] == '--hw': + return run_builds(builds, hw_run) + + if len(argv) > 1 and argv[1] == '--post': release_mq_locks(builds) - sys.exit(0) + return 0 - sys.exit(run_builds(builds, run_build)) + # by default, run all builds from builds.yml + return run_builds(builds, run_build) + + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/camkes-vm/build.py b/camkes-vm/build.py index 05002097..729166b2 100644 --- a/camkes-vm/build.py +++ b/camkes-vm/build.py @@ -66,17 +66,23 @@ def hw_run(manifest_dir: str, build: Build) -> int: return run_build_script(manifest_dir, build, script, final_script=final) -# If called as main, run all builds from builds.yml -if __name__ == '__main__': +def main(argv: list) -> int: builds = load_builds(os.path.dirname(__file__) + "/builds.yml") - if len(sys.argv) > 1 and sys.argv[1] == '--dump': + if len(argv) > 1 and argv[1] == '--dump': pprint(builds) - sys.exit(0) - elif len(sys.argv) > 1 and sys.argv[1] == '--hw': - sys.exit(run_builds(builds, hw_run)) - elif len(sys.argv) > 1 and sys.argv[1] == '--post': + return 0 + + if len(argv) > 1 and argv[1] == '--hw': + return run_builds(builds, hw_run) + + if len(argv) > 1 and argv[1] == '--post': release_mq_locks(builds) - sys.exit(0) + return 0 - sys.exit(run_builds(builds, run_build)) + # by default, run all builds from builds.yml + return run_builds(builds, run_build) + + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/cparser-run/build.py b/cparser-run/build.py index 11e3cda2..006975e9 100644 --- a/cparser-run/build.py +++ b/cparser-run/build.py @@ -28,12 +28,17 @@ def run_cparser(manifest_dir: str, build) -> int: return run_build_script(manifest_dir, build, script) -# If called as main, run all builds from builds.yml -if __name__ == '__main__': +def main(argv: list) -> int: + builds = load_builds(os.path.dirname(__file__) + "/builds.yml") - if len(sys.argv) > 1 and sys.argv[1] == '--dump': + if len(argv) > 1 and argv[1] == '--dump': pprint(builds) - sys.exit(0) + return 0 + + # by default, run all builds from builds.yml + return run_builds(builds, run_cparser) - sys.exit(run_builds(builds, run_cparser)) + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/march-of-platform/march.py b/march-of-platform/march.py index 6d442f4c..878447c7 100755 --- a/march-of-platform/march.py +++ b/march-of-platform/march.py @@ -6,14 +6,18 @@ from platforms import platforms, gh_output -if __name__ == '__main__': - if len(sys.argv) == 2: - plat = platforms.get(sys.argv[1].upper()) - if plat: - gh_output(f"march={plat.march}") - sys.exit(0) - else: - print(f"Unknown platform {sys.argv[1]}") - sys.exit(1) +def main(argv: list) -> int: + if len(argv) != 2: + return 1 + + plat = platforms.get(argv[1].upper()) + if plat: + gh_output(f"march={plat.march}") + return 0 + + print(f"Unknown platform {argv[1]}") + return 1 - sys.exit(1) + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/rump-hello/build.py b/rump-hello/build.py index 140827d6..c72badb7 100644 --- a/rump-hello/build.py +++ b/rump-hello/build.py @@ -55,19 +55,23 @@ def hw_run(manifest_dir: str, build: Build) -> int: return run_build_script(manifest_dir, build, script, final_script=final) -# If called as main, run all builds from builds.yml -if __name__ == '__main__': +def main(argv: list) -> int: builds = load_builds(os.path.dirname(__file__) + "/builds.yml") - if len(sys.argv) > 1 and sys.argv[1] == '--dump': + if len(argv) > 1 and argv[1] == '--dump': pprint(builds) - sys.exit(0) + return 0 - if len(sys.argv) > 1 and sys.argv[1] == '--hw': - sys.exit(run_builds(builds, hw_run)) + if len(argv) > 1 and argv[1] == '--hw': + return run_builds(builds, hw_run) - if len(sys.argv) > 1 and sys.argv[1] == '--post': + if len(argv) > 1 and argv[1] == '--post': release_mq_locks(builds) - sys.exit(0) + return 0 + + # by default, run all builds from builds.yml + return run_builds(builds, run_build) - sys.exit(run_builds(builds, run_build)) + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/seL4-platforms/platforms.py b/seL4-platforms/platforms.py index f2ec7f8e..762b12dd 100644 --- a/seL4-platforms/platforms.py +++ b/seL4-platforms/platforms.py @@ -228,8 +228,9 @@ def gh_output(assgn: str): if not platforms.get(p): print(f"Warning: unknown platform '{p}' in mcs_unsupported list") + # if called as main, dump info: -if __name__ == '__main__': +def main(argv: list) -> int: print("\n# Architectures:") pprint(all_architectures) @@ -251,3 +252,8 @@ def sup(p: Platform) -> str: print("\n# all sim:") pprint([p.name for p in platforms.values() if p.has_simulation]) + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/sel4bench/build.py b/sel4bench/build.py index a3faa26c..4c92488e 100644 --- a/sel4bench/build.py +++ b/sel4bench/build.py @@ -354,8 +354,7 @@ def gen_web(runs: list[Run], yml, file_name: str): f.write('.

') -# If called as main, run all builds from builds.yml -if __name__ == '__main__': +def main(argv: list) -> int: yml = load_yaml(os.path.dirname(__file__) + "/builds.yml") builds = load_builds(None, filter_fun=build_filter, yml=yml) @@ -366,19 +365,24 @@ def gen_web(runs: list[Run], yml, file_name: str): more_builds = [Build(b, default_build) for b in yml.get("more_builds", [])] builds.extend([b for b in more_builds if b and filtered(b, env_filters)]) - if len(sys.argv) > 1 and sys.argv[1] == '--dump': + if len(argv) > 1 and argv[1] == '--dump': pprint(builds) - sys.exit(0) + return 0 - if len(sys.argv) > 1 and sys.argv[1] == '--hw': - sys.exit(run_builds(make_runs(builds), hw_run)) + if len(argv) > 1 and argv[1] == '--hw': + return run_builds(make_runs(builds), hw_run) - if len(sys.argv) > 1 and sys.argv[1] == '--post': + if len(argv) > 1 and argv[1] == '--post': release_mq_locks(builds) - sys.exit(0) + return 0 - if len(sys.argv) > 1 and sys.argv[1] == '--web': + if len(argv) > 1 and argv[1] == '--web': gen_web(make_runs(builds), yml, "index.html") - sys.exit(0) + return 0 + + # by default, run all builds from builds.yml + return run_builds(builds, hw_build) - sys.exit(run_builds(builds, hw_build)) + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/sel4test-hw/build.py b/sel4test-hw/build.py index ec204251..8093dba9 100644 --- a/sel4test-hw/build.py +++ b/sel4test-hw/build.py @@ -134,23 +134,27 @@ def run_for_plat(plat: Platform) -> list[dict]: return "matrix=" + json.dumps(matrix) -# If called as main, run all builds from builds.yml -if __name__ == '__main__': +def main(argv: list) -> int: builds = load_builds(os.path.dirname(__file__) + "/builds.yml", filter_fun=build_filter) - if len(sys.argv) > 1 and sys.argv[1] == '--dump': + if len(argv) > 1 and argv[1] == '--dump': pprint(builds) - sys.exit(0) + return 0 - if len(sys.argv) > 1 and sys.argv[1] == '--matrix': + if len(argv) > 1 and argv[1] == '--matrix': gh_output(to_json(builds)) sys.exit(0) - if len(sys.argv) > 1 and sys.argv[1] == '--hw': - sys.exit(run_builds(builds, hw_run)) + if len(argv) > 1 and argv[1] == '--hw': + return run_builds(builds, hw_run)) - if len(sys.argv) > 1 and sys.argv[1] == '--post': + if len(argv) > 1 and argv[1] == '--post': release_mq_locks(builds) - sys.exit(0) + return 0 - sys.exit(run_builds(builds, hw_build)) + # by default, run all builds from builds.yml + return run_builds(builds, hw_build) + + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/sel4test-sim/build.py b/sel4test-sim/build.py index 8ff2034e..3eef63bf 100644 --- a/sel4test-sim/build.py +++ b/sel4test-sim/build.py @@ -30,12 +30,16 @@ def run_simulation(manifest_dir: str, build: Build) -> int: return run_build_script(manifest_dir, build, script, junit=True) -# If called as main, run all builds from builds.yml -if __name__ == '__main__': +def main(argv: list) -> int: builds = load_builds(os.path.dirname(__file__) + "/builds.yml") - if len(sys.argv) > 1 and sys.argv[1] == '--dump': + if len(argv) > 1 and argv[1] == '--dump': pprint(builds) - sys.exit(0) + return 0 + + # by default, run all builds from builds.yml + return run_builds(builds, run_simulation) - sys.exit(run_builds(builds, run_simulation)) + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/tutorials/build.py b/tutorials/build.py index 041c2153..2db68d08 100644 --- a/tutorials/build.py +++ b/tutorials/build.py @@ -43,18 +43,22 @@ def to_json(builds: list) -> str: return "matrix=" + json.dumps(matrix) -# If called as main, run all builds from builds.yml -if __name__ == '__main__': +def main(argv: list) -> int: yml = load_yaml(os.path.dirname(__file__) + "/builds.yml") disable_app_for = yml['disable_app_for'] - builds = load_builds(None, build_filter, yml) - if len(sys.argv) > 1 and sys.argv[1] == '--dump': + if len(argv) > 1 and argv[1] == '--dump': pprint(builds) - sys.exit(0) - elif len(sys.argv) > 1 and sys.argv[1] == '--matrix': + return 0 + + if len(argv) > 1 and argv[1] == '--matrix': gh_output(to_json(builds)) - sys.exit(0) + return 0 - sys.exit(run_builds(builds, run_simulation)) + # by default, run all builds from builds.yml + return run_builds(builds, run_simulation) + + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/webserver/build.py b/webserver/build.py index 1e0eef44..a0824191 100644 --- a/webserver/build.py +++ b/webserver/build.py @@ -59,17 +59,23 @@ def hw_run(manifest_dir: str, build: Build) -> int: return run_build_script(manifest_dir, build, script, final_script=final) -# If called as main, run all builds from builds.yml -if __name__ == '__main__': +def main(argv: list) -> int: builds = load_builds(os.path.dirname(__file__) + "/builds.yml") - if len(sys.argv) > 1 and sys.argv[1] == '--dump': + if len(argv) > 1 and argv[1] == '--dump': pprint(builds) - sys.exit(0) - elif len(sys.argv) > 1 and sys.argv[1] == '--hw': - sys.exit(run_builds(builds, hw_run)) - elif len(sys.argv) > 1 and sys.argv[1] == '--post': + return 0 + + if len(argv) > 1 and argv[1] == '--hw': + return run_builds(builds, hw_run) + + if len(argv) > 1 and argv[1] == '--post': release_mq_locks(builds) - sys.exit(0) + return 0 - sys.exit(run_builds(builds, run_build)) + # by default, run all builds from builds.yml + return run_builds(builds, run_build) + + +if __name__ == '__main__': + sys.exit(main(argv)) From 56da3ae11b239763c3b1a3cef1c28c47017c7b5e Mon Sep 17 00:00:00 2001 From: Axel Heider Date: Sun, 28 Jan 2024 18:26:52 +0100 Subject: [PATCH 08/15] python: use argument parser Signed-off-by: Axel Heider --- camkes-test/build.py | 24 +++++++++++++++++------- camkes-vm/build.py | 21 +++++++++++++++------ cparser-run/build.py | 14 ++++++++++---- march-of-platform/march.py | 16 +++++++++++----- rump-hello/build.py | 21 +++++++++++++++------ sel4bench/build.py | 24 +++++++++++++++++------- sel4test-hw/build.py | 29 ++++++++++++++++++++--------- sel4test-sim/build.py | 15 +++++++++++---- tutorials/build.py | 18 +++++++++++++----- webserver/build.py | 21 +++++++++++++++------ 10 files changed, 144 insertions(+), 59 deletions(-) diff --git a/camkes-test/build.py b/camkes-test/build.py index 13cb2083..d60044ce 100644 --- a/camkes-test/build.py +++ b/camkes-test/build.py @@ -10,6 +10,7 @@ import sys import os +import argparse import json from builds import Build, run_build_script, run_builds, load_builds, release_mq_locks, SKIP @@ -121,31 +122,40 @@ def to_json(builds: list[Build]) -> str: return "matrix=" + json.dumps(matrix) -def main(argv: list) -> int: +def main(params: list) -> int: + parser = argparse.ArgumentParser() + g = parser.add_mutually_exclusive_group() + g.add_argument('--dump', action='store_true') + g.add_argument('--matrix', action='store_true') + g.add_argument('--hw', action='store_true') + g.add_argument('--post', action='store_true') + g.add_argument('--build', action='store_true') + args = parser.parse_args(params) + yml = load_yaml(os.path.dirname(__file__) + "/builds.yml") apps = yml['apps'] sim_builds = [SimBuild(s) for s in yml['sim']] hw_builds = load_builds(None, build_filter, yml) builds = [b for b in sim_builds if sim_build_filter(b)] + hw_builds - if len(argv) > 1 and argv[1] == '--dump': + if args.dump: pprint(builds) return 0 - if len(argv) > 1 and argv[1] == '--matrix': + if args.matrix: gh_output(to_json(builds)) return 0 - if len(argv) > 1 and argv[1] == '--hw': + if args.hw: return run_builds(builds, hw_run) - if len(argv) > 1 and argv[1] == '--post': + if args.post: release_mq_locks(builds) return 0 - # by default, run all builds from builds.yml + # perform args.build as default return run_builds(builds, run_build) if __name__ == '__main__': - sys.exit(main(sys.argv)) + sys.exit(main(sys.argv[1:])) diff --git a/camkes-vm/build.py b/camkes-vm/build.py index 729166b2..b3cdd7a6 100644 --- a/camkes-vm/build.py +++ b/camkes-vm/build.py @@ -10,6 +10,7 @@ import sys import os +import argparse from builds import Build, run_build_script, run_builds, load_builds, release_mq_locks, SKIP, sim_script from pprint import pprint @@ -66,23 +67,31 @@ def hw_run(manifest_dir: str, build: Build) -> int: return run_build_script(manifest_dir, build, script, final_script=final) -def main(argv: list) -> int: +def main(params: list) -> int: + parser = argparse.ArgumentParser() + g = parser.add_mutually_exclusive_group() + g.add_argument('--dump', action='store_true') + g.add_argument('--hw', action='store_true') + g.add_argument('--post', action='store_true') + g.add_argument('--build', action='store_true') + args = parser.parse_args(params) + builds = load_builds(os.path.dirname(__file__) + "/builds.yml") - if len(argv) > 1 and argv[1] == '--dump': + if args.dump: pprint(builds) return 0 - if len(argv) > 1 and argv[1] == '--hw': + if args.hw: return run_builds(builds, hw_run) - if len(argv) > 1 and argv[1] == '--post': + if args.post: release_mq_locks(builds) return 0 - # by default, run all builds from builds.yml + # perform args.build as default return run_builds(builds, run_build) if __name__ == '__main__': - sys.exit(main(sys.argv)) + sys.exit(main(sys.argv[1:])) diff --git a/cparser-run/build.py b/cparser-run/build.py index 006975e9..06270232 100644 --- a/cparser-run/build.py +++ b/cparser-run/build.py @@ -10,6 +10,7 @@ import sys import os +import argparse from builds import run_build_script, run_builds, load_builds from pprint import pprint @@ -28,17 +29,22 @@ def run_cparser(manifest_dir: str, build) -> int: return run_build_script(manifest_dir, build, script) -def main(argv: list) -> int: +def main(params: list) -> int: + parser = argparse.ArgumentParser() + g = parser.add_mutually_exclusive_group() + g.add_argument('--dump', action='store_true') + g.add_argument('--build', action='store_true') + args = parser.parse_args(params) builds = load_builds(os.path.dirname(__file__) + "/builds.yml") - if len(argv) > 1 and argv[1] == '--dump': + if args.dump: pprint(builds) return 0 - # by default, run all builds from builds.yml + # perform args.build as default return run_builds(builds, run_cparser) if __name__ == '__main__': - sys.exit(main(sys.argv)) + sys.exit(main(sys.argv[1:])) diff --git a/march-of-platform/march.py b/march-of-platform/march.py index 878447c7..5844d3b6 100755 --- a/march-of-platform/march.py +++ b/march-of-platform/march.py @@ -3,21 +3,27 @@ # SPDX-License-Identifier: BSD-2-Clause import sys +#import argparse from platforms import platforms, gh_output -def main(argv: list) -> int: - if len(argv) != 2: +def main(params: list) -> int: + #parser = argparse.ArgumentParser() + #g = parser.add_mutually_exclusive_group() + #args = parser.parse_args() + + if len(params) != 2: return 1 - plat = platforms.get(argv[1].upper()) + arg = params[1] + plat = platforms.get(arg.upper()) if plat: gh_output(f"march={plat.march}") return 0 - print(f"Unknown platform {argv[1]}") + print(f"Unknown platform: '{arg}'") return 1 if __name__ == '__main__': - sys.exit(main(sys.argv)) + sys.exit(main(sys.argv[1:])) diff --git a/rump-hello/build.py b/rump-hello/build.py index c72badb7..e9b3f2a1 100644 --- a/rump-hello/build.py +++ b/rump-hello/build.py @@ -10,6 +10,7 @@ import sys import os +import argparse from builds import Build, run_build_script, run_builds, load_builds, sim_script from builds import release_mq_locks, SKIP @@ -55,23 +56,31 @@ def hw_run(manifest_dir: str, build: Build) -> int: return run_build_script(manifest_dir, build, script, final_script=final) -def main(argv: list) -> int: +def main(params: list) -> int: + parser = argparse.ArgumentParser() + g = parser.add_mutually_exclusive_group() + g.add_argument('--dump', action='store_true') + g.add_argument('--hw', action='store_true') + g.add_argument('--post', action='store_true') + g.add_argument('--build', action='store_true') + args = parser.parse_args(params) + builds = load_builds(os.path.dirname(__file__) + "/builds.yml") - if len(argv) > 1 and argv[1] == '--dump': + if args.dump: pprint(builds) return 0 - if len(argv) > 1 and argv[1] == '--hw': + if args.hw: return run_builds(builds, hw_run) - if len(argv) > 1 and argv[1] == '--post': + if args.post: release_mq_locks(builds) return 0 - # by default, run all builds from builds.yml + # perform args.build as default return run_builds(builds, run_build) if __name__ == '__main__': - sys.exit(main(sys.argv)) + sys.exit(main(sys.argv[1:])) diff --git a/sel4bench/build.py b/sel4bench/build.py index 4c92488e..f3d2c06d 100644 --- a/sel4bench/build.py +++ b/sel4bench/build.py @@ -11,6 +11,7 @@ import sys import os import subprocess +import argparse import json import time from datetime import datetime @@ -354,7 +355,16 @@ def gen_web(runs: list[Run], yml, file_name: str): f.write('.

') -def main(argv: list) -> int: +def main(params: list) -> int: + parser = argparse.ArgumentParser() + g = parser.add_mutually_exclusive_group() + g.add_argument('--dump', action='store_true') + g.add_argument('--hw', action='store_true') + g.add_argument('--post', action='store_true') + g.add_argument('--web', action='store_true') + g.add_argument('--build', action='store_true') + args = parser.parse_args(argv[1:]) + yml = load_yaml(os.path.dirname(__file__) + "/builds.yml") builds = load_builds(None, filter_fun=build_filter, yml=yml) @@ -365,24 +375,24 @@ def main(argv: list) -> int: more_builds = [Build(b, default_build) for b in yml.get("more_builds", [])] builds.extend([b for b in more_builds if b and filtered(b, env_filters)]) - if len(argv) > 1 and argv[1] == '--dump': + if args.dump: pprint(builds) return 0 - if len(argv) > 1 and argv[1] == '--hw': + if args.hw: return run_builds(make_runs(builds), hw_run) - if len(argv) > 1 and argv[1] == '--post': + if args.post: release_mq_locks(builds) return 0 - if len(argv) > 1 and argv[1] == '--web': + if args.web: gen_web(make_runs(builds), yml, "index.html") return 0 - # by default, run all builds from builds.yml + # perform args.build as default return run_builds(builds, hw_build) if __name__ == '__main__': - sys.exit(main(sys.argv)) + sys.exit(main(sys.argv[1:])) diff --git a/sel4test-hw/build.py b/sel4test-hw/build.py index 8093dba9..aed8dea5 100644 --- a/sel4test-hw/build.py +++ b/sel4test-hw/build.py @@ -10,6 +10,7 @@ import sys import os +import argparse import json from builds import Build, run_build_script, run_builds, load_builds, junit_results @@ -134,27 +135,37 @@ def run_for_plat(plat: Platform) -> list[dict]: return "matrix=" + json.dumps(matrix) -def main(argv: list) -> int: +def main(params: list) -> int: + parser = argparse.ArgumentParser() + g = parser.add_mutually_exclusive_group() + g.add_argument('--dump', action='store_true') + g.add_argument('--matrix', action='store_true') + g.add_argument('--hw', action='store_true') + g.add_argument('--post', action='store_true') + g.add_argument('--build', action='store_true') + args = parser.parse_args(params) + builds = load_builds(os.path.dirname(__file__) + "/builds.yml", filter_fun=build_filter) - if len(argv) > 1 and argv[1] == '--dump': + if args.dump: pprint(builds) return 0 - if len(argv) > 1 and argv[1] == '--matrix': + if args.matrix: gh_output(to_json(builds)) - sys.exit(0) + return 0 - if len(argv) > 1 and argv[1] == '--hw': - return run_builds(builds, hw_run)) + if args.hw: + run_builds(builds, hw_run) + return 0 - if len(argv) > 1 and argv[1] == '--post': + if args.post: release_mq_locks(builds) return 0 - # by default, run all builds from builds.yml + # perform args.build as default return run_builds(builds, hw_build) if __name__ == '__main__': - sys.exit(main(sys.argv)) + sys.exit(main(sys.argv[1:])) diff --git a/sel4test-sim/build.py b/sel4test-sim/build.py index 3eef63bf..ad243d9c 100644 --- a/sel4test-sim/build.py +++ b/sel4test-sim/build.py @@ -10,6 +10,7 @@ import sys import os +import argparse from builds import Build, run_build_script, run_builds, load_builds, junit_results from pprint import pprint @@ -30,16 +31,22 @@ def run_simulation(manifest_dir: str, build: Build) -> int: return run_build_script(manifest_dir, build, script, junit=True) -def main(argv: list) -> int: +def main(params: list) -> int: + parser = argparse.ArgumentParser() + g = parser.add_mutually_exclusive_group() + g.add_argument('--dump', action='store_true') + g.add_argument('--build', action='store_true') + args = parser.parse_args(params) + builds = load_builds(os.path.dirname(__file__) + "/builds.yml") - if len(argv) > 1 and argv[1] == '--dump': + if args.dump: pprint(builds) return 0 - # by default, run all builds from builds.yml + # perform args.build as default return run_builds(builds, run_simulation) if __name__ == '__main__': - sys.exit(main(sys.argv)) + sys.exit(main(sys.argv[1:])) diff --git a/tutorials/build.py b/tutorials/build.py index 2db68d08..5c54e99f 100644 --- a/tutorials/build.py +++ b/tutorials/build.py @@ -10,6 +10,7 @@ import sys import os +import argparse import json from builds import Build, load_builds, run_build_script, run_builds, junit_results @@ -43,22 +44,29 @@ def to_json(builds: list) -> str: return "matrix=" + json.dumps(matrix) -def main(argv: list) -> int: +def main(params: list) -> int: + parser = argparse.ArgumentParser() + g = parser.add_mutually_exclusive_group() + g.add_argument('--dump', action='store_true') + g.add_argument('--matrix', action='store_true') + g.add_argument('--build', action='store_true') + args = parser.parse_args(params) + yml = load_yaml(os.path.dirname(__file__) + "/builds.yml") disable_app_for = yml['disable_app_for'] builds = load_builds(None, build_filter, yml) - if len(argv) > 1 and argv[1] == '--dump': + if args.dump: pprint(builds) return 0 - if len(argv) > 1 and argv[1] == '--matrix': + if args.matrix: gh_output(to_json(builds)) return 0 - # by default, run all builds from builds.yml + # perform args.build as default return run_builds(builds, run_simulation) if __name__ == '__main__': - sys.exit(main(sys.argv)) + sys.exit(main(sys.argv[1:])) diff --git a/webserver/build.py b/webserver/build.py index a0824191..77d28a87 100644 --- a/webserver/build.py +++ b/webserver/build.py @@ -10,6 +10,7 @@ import sys import os +import argparse from builds import Build, run_build_script, run_builds, load_builds, release_mq_locks, SKIP, sim_script from pprint import pprint @@ -59,23 +60,31 @@ def hw_run(manifest_dir: str, build: Build) -> int: return run_build_script(manifest_dir, build, script, final_script=final) -def main(argv: list) -> int: +def main(params: list) -> int: + parser = argparse.ArgumentParser() + g = parser.add_mutually_exclusive_group() + g.add_argument('--dump', action='store_true') + g.add_argument('--hw', action='store_true') + g.add_argument('--post', action='store_true') + g.add_argument('--build', action='store_true') + args = parser.parse_args(params) + builds = load_builds(os.path.dirname(__file__) + "/builds.yml") - if len(argv) > 1 and argv[1] == '--dump': + if args.dump: pprint(builds) return 0 - if len(argv) > 1 and argv[1] == '--hw': + if args.hw: return run_builds(builds, hw_run) - if len(argv) > 1 and argv[1] == '--post': + if args.post: release_mq_locks(builds) return 0 - # by default, run all builds from builds.yml + # perform args.build as default return run_builds(builds, run_build) if __name__ == '__main__': - sys.exit(main(argv)) + sys.exit(main(argv[1:])) From c4ccd7af1661a3cb0e76f91d40b72604eabf2cf6 Mon Sep 17 00:00:00 2001 From: Axel Heider Date: Sat, 27 Jan 2024 14:47:17 +0100 Subject: [PATCH 09/15] python: use os.path.join() Signed-off-by: Axel Heider --- camkes-test/build.py | 3 ++- camkes-vm/build.py | 3 ++- cparser-run/build.py | 3 ++- rump-hello/build.py | 3 ++- seL4-platforms/platforms.py | 3 ++- sel4bench/build.py | 3 ++- sel4test-hw/build.py | 3 ++- sel4test-sim/build.py | 3 ++- tutorials/build.py | 3 ++- webserver/build.py | 3 ++- 10 files changed, 20 insertions(+), 10 deletions(-) diff --git a/camkes-test/build.py b/camkes-test/build.py index d60044ce..9eda0c1d 100644 --- a/camkes-test/build.py +++ b/camkes-test/build.py @@ -132,7 +132,8 @@ def main(params: list) -> int: g.add_argument('--build', action='store_true') args = parser.parse_args(params) - yml = load_yaml(os.path.dirname(__file__) + "/builds.yml") + builds_yaml_file = os.path.join(os.path.dirname(__file__), "builds.yml") + yml = load_yaml(builds_yaml_file) apps = yml['apps'] sim_builds = [SimBuild(s) for s in yml['sim']] hw_builds = load_builds(None, build_filter, yml) diff --git a/camkes-vm/build.py b/camkes-vm/build.py index b3cdd7a6..a2adf2f2 100644 --- a/camkes-vm/build.py +++ b/camkes-vm/build.py @@ -76,7 +76,8 @@ def main(params: list) -> int: g.add_argument('--build', action='store_true') args = parser.parse_args(params) - builds = load_builds(os.path.dirname(__file__) + "/builds.yml") + builds_yaml_file = os.path.join(os.path.dirname(__file__), "builds.yml") + builds = load_builds(builds_yaml_file) if args.dump: pprint(builds) diff --git a/cparser-run/build.py b/cparser-run/build.py index 06270232..8d0dbd99 100644 --- a/cparser-run/build.py +++ b/cparser-run/build.py @@ -36,7 +36,8 @@ def main(params: list) -> int: g.add_argument('--build', action='store_true') args = parser.parse_args(params) - builds = load_builds(os.path.dirname(__file__) + "/builds.yml") + builds_yaml_file = os.path.join(os.path.dirname(__file__), "builds.yml") + builds = load_builds(builds_yaml_file) if args.dump: pprint(builds) diff --git a/rump-hello/build.py b/rump-hello/build.py index e9b3f2a1..92644050 100644 --- a/rump-hello/build.py +++ b/rump-hello/build.py @@ -65,7 +65,8 @@ def main(params: list) -> int: g.add_argument('--build', action='store_true') args = parser.parse_args(params) - builds = load_builds(os.path.dirname(__file__) + "/builds.yml") + builds_yaml_file = os.path.join(os.path.dirname(__file__), "builds.yml") + builds = load_builds(builds_yaml_file) if args.dump: pprint(builds) diff --git a/seL4-platforms/platforms.py b/seL4-platforms/platforms.py index 762b12dd..a9279a7a 100644 --- a/seL4-platforms/platforms.py +++ b/seL4-platforms/platforms.py @@ -212,7 +212,8 @@ def gh_output(assgn: str): # module init: -_yaml_platforms = load_yaml(os.path.dirname(__file__) + "/platforms.yml") +_platforms_yaml_file = os.path.join(os.path.dirname(__file__), "platforms.yml") +_yaml_platforms = load_yaml(_platforms_yaml_file) all_architectures = _yaml_platforms["architectures"] all_modes = _yaml_platforms["modes"] diff --git a/sel4bench/build.py b/sel4bench/build.py index f3d2c06d..53b7d6a3 100644 --- a/sel4bench/build.py +++ b/sel4bench/build.py @@ -365,7 +365,8 @@ def main(params: list) -> int: g.add_argument('--build', action='store_true') args = parser.parse_args(argv[1:]) - yml = load_yaml(os.path.dirname(__file__) + "/builds.yml") + builds_yaml_file = os.path.join(os.path.dirname(__file__), "builds.yml") + yml = load_yaml(builds_yaml_file) builds = load_builds(None, filter_fun=build_filter, yml=yml) # add additional builds; run only env filter, trusting that manual builds diff --git a/sel4test-hw/build.py b/sel4test-hw/build.py index aed8dea5..ab90c8a8 100644 --- a/sel4test-hw/build.py +++ b/sel4test-hw/build.py @@ -145,7 +145,8 @@ def main(params: list) -> int: g.add_argument('--build', action='store_true') args = parser.parse_args(params) - builds = load_builds(os.path.dirname(__file__) + "/builds.yml", filter_fun=build_filter) + builds_yaml_file = os.path.join(os.path.dirname(__file__), "builds.yml") + builds = load_builds(builds_yaml_file, filter_fun=build_filter) if args.dump: pprint(builds) diff --git a/sel4test-sim/build.py b/sel4test-sim/build.py index ad243d9c..81d63b98 100644 --- a/sel4test-sim/build.py +++ b/sel4test-sim/build.py @@ -38,7 +38,8 @@ def main(params: list) -> int: g.add_argument('--build', action='store_true') args = parser.parse_args(params) - builds = load_builds(os.path.dirname(__file__) + "/builds.yml") + builds_yaml_file = os.path.join(os.path.dirname(__file__), "builds.yml") + builds = load_builds(builds_yaml_file) if args.dump: pprint(builds) diff --git a/tutorials/build.py b/tutorials/build.py index 5c54e99f..058b8eba 100644 --- a/tutorials/build.py +++ b/tutorials/build.py @@ -52,7 +52,8 @@ def main(params: list) -> int: g.add_argument('--build', action='store_true') args = parser.parse_args(params) - yml = load_yaml(os.path.dirname(__file__) + "/builds.yml") + builds_yaml_file = os.path.join(os.path.dirname(__file__), "builds.yml") + yml = load_yaml(builds_yaml_file) disable_app_for = yml['disable_app_for'] builds = load_builds(None, build_filter, yml) diff --git a/webserver/build.py b/webserver/build.py index 77d28a87..f0a1dade 100644 --- a/webserver/build.py +++ b/webserver/build.py @@ -69,7 +69,8 @@ def main(params: list) -> int: g.add_argument('--build', action='store_true') args = parser.parse_args(params) - builds = load_builds(os.path.dirname(__file__) + "/builds.yml") + builds_yaml_file = os.path.join(os.path.dirname(__file__), "builds.yml") + builds = load_builds(builds_yaml_file) if args.dump: pprint(builds) From 9e9ecb7166200cf0673f451e73cf48210f21e8ae Mon Sep 17 00:00:00 2001 From: Axel Heider Date: Fri, 12 Apr 2024 21:01:48 +0200 Subject: [PATCH 10/15] cleanup JSON creation and improve comments Signed-off-by: Axel Heider --- camkes-test/build.py | 15 ++++++++----- sel4test-hw/build.py | 52 ++++++++++++++++++++------------------------ tutorials/build.py | 15 +++++-------- 3 files changed, 38 insertions(+), 44 deletions(-) diff --git a/camkes-test/build.py b/camkes-test/build.py index 9eda0c1d..86c862eb 100644 --- a/camkes-test/build.py +++ b/camkes-test/build.py @@ -115,11 +115,14 @@ def sim_build_filter(build: SimBuild) -> bool: return (not name or build.name == name) and (not plat or plat == 'sim') -def to_json(builds: list[Build]) -> str: - """Return a GitHub build matrix as GitHub output assignment.""" - - matrix = {"include": [{"name": b.name, "platform": b.get_platform().name} for b in builds]} - return "matrix=" + json.dumps(matrix) +def gh_output_matrix(param_name: str, builds: list[Build]) -> None: + build_list = [{"name": b.name, + "platform": b.get_platform().name + } + for b in builds] + # GitHub output assignment + matrix_json = json.dumps({"include": build_list}) + gh_output(f"{param_name}={matrix_json}") def main(params: list) -> int: @@ -144,7 +147,7 @@ def main(params: list) -> int: return 0 if args.matrix: - gh_output(to_json(builds)) + gh_output_matrix("matrix", builds) return 0 if args.hw: diff --git a/sel4test-hw/build.py b/sel4test-hw/build.py index ab90c8a8..29ad7d18 100644 --- a/sel4test-hw/build.py +++ b/sel4test-hw/build.py @@ -12,6 +12,7 @@ import os import argparse import json +import itertools from builds import Build, run_build_script, run_builds, load_builds, junit_results from builds import release_mq_locks, SKIP @@ -100,39 +101,32 @@ def build_filter(build: Build) -> bool: return True -def to_json(builds: List[Build]) -> str: - """Return a GitHub build matrix per enabled hardware platform as GitHub output assignment.""" +def gh_output_matrix(param_name: str, builds: list[Build]) -> None: + build_list = [] + # Loop over all the different platforms of the build list. Using + # set-comprehension " { ... for ... } " instead of list-comprehension + # " [ ... for ... ] " eliminates duplicates automatically. + for plat in {b.get_platform() for b in builds}: - def run_for_plat(plat: Platform) -> list[dict]: + # ignore all platforms that can't tested or not even be built if plat.no_hw_test or plat.no_hw_build: - return [] + continue - # separate runs for each compiler on arm - if plat.arch == 'arm': - return [ - {"platform": plat.name, "march": plat.march, "compiler": "gcc"}, - {"platform": plat.name, "march": plat.march, "compiler": "clang"}, - ] + variants = {"compiler": ["gcc", "clang"]} + if (plat.arch == 'x86'): + variants["mode"] = [32, 64] - if plat.arch == 'riscv': - return [ - {"platform": plat.name, "march": plat.march, "compiler": "gcc"}, - {"platform": plat.name, "march": plat.march, "compiler": "clang"}, - ] + # create builds for all combination from the variants matrix + for vals in itertools.product(*(variants.values())): + build_variant = {"platform": plat.name, + "march": plat.march, + **dict(zip(variants.keys(), vals)) + } + build_list.append(build_variant) - # separate runs for each compiler + mode on x86, because we have more machines available - if plat.arch == 'x86': - return [ - {"platform": plat.name, "march": plat.march, "compiler": "gcc", "mode": 32}, - {"platform": plat.name, "march": plat.march, "compiler": "clang", "mode": 32}, - {"platform": plat.name, "march": plat.march, "compiler": "gcc", "mode": 64}, - {"platform": plat.name, "march": plat.march, "compiler": "clang", "mode": 64}, - ] - - platforms = set([b.get_platform() for b in builds]) - matrix = {"include": [run for plat in platforms for run in run_for_plat(plat)]} - - return "matrix=" + json.dumps(matrix) + # GitHub output assignment + matrix_json = json.dumps({"include": build_list}) + gh_output(f"{param_name}={matrix_json}") def main(params: list) -> int: @@ -153,7 +147,7 @@ def main(params: list) -> int: return 0 if args.matrix: - gh_output(to_json(builds)) + gh_output_matrix("matrix", builds) return 0 if args.hw: diff --git a/tutorials/build.py b/tutorials/build.py index 058b8eba..3ad6ccad 100644 --- a/tutorials/build.py +++ b/tutorials/build.py @@ -34,14 +34,11 @@ def build_filter(build: Build) -> bool: return build.app not in disable_app_for.get(build.get_platform().name, []) -def to_json(builds: list) -> str: - """Return a GitHub build matrix as GitHub output assignment. - - Basically just returns a list of build names that we can then - filter on.""" - - matrix = {"include": [{"name": b.name} for b in builds]} - return "matrix=" + json.dumps(matrix) +def gh_output_matrix(param_name: str, builds: list[Build]) -> None: + build_list = [{"name": b.name} for b in builds] + # GitHub output assignment + matrix_json = json.dumps({"include": build_list}) + gh_output(f"{param_name}={matrix_json}") def main(params: list) -> int: @@ -62,7 +59,7 @@ def main(params: list) -> int: return 0 if args.matrix: - gh_output(to_json(builds)) + gh_output_matrix("matrix", builds) return 0 # perform args.build as default From aa34b6345b177180abff8f006ff70b898aba5ff4 Mon Sep 17 00:00:00 2001 From: Axel Heider Date: Fri, 12 Jan 2024 21:29:35 +0100 Subject: [PATCH 11/15] WIP use plat.modes --- sel4test-hw/build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sel4test-hw/build.py b/sel4test-hw/build.py index 29ad7d18..34c2456f 100644 --- a/sel4test-hw/build.py +++ b/sel4test-hw/build.py @@ -114,7 +114,7 @@ def gh_output_matrix(param_name: str, builds: list[Build]) -> None: variants = {"compiler": ["gcc", "clang"]} if (plat.arch == 'x86'): - variants["mode"] = [32, 64] + variants["mode"] = plat.modes # create builds for all combination from the variants matrix for vals in itertools.product(*(variants.values())): From a7e0c75bdb06681ed6afb2c97ed1e95e649c3c82 Mon Sep 17 00:00:00 2001 From: Axel Heider Date: Sun, 28 Jan 2024 19:03:01 +0100 Subject: [PATCH 12/15] python: use fully qualified names --- camkes-test/build.py | 50 ++++++++++++++++++++-------------------- camkes-vm/build.py | 22 +++++++++--------- rump-hello/build.py | 29 +++++++++++------------ seL4-platforms/builds.py | 14 +++++------ sel4test-hw/build.py | 45 ++++++++++++++++++------------------ sel4test-sim/build.py | 16 ++++++------- tutorials/build.py | 10 ++++---- webserver/build.py | 26 ++++++++++----------- 8 files changed, 105 insertions(+), 107 deletions(-) diff --git a/camkes-test/build.py b/camkes-test/build.py index 86c862eb..4a7c8e7c 100644 --- a/camkes-test/build.py +++ b/camkes-test/build.py @@ -13,9 +13,9 @@ import argparse import json -from builds import Build, run_build_script, run_builds, load_builds, release_mq_locks, SKIP -from platforms import load_yaml, gh_output -from pprint import pprint +import builds +import platforms +import pprint # See also builds.yml for how builds are split up in this test. We use the build @@ -41,10 +41,10 @@ def __repr__(self) -> str: ' })' -def run_build(manifest_dir: str, build: Build | SimBuild) -> int: +def run_build(manifest_dir: str, build: builds.Build | SimBuild) -> int: """Run one CAmkES test. Can be either Build or SimBuild.""" - if isinstance(build, Build): + if isinstance(build, builds.Build): app = apps[build.app] build.files = build.get_platform().image_names(build.get_mode(), "capdl-loader") build.settings['CAMKES_APP'] = build.app @@ -76,23 +76,23 @@ def run_build(manifest_dir: str, build: Build | SimBuild) -> int: else: print(f"Warning: unknown build type for {build.name}") - return run_build_script(manifest_dir, build, script) + return builds.run_build_script(manifest_dir, build, script) -def hw_run(manifest_dir: str, build: Build) -> int: +def hw_run(manifest_dir: str, build: builds.Build) -> int: """Run one hardware test.""" if build.is_disabled(): print(f"Build {build.name} disabled, skipping.") - return SKIP + return builds.SKIP build.success = apps[build.app]['success'] script, final = build.hw_run('log.txt') - return run_build_script(manifest_dir, build, script, final_script=final) + return builds.run_build_script(manifest_dir, build, script, final_script=final) -def build_filter(build: Build) -> bool: +def build_filter(build: builds.Build) -> bool: if not build.app: return False @@ -115,14 +115,14 @@ def sim_build_filter(build: SimBuild) -> bool: return (not name or build.name == name) and (not plat or plat == 'sim') -def gh_output_matrix(param_name: str, builds: list[Build]) -> None: - build_list = [{"name": b.name, - "platform": b.get_platform().name - } - for b in builds] +def gh_output_matrix(param_name: str, build_list: list[builds.Build]) -> None: + matrix_builds = [{"name": b.name, + "platform": b.get_platform().name + } + for b in build_list] # GitHub output assignment - matrix_json = json.dumps({"include": build_list}) - gh_output(f"{param_name}={matrix_json}") + matrix_json = json.dumps({"include": matrix_builds}) + platforms.gh_output(f"{param_name}={matrix_json}") def main(params: list) -> int: @@ -136,29 +136,29 @@ def main(params: list) -> int: args = parser.parse_args(params) builds_yaml_file = os.path.join(os.path.dirname(__file__), "builds.yml") - yml = load_yaml(builds_yaml_file) + yml = platforms.load_yaml(builds_yaml_file) apps = yml['apps'] sim_builds = [SimBuild(s) for s in yml['sim']] - hw_builds = load_builds(None, build_filter, yml) - builds = [b for b in sim_builds if sim_build_filter(b)] + hw_builds + hw_builds = builds.load_builds(None, build_filter, yml) + build_list = [b for b in sim_builds if sim_build_filter(b)] + hw_builds if args.dump: - pprint(builds) + pprint.pprint(build_list) return 0 if args.matrix: - gh_output_matrix("matrix", builds) + gh_output_matrix("matrix", build_list) return 0 if args.hw: - return run_builds(builds, hw_run) + return builds.run_builds(build_list, hw_run) if args.post: - release_mq_locks(builds) + builds.release_mq_locks(build_list) return 0 # perform args.build as default - return run_builds(builds, run_build) + return builds.run_builds(build_list, run_build) if __name__ == '__main__': diff --git a/camkes-vm/build.py b/camkes-vm/build.py index a2adf2f2..f64ccd16 100644 --- a/camkes-vm/build.py +++ b/camkes-vm/build.py @@ -12,7 +12,7 @@ import os import argparse -from builds import Build, run_build_script, run_builds, load_builds, release_mq_locks, SKIP, sim_script +from builds import Build, run_build_script, run_builds, load_builds, release_mq_locks, SKIP from pprint import pprint @@ -22,7 +22,7 @@ # The only thing this really has in common with a "Build" is the "name" field. -def run_build(manifest_dir: str, build: Build) -> int: +def run_build(manifest_dir: str, build: builds.Build) -> int: """Run one CAmkES VM test.""" plat = build.get_platform() @@ -49,22 +49,22 @@ def run_build(manifest_dir: str, build: Build) -> int: if plat.has_simulation and plat.name != 'PC99': script.append(sim_script(build.success, failure=build.error)) - return run_build_script(manifest_dir, build, script) + return builds.run_build_script(manifest_dir, build, script) -def hw_run(manifest_dir: str, build: Build) -> int: +def hw_run(manifest_dir: str, build: builds.Build) -> int: """Run one hardware test.""" if build.is_disabled(): print(f"Build {build.name} disabled, skipping.") - return SKIP + return builds.SKIP plat = build.get_platform() build.files = plat.image_names(build.get_mode(), "capdl-loader") script, final = build.hw_run('log.txt') - return run_build_script(manifest_dir, build, script, final_script=final) + return builds.run_build_script(manifest_dir, build, script, final_script=final) def main(params: list) -> int: @@ -77,21 +77,21 @@ def main(params: list) -> int: args = parser.parse_args(params) builds_yaml_file = os.path.join(os.path.dirname(__file__), "builds.yml") - builds = load_builds(builds_yaml_file) + build_list = builds.load_builds(builds_yaml_file) if args.dump: - pprint(builds) + pprint.pprint(build_list) return 0 if args.hw: - return run_builds(builds, hw_run) + return builds.run_builds(build_list, hw_run) if args.post: - release_mq_locks(builds) + builds.release_mq_locks(build_list) return 0 # perform args.build as default - return run_builds(builds, run_build) + return builds.run_builds(build_list, run_build) if __name__ == '__main__': diff --git a/rump-hello/build.py b/rump-hello/build.py index 92644050..55ebc0aa 100644 --- a/rump-hello/build.py +++ b/rump-hello/build.py @@ -12,19 +12,18 @@ import os import argparse -from builds import Build, run_build_script, run_builds, load_builds, sim_script -from builds import release_mq_locks, SKIP -from pprint import pprint +import build +import pprint -def adjust_build(build: Build): +def adjust_build(build: builds.Build): build.files = build.get_platform().image_names(build.get_mode(), "roottask") # remove parameters from setting that CMake does not use and thus would # raise a nasty warning del build.settings['BAMBOO'] -def run_build(manifest_dir: str, build: Build) -> int: +def run_build(manifest_dir: str, build: builds.Build) -> int: """Run one rumprun-hello test.""" adjust_build(build) @@ -35,25 +34,25 @@ def run_build(manifest_dir: str, build: Build) -> int: ] if build.req == 'sim': - script.append(sim_script(build.success)) + script.append(builds.sim_script(build.success)) else: script.append(["tar", "czf", f"../{build.name}-images.tar.gz", "images/"]) - return run_build_script(manifest_dir, build, script) + return builds.run_build_script(manifest_dir, build, script) -def hw_run(manifest_dir: str, build: Build) -> int: +def hw_run(manifest_dir: str, build: builds.Build) -> int: """Run one hardware test.""" adjust_build(build) if build.is_disabled(): print(f"Build {build.name} disabled, skipping.") - return SKIP + return builds.SKIP script, final = build.hw_run('log.txt') - return run_build_script(manifest_dir, build, script, final_script=final) + return builds.run_build_script(manifest_dir, build, script, final_script=final) def main(params: list) -> int: @@ -66,21 +65,21 @@ def main(params: list) -> int: args = parser.parse_args(params) builds_yaml_file = os.path.join(os.path.dirname(__file__), "builds.yml") - builds = load_builds(builds_yaml_file) + build_list = builds.load_builds(builds_yaml_file) if args.dump: - pprint(builds) + pprint.pprint(build_list) return 0 if args.hw: - return run_builds(builds, hw_run) + return builds.run_builds(build_list, hw_run) if args.post: - release_mq_locks(builds) + builds.release_mq_locks(build_list) return 0 # perform args.build as default - return run_builds(builds, run_build) + return builds.run_builds(build_list, run_build) if __name__ == '__main__': diff --git a/seL4-platforms/builds.py b/seL4-platforms/builds.py index 40f6d212..25b09f7a 100644 --- a/seL4-platforms/builds.py +++ b/seL4-platforms/builds.py @@ -20,9 +20,9 @@ import copy import time +import platforms +from platforms import ValidationException from junitparser.junitparser import Failure, Error -from platforms import ValidationException, Platform, platforms, load_yaml, mcs_unsupported - from junitparser import JUnitXml @@ -98,9 +98,9 @@ def update_settings(self): # Sel4testSimulation and Sel4testHaveCache. self.settings["SIMULATION"] = "TRUE" - def get_platform(self) -> Platform: + def get_platform(self) -> platforms.Platform: """Return the Platform object for this build definition.""" - return platforms[self.platform] + return platforms.platforms[self.platform] def get_mode(self) -> int: """Return the mode (32/64) for this build; taken from platform if not defined""" @@ -168,7 +168,7 @@ def is_gcc(self) -> bool: return not self.is_clang() def can_mcs(self) -> bool: - return self.get_platform().name not in mcs_unsupported + return self.get_platform().name not in platforms.mcs_unsupported def set_mcs(self): if not self.can_mcs(): @@ -878,7 +878,7 @@ def load_builds(file_name: str, filter_fun=lambda x: True, Applies defaults, variants, and build-filter from the yaml file. Takes an optional filtering function for removing unwanted builds.""" - yml = yml or load_yaml(file_name) + yml = yml or platforms.load_yaml(file_name) default_build = yml.get("default", {}) build_filters = yml.get("build-filter", []) @@ -887,7 +887,7 @@ def load_builds(file_name: str, filter_fun=lambda x: True, yml_builds = yml.get("builds", []) if yml_builds == []: - base_builds = [build_for_platform(p, default_build) for p in platforms.keys()] + base_builds = [build_for_platform(p, default_build) for p in platforms.platforms.keys()] else: base_builds = [Build(b, default_build) for b in yml_builds] diff --git a/sel4test-hw/build.py b/sel4test-hw/build.py index 34c2456f..6a49f2b7 100644 --- a/sel4test-hw/build.py +++ b/sel4test-hw/build.py @@ -14,13 +14,12 @@ import json import itertools -from builds import Build, run_build_script, run_builds, load_builds, junit_results -from builds import release_mq_locks, SKIP -from platforms import Platform, gh_output -from pprint import pprint +import builds +import platforms +import pprint -def hw_build(manifest_dir: str, build: Build) -> int: +def hw_build(manifest_dir: str, build: builds.Build) -> int: """Run one hardware build.""" if build.get_platform().name == "RPI4": @@ -35,22 +34,22 @@ def hw_build(manifest_dir: str, build: Build) -> int: ["cp", "kernel/kernel.elf", f"../{build.name}-kernel.elf"] ] - return run_build_script(manifest_dir, build, script) + return builds.run_build_script(manifest_dir, build, script) -def hw_run(manifest_dir: str, build: Build) -> int: +def hw_run(manifest_dir: str, build: builds.Build) -> int: """Run one hardware test.""" if build.is_disabled(): print(f"Build {build.name} disabled, skipping.") - return SKIP + return builds.SKIP - script, final = build.hw_run(junit_results) + script, final = build.hw_run(builds.junit_results) - return run_build_script(manifest_dir, build, script, final_script=final, junit=True) + return builds.run_build_script(manifest_dir, build, script, final_script=final, junit=True) -def build_filter(build: Build) -> bool: +def build_filter(build: builds.Build) -> bool: plat = build.get_platform() if plat.no_hw_build: @@ -101,12 +100,12 @@ def build_filter(build: Build) -> bool: return True -def gh_output_matrix(param_name: str, builds: list[Build]) -> None: - build_list = [] +def gh_output_matrix(param_name: str, build_list: list[builds.Build]) -> None: + matrix_builds = [] # Loop over all the different platforms of the build list. Using # set-comprehension " { ... for ... } " instead of list-comprehension # " [ ... for ... ] " eliminates duplicates automatically. - for plat in {b.get_platform() for b in builds}: + for plat in {b.get_platform() for b in build_list}: # ignore all platforms that can't tested or not even be built if plat.no_hw_test or plat.no_hw_build: @@ -122,11 +121,11 @@ def gh_output_matrix(param_name: str, builds: list[Build]) -> None: "march": plat.march, **dict(zip(variants.keys(), vals)) } - build_list.append(build_variant) + matrix_builds.append(build_variant) # GitHub output assignment - matrix_json = json.dumps({"include": build_list}) - gh_output(f"{param_name}={matrix_json}") + matrix_json = json.dumps({"include": matrix_builds}) + platforms.gh_output(f"{param_name}={matrix_json}") def main(params: list) -> int: @@ -140,26 +139,26 @@ def main(params: list) -> int: args = parser.parse_args(params) builds_yaml_file = os.path.join(os.path.dirname(__file__), "builds.yml") - builds = load_builds(builds_yaml_file, filter_fun=build_filter) + build_list = builds.load_builds(builds_yaml_file, filter_fun=build_filter) if args.dump: - pprint(builds) + pprint.pprint(build_list) return 0 if args.matrix: - gh_output_matrix("matrix", builds) + gh_output_matrix("matrix", build_list) return 0 if args.hw: - run_builds(builds, hw_run) + builds.run_builds(build_list, hw_run) return 0 if args.post: - release_mq_locks(builds) + builds.release_mq_locks(build_list) return 0 # perform args.build as default - return run_builds(builds, hw_build) + return builds.run_builds(build_list, hw_build) if __name__ == '__main__': diff --git a/sel4test-sim/build.py b/sel4test-sim/build.py index 81d63b98..57852d7e 100644 --- a/sel4test-sim/build.py +++ b/sel4test-sim/build.py @@ -12,11 +12,11 @@ import os import argparse -from builds import Build, run_build_script, run_builds, load_builds, junit_results -from pprint import pprint +import builds +import pprint -def run_simulation(manifest_dir: str, build: Build) -> int: +def run_simulation(manifest_dir: str, build: builds.Build) -> int: """Run one simulation build and test.""" expect = '"%s" {exit 0} timeout {exit 1}' % build.success @@ -25,10 +25,10 @@ def run_simulation(manifest_dir: str, build: Build) -> int: ["../init-build.sh"] + build.settings_args(), ["ninja"], ["bash", "-c", - f"expect -c 'spawn ./simulate; set timeout 1200; expect {expect}' | tee {junit_results}"] + f"expect -c 'spawn ./simulate; set timeout 1200; expect {expect}' | tee {builds.junit_results}"] ] - return run_build_script(manifest_dir, build, script, junit=True) + return builds.run_build_script(manifest_dir, build, script, junit=True) def main(params: list) -> int: @@ -39,14 +39,14 @@ def main(params: list) -> int: args = parser.parse_args(params) builds_yaml_file = os.path.join(os.path.dirname(__file__), "builds.yml") - builds = load_builds(builds_yaml_file) + build_list = builds.load_builds(builds_yaml_file) if args.dump: - pprint(builds) + pprint.pprint(build_list) return 0 # perform args.build as default - return run_builds(builds, run_simulation) + return builds.run_builds(build_list, run_simulation) if __name__ == '__main__': diff --git a/tutorials/build.py b/tutorials/build.py index 3ad6ccad..355ce4d9 100644 --- a/tutorials/build.py +++ b/tutorials/build.py @@ -34,11 +34,11 @@ def build_filter(build: Build) -> bool: return build.app not in disable_app_for.get(build.get_platform().name, []) -def gh_output_matrix(param_name: str, builds: list[Build]) -> None: - build_list = [{"name": b.name} for b in builds] +def gh_output_matrix(param_name: str, build_list: list[builds.Build]) -> None: + matrix_builds = [{"name": b.name} for b in build_list] # GitHub output assignment - matrix_json = json.dumps({"include": build_list}) - gh_output(f"{param_name}={matrix_json}") + matrix_json = json.dumps({"include": matrix_builds}) + platforms.gh_output(f"{param_name}={matrix_json}") def main(params: list) -> int: @@ -59,7 +59,7 @@ def main(params: list) -> int: return 0 if args.matrix: - gh_output_matrix("matrix", builds) + gh_output_matrix("matrix", build_list) return 0 # perform args.build as default diff --git a/webserver/build.py b/webserver/build.py index f0a1dade..f015a96f 100644 --- a/webserver/build.py +++ b/webserver/build.py @@ -12,8 +12,8 @@ import os import argparse -from builds import Build, run_build_script, run_builds, load_builds, release_mq_locks, SKIP, sim_script -from pprint import pprint +import builds +import pprint # See also builds.yml for how builds are split up in this test. We use the build @@ -22,7 +22,7 @@ # The only thing this really has in common with a "Build" is the "name" field. -def run_build(manifest_dir: str, build: Build) -> int: +def run_build(manifest_dir: str, build: builds.Build) -> int: """Run one seL4 web server app test.""" plat = build.get_platform() @@ -40,24 +40,24 @@ def run_build(manifest_dir: str, build: Build) -> int: ] if plat.has_simulation and plat.name != 'PC99': - script.append(sim_script(build.success)) + script.append(builds.sim_script(build.success)) - return run_build_script(manifest_dir, build, script) + return builds.run_build_script(manifest_dir, build, script) -def hw_run(manifest_dir: str, build: Build) -> int: +def hw_run(manifest_dir: str, build: builds.Build) -> int: """Run one hardware test.""" if build.is_disabled(): print(f"Build {build.name} disabled, skipping.") - return SKIP + return builds.SKIP plat = build.get_platform() build.files = plat.image_names(build.get_mode(), "capdl-loader") script, final = build.hw_run('log.txt') - return run_build_script(manifest_dir, build, script, final_script=final) + return builds.run_build_script(manifest_dir, build, script, final_script=final) def main(params: list) -> int: @@ -70,21 +70,21 @@ def main(params: list) -> int: args = parser.parse_args(params) builds_yaml_file = os.path.join(os.path.dirname(__file__), "builds.yml") - builds = load_builds(builds_yaml_file) + build_list = builds.load_builds(builds_yaml_file) if args.dump: - pprint(builds) + pprint.pprint(build_list) return 0 if args.hw: - return run_builds(builds, hw_run) + return builds.run_builds(build_list, hw_run) if args.post: - release_mq_locks(builds) + builds.release_mq_locks(build_list) return 0 # perform args.build as default - return run_builds(builds, run_build) + return builds.run_builds(build_list, run_build) if __name__ == '__main__': From a25b86682811d03e4faf0f04c8f9aaae2b1c5c98 Mon Sep 17 00:00:00 2001 From: Axel Heider Date: Wed, 31 Jan 2024 18:51:53 +0100 Subject: [PATCH 13/15] python: inline success_from_bool() Signed-off-by: Axel Heider --- seL4-platforms/builds.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/seL4-platforms/builds.py b/seL4-platforms/builds.py index 25b09f7a..7c0c00f1 100644 --- a/seL4-platforms/builds.py +++ b/seL4-platforms/builds.py @@ -489,13 +489,6 @@ def mq_print_lock(machine: str) -> list[str]: REPEAT = 3 -def success_from_bool(success: bool) -> int: - if success: - return SUCCESS - else: - return FAILURE - - def run_cmd(cmd, run: Union[Run, Build], prev_output: str = None) -> int: """If the command is a list[str], echo + run command with arguments, otherwise expect a function, and run that function on the supplied Run plus outputs from @@ -515,9 +508,10 @@ def run_cmd(cmd, run: Union[Run, Build], prev_output: str = None) -> int: print(line) sys.stdout.flush() sys.stderr.flush() - ret = process.wait() - return success_from_bool(ret == 0), lines + ret_code = process.wait() + ret = SUCCESS if (0 == ret_code) else FAILURE + return ret, lines else: return cmd(run, prev_output) @@ -535,7 +529,7 @@ def summarise_junit(file_path: str) -> tuple[int, list[str]]: xml = JUnitXml.fromfile(file_path) succeeded = xml.tests - (xml.failures + xml.errors + xml.skipped) success = xml.failures == 0 and xml.errors == 0 - + ret = SUCCESS if success else FAILURE col = ANSI_GREEN if success else ANSI_RED printc(col, "Test summary") @@ -552,7 +546,7 @@ def summarise_junit(file_path: str) -> tuple[int, list[str]]: failures = {str(case.name) for case in xml if any([isinstance(r, Failure) or isinstance(r, Error) for r in case.result])} - return success_from_bool(success), list(failures) + return ret, list(failures) # where junit results are left after sanitising: From db1bd8abc93f6596869e63c5747e1754547c3af2 Mon Sep 17 00:00:00 2001 From: Axel Heider Date: Thu, 1 Feb 2024 03:53:23 +0100 Subject: [PATCH 14/15] python: create class AnsiPrinter Signed-off-by: Axel Heider --- seL4-platforms/builds.py | 145 +++++++++++++++++++++++++-------------- 1 file changed, 94 insertions(+), 51 deletions(-) diff --git a/seL4-platforms/builds.py b/seL4-platforms/builds.py index 7c0c00f1..3758ea2b 100644 --- a/seL4-platforms/builds.py +++ b/seL4-platforms/builds.py @@ -35,13 +35,72 @@ # where to expect jUnit results by default junit_results = 'results.xml' -# colour codes -ANSI_RESET = "\033[0m" -ANSI_RED = "\033[31;1m" -ANSI_GREEN = "\033[32m" -ANSI_YELLOW = "\033[33m" -ANSI_WHITE = "\033[37m" -ANSI_BOLD = "\033[1m" +# return codes for a test run or single step of a run +FAILURE = 0 +SUCCESS = 1 +SKIP = 2 +REPEAT = 3 + + +class AnsiPrinter: + # colour codes + ANSI_RESET = "\033[0m" + ANSI_BOLD = "\033[1m" + #ANSI_BLACK = "\033[30m" + ANSI_RED = "\033[31;1m" + ANSI_GREEN = "\033[32m" + ANSI_YELLOW = "\033[33m" + ANSI_BLUE = "\033[34m" + ANSI_MAGENTA = "\033[35m" + ANSI_CYAN = "\033[36m" + ANSI_WHITE = "\033[37m" + + @classmethod + def printc(cls, ansi_color: str, content: str): + print(f"{ansi_color}{content}{cls.ANSI_RESET}") + sys.stdout.flush() + + @classmethod + def error(cls, content: str): + cls.printc(cls.ANSI_RED, content) + + @classmethod + def warn(cls, content: str): + cls.printc(cls.ANSI_YELLOW, content) + + @classmethod + def skip(cls, content: str): + cls.printc(cls.ANSI_YELLOW, content) + + @classmethod + def ok(cls, content: str): + cls.printc(cls.ANSI_GREEN, content) + + @classmethod + def command(cls, cmd: Union[str, list]): + cmd = cmd if isinstance(cmd, str) \ + else " ".join(cmd) if isinstance(cmd, list) \ + else str(cmd) + cls.printc(cls.ANSI_YELLOW, f"+++ {cmd}") + + @classmethod + def step_start(cls, step_type: str, step_name: str): + print(f"::group::{step_name}") + cls.printc(cls.ANSI_BOLD, + f"-----------[ start {step_type} {step_name} ]-----------") + + @classmethod + def step_end(cls, step_type: str, step_name: str, result: int): + cls.printc(cls.ANSI_BOLD, + f"-----------[ end {step_type} {step_name} ]-----------") + print("::endgroup::") + # print status after group, so that it's easier to scan for failed jobs + if result == SUCCESS: + cls.ok(f"{step_name} succeeded") + elif result == SKIP: + cls.skip(f"{step_name} skipped") + elif result == FAILURE: + cls.error(f"{step_name} FAILED") class Build: @@ -365,7 +424,7 @@ def repeat_on_boot_failure(log: list[str]) -> int: for pat in boot_fail_patterns: for i in range(len(log)+1-len(pat)): if all(p in log[i+j] for j, p in enumerate(pat)): - printc(ANSI_RED, "Boot failure detected.") + AnsiPrinter.error("Boot failure detected.") time.sleep(10) return REPEAT, None else: @@ -482,21 +541,13 @@ def mq_print_lock(machine: str) -> list[str]: return ['mq.sh', 'sem', '-info', machine] -# return codes for a test run or single step of a run -FAILURE = 0 -SUCCESS = 1 -SKIP = 2 -REPEAT = 3 - - def run_cmd(cmd, run: Union[Run, Build], prev_output: str = None) -> int: """If the command is a list[str], echo + run command with arguments, otherwise expect a function, and run that function on the supplied Run plus outputs from previous command.""" if isinstance(cmd, list): - printc(ANSI_YELLOW, "+++ " + " ".join(cmd)) - sys.stdout.flush() + AnsiPrinter.command(cmd) # Print output as it arrives. Some of the build commands take too long to # wait until all output is there. Keep stderr separate, but flush it. process = subprocess.Popen(cmd, text=True, stdout=subprocess.PIPE, @@ -516,10 +567,6 @@ def run_cmd(cmd, run: Union[Run, Build], prev_output: str = None) -> int: return cmd(run, prev_output) -def printc(color: str, content: str): - print(color + content + ANSI_RESET) - - def summarise_junit(file_path: str) -> tuple[int, list[str]]: """Parse jUnit output and show a summary. @@ -530,17 +577,18 @@ def summarise_junit(file_path: str) -> tuple[int, list[str]]: succeeded = xml.tests - (xml.failures + xml.errors + xml.skipped) success = xml.failures == 0 and xml.errors == 0 ret = SUCCESS if success else FAILURE - col = ANSI_GREEN if success else ANSI_RED + col = AnsiPrinter.ANSI_GREEN if success else AnsiPrinter.ANSI_RED - printc(col, "Test summary") - printc(col, "------------") - printc(ANSI_GREEN if success else "", f"succeeded: {succeeded}/{xml.tests}") + AnsiPrinter.printc(col, "Test summary") + AnsiPrinter.printc(col, "------------") + AnsiPrinter.printc(AnsiPrinter.ANSI_GREEN if success else "", + f"succeeded: {succeeded}/{xml.tests}") if xml.skipped > 0: - printc(ANSI_YELLOW, f"skipped: {xml.skipped}") + AnsiPrinter.skip(f"skipped: {xml.skipped}") if xml.failures > 0: - printc(ANSI_RED, f"failures: {xml.failures}") + AnsiPrinter.error(f"failures: {xml.failures}") if xml.errors > 0: - printc(ANSI_RED, f"errors: {xml.errors}") + AnsiPrinter.error(f"errors: {xml.errors}") print() failures = {str(case.name) for case in xml @@ -590,9 +638,7 @@ def run_build_script(manifest_dir: str, result = SKIP tries_left = 3 - print(f"::group::{run.name}") - printc(ANSI_BOLD, f"-----------[ start test {run.name} ]-----------") - sys.stdout.flush() + AnsiPrinter.step_start("test", run.name) while tries_left > 0: tries_left -= 1 @@ -619,9 +665,9 @@ def run_build_script(manifest_dir: str, break if result == FAILURE: - printc(ANSI_RED, ">>> command failed, aborting.") + AnsiPrinter.error(">>> command failed, aborting.") elif result == SKIP: - printc(ANSI_YELLOW, ">>> skipping this test.") + AnsiPrinter.skip(">>> skipping this test.") # run final script tasks even in case of failure, but not for SKIP if result != SKIP: @@ -644,36 +690,32 @@ def run_build_script(manifest_dir: str, try: result, failures = summarise_junit(junit_file) except IOError: - printc(ANSI_RED, f"Error reading {junit_file}") + AnsiPrinter.error(f"Error reading {junit_file}") result = FAILURE except: - printc(ANSI_RED, f"Error parsing {junit_file}") + AnsiPrinter.error(f"Error parsing {junit_file}") result = FAILURE if result == REPEAT and tries_left > 0: - printc(ANSI_YELLOW, ">>> command failed, repeating test.") + AnsiPrinter.warn(">>> command failed, repeating test.") elif result == REPEAT and tries_left == 0: result = FAILURE - printc(ANSI_RED, ">>> command failed, no tries left.") + AnsiPrinter.error(">>> command failed, no tries left.") if result != REPEAT: break - printc(ANSI_BOLD, f"-----------[ end test {run.name} ]-----------") - print("::endgroup::") + AnsiPrinter.step_end("test", run.name, result) # after group, so that it's easier to scan for failed jobs - if result == SUCCESS: - printc(ANSI_GREEN, f"{run.name} succeeded") - elif result == SKIP: - printc(ANSI_YELLOW, f"{run.name} skipped") - elif result == FAILURE: - printc(ANSI_RED, f"{run.name} FAILED") + if result == FAILURE: if failures != []: max_print = 10 - printc(ANSI_RED, "Failed cases: " + ", ".join(failures[:max_print]) + - (" ..." if len(failures) > max_print else "")) + AnsiPrinter.error("Failed cases: " + ", ".join(failures[:max_print]) + + (" ..." if len(failures) > max_print else "")) + elif result in [SUCCESS, SKIP]: + pass # AnsiPrinter.step_end(() has printed everything else: - printc(ANSI_RED, f"{run.name} with REPEAT at end of test, we should not see this.") + AnsiPrinter.error(f"{run.name} with REPEAT at end of test, we should not see this.") print("") sys.stdout.flush() @@ -921,12 +963,13 @@ def run_builds(builds: list, run_fun) -> int: results[run_fun(manifest_dir, build)].append(build.name) no_failures = results[FAILURE] == [] - printc(ANSI_GREEN if no_failures else "", "Successful tests: " + ", ".join(results[SUCCESS])) + AnsiPrinter.printc(AnsiPrinter.ANSI_GREEN if no_failures else "", + "Successful tests: " + ", ".join(results[SUCCESS])) if results[SKIP] != []: print() - printc(ANSI_YELLOW, "SKIPPED tests: " + ", ".join(results[SKIP])) + AnsiPrinter.skip("SKIPPED tests: " + ", ".join(results[SKIP])) if results[FAILURE] != []: print() - printc(ANSI_RED, "FAILED tests: " + ", ".join(results[FAILURE])) + AnsiPrinter.error("FAILED tests: " + ", ".join(results[FAILURE])) return 0 if no_failures else 1 From a6178de3528d840d446cb00ffd911970908cb8a3 Mon Sep 17 00:00:00 2001 From: Axel Heider Date: Sun, 3 Mar 2024 19:50:21 +0100 Subject: [PATCH 15/15] CI: run mypi --- .github/workflows/push.yml | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 9388e929..15c7132e 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -26,3 +26,37 @@ jobs: - uses: seL4/ci-actions/link-check@master with: exclude: '/node_modules/' + + mypy: + name: MyPy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install mypy + run: pip3 install mypy + - name: Run mypy + #run: mypy --explicit-package-bases ./ + run: | + mypy seL4-platforms + mypy seL4-platforms camkes-hw + mypy seL4-platforms camkes-test + mypy seL4-platforms camkes-vm + mypy seL4-platforms camkes-vm-hw + mypy seL4-platforms cparser-run + mypy seL4-platforms dashboard + mypy seL4-platforms l4v-deploy + mypy seL4-platforms march-of-platform + mypy seL4-platforms rump-hello + mypy seL4-platforms rump-hello-hw + mypy seL4-platforms sel4bench + mypy seL4-platforms sel4bench-hw + mypy seL4-platforms sel4bench-web + mypy seL4-platforms sel4test-hw + mypy seL4-platforms sel4test-hw-matrix + mypy seL4-platforms sel4test-hw-run + mypy seL4-platforms sel4test-sim + mypy seL4-platforms thylint + mypy seL4-platforms trigger + mypy seL4-platforms tutorials + mypy seL4-platforms webserver + mypy seL4-platforms webserver-hw