Received: by 2002:a05:6a10:5bc5:0:0:0:0 with SMTP id os5csp5030096pxb; Tue, 2 Nov 2021 21:30:52 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzWtgL5UvkxLaOig5z0S9X+KB0ud5ia1gtIBka8w3jfwdOsqhdLLtCS5nv/U6isxZn15GDo X-Received: by 2002:a50:9993:: with SMTP id m19mr21992745edb.259.1635913851880; Tue, 02 Nov 2021 21:30:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1635913851; cv=none; d=google.com; s=arc-20160816; b=qiKRenwOmgjl1P9I74OM262BMnMrd+MEYxKXw/Wn7rVCsanclHD7onr3YW74YPQCPJ mzf6UbUkK4KC2m7uQt+suF8y4uPX8uXDRR9SFFD0jXWkd7j3+lkrPhr+SKzCiAQJcRrK 6gUN+E8K1v1B+8HKnOdClFyXJrroYk2oECEvlY7l8YpIOUHd3VYZBwWa5nybssuaOBP0 s1upeqKPaIF2Zh4dYcuqZBjOwYHJZ1d7IkSomQXcNrRVoExcxMAztgedIuOpsrC76VSg PCxBYnOfOiqQduRChA/5QOPNdFutxcvghu0TLQbVKOwaoYg98ruYK83E0FFA1/3jHi+I e7Fw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:mime-version:message-id:date :dkim-signature; bh=0XauQlZsaPUfyum8gatBpe8x8WpyNCmm8SdAdVAZ9Qo=; b=sQ5dvUx6FaoQyK6rx7yUQILQm0nSpbYplof1HNc+fq6nhVlg/N1/bkILWTmtvkp/Il aqXKdRQ3GhKZuUZWDzqiwYkRidfhdiE7vfLhYfD2ZWiE77oAORff4TwoqdL8vBgCA1Ap 1fg6wQEqz1yO/fK9YvHtLyVjmM72TYzuf36M8JoV1wAHpeWnQE+BZvHzJ1+l/a2PrVRF RhZp6mdVbfhD6nNWrxDJQrST/fAzTRBr34aNH9S6H93kTPHMNzF+8EwvBrBCnoiNXuXO k+bcEYloUgI1xlvDFsLUUCdJTEHeox9dDywpq6gruST+a01R7h2lGFnHSsrBrRdutZaK RPtA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b="DH/50Tu1"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id k5si1572368edl.259.2021.11.02.21.30.21; Tue, 02 Nov 2021 21:30:51 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b="DH/50Tu1"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231137AbhKCEZK (ORCPT + 99 others); Wed, 3 Nov 2021 00:25:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33606 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230483AbhKCEZJ (ORCPT ); Wed, 3 Nov 2021 00:25:09 -0400 Received: from mail-pg1-x549.google.com (mail-pg1-x549.google.com [IPv6:2607:f8b0:4864:20::549]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 87A8AC061714 for ; Tue, 2 Nov 2021 21:22:33 -0700 (PDT) Received: by mail-pg1-x549.google.com with SMTP id p20-20020a63fe14000000b002cc2a31eaf6so903713pgh.6 for ; Tue, 02 Nov 2021 21:22:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:message-id:mime-version:subject:from:to:cc; bh=0XauQlZsaPUfyum8gatBpe8x8WpyNCmm8SdAdVAZ9Qo=; b=DH/50Tu1YmUDH6wSMIfrdQahebDs+g8pBwDxf7xOVKI/RwroMkffOccH2HgZwPuNmX Lbt6kJ8e8Ao2YMbgirpGdSlk8+X32EBih0w5+D9PlteoIZGgQP9lURxFcIgQ98+SniVk e195YnEcNZqSYWNfmQOLn9wWCwmlNzFKxYWXWBuNSPq94vOna3SNVhsXBJLX/CUJ9RsS SdJ/TzLe1zkiSwdMcPwsZD2/SU0Lcu+3XZH/yOergrpIBjWWwHSi2BJihKBeWjMgZxul bB/Zl8iwByCbyls2F9afcYkALfZeuEsyE01aaSouD5j3mogNY1MSU5PPM9Fw1N9qG6tA RaTg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc; bh=0XauQlZsaPUfyum8gatBpe8x8WpyNCmm8SdAdVAZ9Qo=; b=kNvI4qR/XxSaKdDTTpyklP7KqVbMk6DEb247GycyHTIVAE70u82HRFKXOmRlGflqCv SM8ZsXwv0YxDrLTRsZkvhaXmmEYkQ6xquAcwdecKppipujF0jvTYcytlrGNhE3ulgkZC FkN+47lMOMc2HzJVIaRflnfwNPzHoM8kRhOUpv1yBJD112qgchj6nzD9gZHn8oxdqa1u l4G1ZN2xlQKLIpXxs2hbGtTaEXji1aSIehEZ3elpc5GOR9BLKD5nVzSCJp4x4VuZMW8W p2s3k7mzKmBw+R8n2Ez7S9GbKdzNlCUdmFVu0sjRJJTJ2Rxv3iS2sQEKV9d7BYZ+GWAz 5uDw== X-Gm-Message-State: AOAM533eKEY/CuyPjfCUJDxugH06voh4rZ0fMtOG0gH2GEptPyW+Mpqr Thkamyz6Q41ymcFUphdVKrj1U252UY35vg== X-Received: from dlatypov.svl.corp.google.com ([2620:15c:2cd:202:8673:8d2f:d693:6af]) (user=dlatypov job=sendgmr) by 2002:aa7:8016:0:b0:481:2405:e72b with SMTP id j22-20020aa78016000000b004812405e72bmr9625182pfi.54.1635913352981; Tue, 02 Nov 2021 21:22:32 -0700 (PDT) Date: Tue, 2 Nov 2021 21:22:28 -0700 Message-Id: <20211103042228.586967-1-dlatypov@google.com> Mime-Version: 1.0 X-Mailer: git-send-email 2.33.1.1089.g2158813163f-goog Subject: [PATCH v2] kunit: add run_checks.py script to validate kunit changes From: Daniel Latypov To: brendanhiggins@google.com, davidgow@google.com Cc: linux-kernel@vger.kernel.org, kunit-dev@googlegroups.com, linux-kselftest@vger.kernel.org, skhan@linuxfoundation.org, Daniel Latypov Content-Type: text/plain; charset="UTF-8" Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This formalizes the checks KUnit maintainers have been running (or in other cases: forgetting to run). This script also runs them all in parallel to minimize friction (pytype can be fairly slow, but not slower than running kunit.py). Example output: $ ./tools/testing/kunit/run_checks.py Waiting on 4 checks (kunit_tool_test.py, kunit smoke test, pytype, mypy)... kunit_tool_test.py: PASSED mypy: PASSED pytype: PASSED kunit smoke test: PASSED On failure or timeout (5 minutes), it'll dump out the stdout/stderr. E.g. adding in a type-checking error: mypy: FAILED > kunit.py:54: error: Name 'nonexistent_function' is not defined > Found 1 error in 1 file (checked 8 source files) mypy and pytype are two Python type-checkers and must be installed. This file treats them as optional and will mark them as SKIPPED if not installed. This tool also runs `kunit.py run --kunitconfig=lib/kunit` to run KUnit's own KUnit tests and to verify KUnit kernel code and kunit.py play nicely together. It uses --build_dir=kunit_run_checks so as not to clobber the default build_dir, which helps make it faster by reducing the need to rebuild, esp. if you're been passing in --arch instead of using UML. Signed-off-by: Daniel Latypov Reviewed-by: David Gow --- tools/testing/kunit/run_checks.py | 81 +++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100755 tools/testing/kunit/run_checks.py diff --git a/tools/testing/kunit/run_checks.py b/tools/testing/kunit/run_checks.py new file mode 100755 index 000000000000..4f32133ed77c --- /dev/null +++ b/tools/testing/kunit/run_checks.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 +# +# This file runs some basic checks to verify kunit works. +# It is only of interest if you're making changes to KUnit itself. +# +# Copyright (C) 2021, Google LLC. +# Author: Daniel Latypov + +from concurrent import futures +import datetime +import os +import shutil +import subprocess +import sys +import textwrap +from typing import Dict, List, Sequence, Tuple + +ABS_TOOL_PATH = os.path.abspath(os.path.dirname(__file__)) +TIMEOUT = datetime.timedelta(minutes=5).total_seconds() + +commands: Dict[str, Sequence[str]] = { + 'kunit_tool_test.py': ['./kunit_tool_test.py'], + 'kunit smoke test': ['./kunit.py', 'run', '--kunitconfig=lib/kunit', '--build_dir=kunit_run_checks'], + 'pytype': ['/bin/sh', '-c', 'pytype *.py'], + 'mypy': ['/bin/sh', '-c', 'mypy *.py'], +} + +# The user might not have mypy or pytype installed, skip them if so. +# Note: you can install both via `$ pip install mypy pytype` +necessary_deps : Dict[str, str] = { + 'pytype': 'pytype', + 'mypy': 'mypy', +} + +def main(argv: Sequence[str]) -> None: + if argv: + raise RuntimeError('This script takes no arguments') + + future_to_name: Dict[futures.Future, str] = {} + executor = futures.ThreadPoolExecutor(max_workers=len(commands)) + for name, argv in commands.items(): + if name in necessary_deps and shutil.which(necessary_deps[name]) is None: + print(f'{name}: SKIPPED, {necessary_deps[name]} not in $PATH') + continue + f = executor.submit(run_cmd, argv) + future_to_name[f] = name + + has_failures = False + print(f'Waiting on {len(future_to_name)} checks ({", ".join(future_to_name.values())})...') + for f in futures.as_completed(future_to_name.keys()): + name = future_to_name[f] + ex = f.exception() + if not ex: + print(f'{name}: PASSED') + continue + + has_failures = True + if isinstance(ex, subprocess.TimeoutExpired): + print(f'{name}: TIMED OUT') + elif isinstance(ex, subprocess.CalledProcessError): + print(f'{name}: FAILED') + else: + print('{name}: unexpected exception: {ex}') + continue + + output = ex.output + if output: + print(textwrap.indent(output.decode(), '> ')) + executor.shutdown() + + if has_failures: + sys.exit(1) + + +def run_cmd(argv: Sequence[str]): + subprocess.check_output(argv, stderr=subprocess.STDOUT, cwd=ABS_TOOL_PATH, timeout=TIMEOUT) + + +if __name__ == '__main__': + main(sys.argv[1:]) base-commit: 52a5d80a2225e2d0b2a8f4656b76aead2a443b2a -- 2.33.1.1089.g2158813163f-goog