From ceec795ae5993e60801aaad6479593985f946040 Mon Sep 17 00:00:00 2001 From: MrKevinWeiss Date: Thu, 4 May 2023 12:13:54 +0200 Subject: [PATCH] compile_and_test_for_board: Add only-if-changed feature This will use the make test-input-hash-changed feature to save the test hashes with the results and optionally skip running the test if nothing has changed. Murdock already has this feature but it is not easily accessible. This should prevent unneeded flash cycles as well as speeding up constant rerunning of tests for boards. --- .../compile_and_test_for_board.py | 40 ++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/dist/tools/compile_and_test_for_board/compile_and_test_for_board.py b/dist/tools/compile_and_test_for_board/compile_and_test_for_board.py index 9e8ee3e69f..824d693722 100755 --- a/dist/tools/compile_and_test_for_board/compile_and_test_for_board.py +++ b/dist/tools/compile_and_test_for_board/compile_and_test_for_board.py @@ -44,6 +44,7 @@ usage: compile_and_test_for_board.py [-h] [--applications APPLICATIONS] [--test-targets TEST_TARGETS] [--test-available-targets TEST_AVAILABLE_TARGETS] [--report-xml] [--jobs JOBS] + [--only-if-changed] riot_directory board [result_directory] positional arguments: @@ -84,6 +85,9 @@ optional arguments: (default: False) --jobs JOBS, -j JOBS Parallel building (0 means not limit, like '--jobs') (default: None) + --only-if-changed, -c + Only test if the application has changed since last + test (default: False) ``` """ # noqa @@ -225,6 +229,7 @@ def is_in_directory(path, directory): return path.startswith(directory) +# pylint: disable=too-many-instance-attributes class RIOTApplication: """RIOT Application representation. @@ -245,6 +250,7 @@ class RIOTApplication: ) FLASH_TARGETS = ("flash-only",) TEST_TARGETS = ("test",) + TEST_INPUT_HASH = ("test-input-hash-changed",) TEST_AVAILABLE_TARGETS = ("test/available",) # pylint: disable=too-many-arguments @@ -252,6 +258,7 @@ class RIOTApplication: self.board = board self.riotdir = riotdir self.appdir = appdir + self.hashdir = os.path.abspath(os.path.join(resultdir, "hashes", appdir)) self.resultdir = os.path.join(resultdir, appdir) if junit: if not junit_xml: @@ -368,8 +375,11 @@ class RIOTApplication: incremental=False, jobs=False, with_test_only=False, + only_if_changed=False, ): # pylint:disable=too-many-arguments + # pylint:disable=too-many-nested-blocks + # pylint:disable=too-many-branches """Compile and execute test if available. Checks for board supported/enough memory, compiles. @@ -422,8 +432,28 @@ class RIOTApplication: if clean_after: self.clean_intermediates() + # pylint: disable=too-many-nested-blocks if runtest: if has_test: + if only_if_changed: + try: + out = self.make( + self.TEST_INPUT_HASH, + env={"RIOT_TEST_HASH_DIR": self.hashdir}, + ) + hash_match = "hashes match" in out.lower() + self.logger.info("Hashes match: %r", hash_match) + if hash_match: + self._skip( + "bins_unchanged", + f"{self.appdir} matched test input hashes.", + ) + if clean_after: + self.clean() + self.logger.info("Success") + return + except subprocess.CalledProcessError as err: + self._make_handle_error(self.TEST_INPUT_HASH[0], err) setuptasks = collections.OrderedDict([("flash", self.FLASH_TARGETS)]) self.make_with_outfile( "test", self.TEST_TARGETS, save_output=True, setuptasks=setuptasks @@ -732,7 +762,6 @@ PARSER.add_argument( default=False, help="Output results to report.xml in the " "result_directory", ) - PARSER.add_argument( "--jobs", "-j", @@ -740,6 +769,14 @@ PARSER.add_argument( default=None, help="Parallel building (0 means not limit, like '--jobs')", ) +# Arg that allows hashes of tests to be saved locally in a hashes folder +# and used to skip tests if new hashes match. +PARSER.add_argument( + "--only-if-changed", + "-c", + action="store_true", + help="Only test if the application has changed since last test", +) def main(args): @@ -798,6 +835,7 @@ def main(args): incremental=args.incremental, jobs=args.jobs, with_test_only=args.with_test_only, + only_if_changed=args.only_if_changed, ) for app in applications ]