From patchwork Sun Nov 15 08:48:04 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104190 Received: from mail-wr1-f52.google.com (mail-wr1-f52.google.com [209.85.221.52]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.4367.1794732532014522822 for ; Sun, 15 Nov 2026 00:48:52 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=bq4MGuT5; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.52, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f52.google.com with SMTP id ffacd0b85a97d-498f5fa4f70so2749992f8f.0 for ; Sun, 15 Nov 2026 00:48:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732530; x=1795337330; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=WvJlynGnWWoT8SaOwiitnm2zwS8mu77Rhhykk8x7x7s=; b=bq4MGuT5/eC32RUv86SQJZsVUnLS8aMJUCuJxySsjlaUEtNXRD+OnBY2FS3C5aKT2i wWQCcN16v7Obo8LtYf/Icbl7kov0Lcle096p0ysctIdd7G12MB+1smbFWEPaQN6eS2lp YjNZpgVeQeTarHAODfxb6TLpPSfoonvdAkjnA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732530; x=1795337330; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to:content-type; bh=WvJlynGnWWoT8SaOwiitnm2zwS8mu77Rhhykk8x7x7s=; b=C7MNar8ywYDjXodZenbhfbIGW2hP0drrI4Sk3iNfMhps8qVPRZmeh90oiRAjwjncks ao85wrts3ziWMELKRnRUzqfWPO75QbZHol+C147Xgu2ttGP1A4Q1ZkUBnSvbJldUyxds L3HSmEes8jxeeN0sW/AXoooOq/zvMvi2kEQnY6Qb3OYR6t7W2mUtfu6GztKeR1+N3aP/ j9k/VGCodZyGauw2dSxWq1OuF6eQ26sy53mrVYUDuTEkabkfjY3vZVylBuSMmL+CthXf 6jdXELjhNg6mfpvUcO/fNZys1YX1CKp1lnth/1XJpauleO6zF0hfIR4sptJ88BLeAFIx EPpg== X-Gm-Message-State: APuU4Z+DQeyZBvG6h+0NJCjy+hNbWRbCVDS+SzfiCPnNHax4+WRtsKw0 IVrbtmlu4P7/PSg0ngOfnSH9wfywvftVnonIfz7c66/rF6JDINq2W5pIekpfSqJ5NV0fKuo2Rfz W4hhHmsY= X-Gm-Gg: AYBFou35Gh7BeHSLQH1ejpUKrTyN6IwaE0hDWSKxiuDM9o48uV0RLgW314XocMAPqoO D80nxfj6aSAcWGmEqn5R+bQ7GoPSy6Y82ZLQaK5Jzjwp2Bt+PsMQ6nI7TasP+vpPKDxZ0UYdpWL 9Zy6rsTLqJHh86rNdXdSwiqGU+T9+3jjxmFE7//TEOUUXbZEyu/XeoiIIKFbaUbJSR6NHc56lye s5izTympzbZzmPSFGMhGLOOCYSU03QvCEBjcqJ7dD+GHbVo4ZNUUf/3hWIZSjvwHMwnYX8/e4fq 0L5fldfbCPcU4eCNNEdZHXrtgIWY5xox6dopQkfaGLoRkegP4yEhWK88fQN5S8H0SJmWPkOpw9W uV2S7ZgHFEidPwQzhgjTB6WpHxA13LFidyi0quW2AEiYauZGumUI3HbiwsxXsnKnJka0ePta85g jYkUex5W0hKi8LF7PZ+pQyCF6+KvSuh3j7hzq+ipKdkx0GsGEQY41k+5NPQHuwP9Vup8j3J7gx9 sYivOq8OnF92WiAz2EXfB0/vWt491mpmDGiT2MF4xfLgLjOdp8DHw9BaI1kvVc6fUCEMVlCsart qU8upajK7lVf10z8rRqtmvKVDgP1nPbAVCKdvd0i43MCfUVCmkYZZZDNcg== X-Received: by 2002:a05:6000:4541:b0:48f:bb86:cc03 with SMTP id ffacd0b85a97d-49c70ed7ff4mr10833893f8f.11.1794732529802; Sun, 15 Nov 2026 00:48:49 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.48.48 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:48:48 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 01/41] oeqa/loader: Drop code for pre python 3.5 Date: Sun, 15 Nov 2026 08:48:04 +0000 Message-ID: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:48:58 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250232 We require python 3.9+ now so drop this dead code. Signed-off-by: Richard Purdie --- meta/lib/oeqa/core/loader.py | 37 +++++++++++------------------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/meta/lib/oeqa/core/loader.py b/meta/lib/oeqa/core/loader.py index d12d5a055cc..84448325804 100644 --- a/meta/lib/oeqa/core/loader.py +++ b/meta/lib/oeqa/core/loader.py @@ -322,29 +322,14 @@ class OETestLoader(unittest.TestLoader): return (load_module, load_underscore) - # XXX After Python 3.5, remove backward compatibility hacks for - # use_load_tests deprecation via *args and **kws. See issue 16662. - if sys.version_info >= (3,5): - def loadTestsFromModule(self, module, *args, pattern=None, **kws): - """ - Returns a suite of all tests cases contained in module. - """ - load_module, load_underscore = self._filterModule(module) - - if load_module or load_underscore: - return super(OETestLoader, self).loadTestsFromModule( - module, *args, pattern=pattern, **kws) - else: - return self.suiteClass() - else: - def loadTestsFromModule(self, module, use_load_tests=True): - """ - Returns a suite of all tests cases contained in module. - """ - load_module, load_underscore = self._filterModule(module) - - if load_module or load_underscore: - return super(OETestLoader, self).loadTestsFromModule( - module, use_load_tests) - else: - return self.suiteClass() + def loadTestsFromModule(self, module, *args, pattern=None, **kws): + """ + Returns a suite of all tests cases contained in module. + """ + load_module, load_underscore = self._filterModule(module) + + if load_module or load_underscore: + return super(OETestLoader, self).loadTestsFromModule( + module, *args, pattern=pattern, **kws) + else: + return self.suiteClass() From patchwork Sun Nov 15 08:48:05 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104192 Received: from mail-wr1-f41.google.com (mail-wr1-f41.google.com [209.85.221.41]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4313.1794732534660300965 for ; Sun, 15 Nov 2026 00:48:55 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=N4sDP7CZ; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.41, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f41.google.com with SMTP id ffacd0b85a97d-498f5fa4f70so2750017f8f.0 for ; Sun, 15 Nov 2026 00:48:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732533; x=1795337333; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=Ic4PhKDKC/l+5YXO7nJhqLyNk+JKsmErvbla0bTtFWE=; b=N4sDP7CZsbPCKOcdvfTNvTIXcoWAXtOIzkLLZO9hkPhKqveZKzmusW6LFPRqUUZEDw TtiLrKlSpSyoAMSm9bKhyGcKpNPtZmN1liasEv9HYqLiNpC3UF97YAk7R/cPYcp1EJfB NyUxev4r/f4yRxksi7R3VhizkuUDawNMvzlDA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732533; x=1795337333; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=Ic4PhKDKC/l+5YXO7nJhqLyNk+JKsmErvbla0bTtFWE=; b=tTOjERlSBFeDUo6mtPT2A6B9jomO5XJJ4H50ldXjE9PHWTI031hNjCbqRLkX+w6IbB ii+qW0xijgiAMNEFyp5PcRe5MKtpnBaGDBMzHKrB7BU7w6BdmGAE7Ejoua6ldMRMi8z/ 81DdPpx6rLY8WIeewnjjfvQWtDA2AGkRhzbkhpiddNu9yEKvI9WSMTsiD1QO7U2SmEM1 bPIEhWofH33SS8metdxvu8zFqKpPtdscM6V66ZGYPw5XXrzcMRmiY0PSa4elknya1W/b kh1krq75LMRPj6XhZXFskYFxKLiQQXH7mzUiY96VHBbmajwkFr4LS9VpU62XHPlOtjPX 1oxw== X-Gm-Message-State: APuU4Z+P5frQuPxr/n+yn0zgQwzkyIjw2ZszGV36HRAqK1u9nfZM8bk+ JmcyO8M9bmxeiQXutV0c7SSDcgBfN23GKns2qsTu1HjY2DQCGEsiKplQ+rJSbJyUIN5bkXmKoI4 JCm6Dd0s= X-Gm-Gg: AYBFou3oGaN5gVWMuntMut1/LGvyweoIOCgHRNzRvCpjIocXUOl28YgAwilIO7Da20m zr8+uCz2QcRd04JfB4vOcmzWbCMJIyGhSbyNBh497WnltTAgX2s6mrmvPX/sKq8Pi+w5RneN0Rz /X2JeUklwIBxEZyYob8/JRQiDrybGfzcxzdfNU6K2WPeOSfM2lCO6i/V1VtM8JdZdESWHorE+pD wtJKwthVRkIvh3sWlq11gQqVNKTYjxZF2Y77goMUKohsSB83kVWF6WZQ1eNLNpfZJyovgNM84nS xazCJG146brfpA3HDwbePk2P6W02x0GQo+aCalg6wSor1omeUW/tZyFOSc28nhTLD3svoWrp8Jc ws9gRsrQu0LC0IMlwowSC1XYq+rwnWdEunBbdl5K6NP8YnMPAEkVCkqVjLkA+T5gJ5On6SGeloJ kgD8641HsNqeVOcX9IjqamQJFcs/xV5NZNDeTXJpdhn5tehPneNcz+s4IMXo/GZZMhO83Gb1gbE GZwkqK+DqsNdGxiQgXpa+WE0DVL++ix3g70KUVViu9gCwBI+PTN86AnJr8NpTHS+zsU94XWGc0i Q25q7CqSVEFOn7lrtvDyK91mT8CU3TOKdXGKBLzNq2EIRFyVKLoPLFOhIw== X-Received: by 2002:a5d:5f08:0:b0:48d:f36e:ccc0 with SMTP id ffacd0b85a97d-49c6a645d4fmr15264347f8f.0.1794732532254; Sun, 15 Nov 2026 00:48:52 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.48.49 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:48:50 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 02/41] lib: Simplify super() calls Date: Sun, 15 Nov 2026 08:48:05 +0000 Message-ID: <20261115084845.701136-2-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:00 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250234 python3 allows the super() calls to be simplified, make this change through our python code. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oe/classutils.py | 2 +- meta/lib/oe/package_manager/common_deb_ipk.py | 2 +- meta/lib/oe/package_manager/deb/__init__.py | 2 +- meta/lib/oe/package_manager/deb/rootfs.py | 4 ++-- meta/lib/oe/package_manager/deb/sdk.py | 2 +- meta/lib/oe/package_manager/ipk/__init__.py | 4 ++-- meta/lib/oe/package_manager/ipk/rootfs.py | 4 ++-- meta/lib/oe/package_manager/ipk/sdk.py | 2 +- meta/lib/oe/package_manager/rpm/__init__.py | 2 +- meta/lib/oe/package_manager/rpm/rootfs.py | 2 +- meta/lib/oe/package_manager/rpm/sdk.py | 2 +- meta/lib/oe/terminal.py | 2 +- meta/lib/oeqa/buildperf/base.py | 20 +++++++++---------- meta/lib/oeqa/controllers/controllerimage.py | 6 +++--- meta/lib/oeqa/core/decorator/depends.py | 2 +- meta/lib/oeqa/core/loader.py | 6 +++--- meta/lib/oeqa/core/runner.py | 18 ++++++++--------- meta/lib/oeqa/core/target/qemu.py | 2 +- meta/lib/oeqa/core/target/serial.py | 2 +- meta/lib/oeqa/core/target/ssh.py | 2 +- meta/lib/oeqa/core/utils/concurrencytest.py | 6 +++--- meta/lib/oeqa/oetest.py | 12 +++++------ meta/lib/oeqa/runtime/case.py | 4 ++-- meta/lib/oeqa/runtime/context.py | 6 +++--- meta/lib/oeqa/runtime/loader.py | 2 +- meta/lib/oeqa/sdk/context.py | 8 ++++---- meta/lib/oeqa/sdk/utils/sdkbuildproject.py | 4 ++-- meta/lib/oeqa/selftest/case.py | 10 +++++----- .../selftest/cases/_sstatetests_noauto.py | 2 +- meta/lib/oeqa/selftest/cases/bblayers.py | 2 +- meta/lib/oeqa/selftest/cases/bblock.py | 2 +- meta/lib/oeqa/selftest/cases/devtool.py | 8 ++++---- meta/lib/oeqa/selftest/cases/esdk.py | 2 +- meta/lib/oeqa/selftest/cases/gotoolchain.py | 4 ++-- .../oeqa/selftest/cases/kerneldevelopment.py | 6 +++--- meta/lib/oeqa/selftest/cases/layerappend.py | 2 +- meta/lib/oeqa/selftest/cases/manifest.py | 2 +- meta/lib/oeqa/selftest/cases/meta_ide.py | 4 ++-- meta/lib/oeqa/selftest/cases/pkgdata.py | 2 +- meta/lib/oeqa/selftest/cases/prservice.py | 2 +- meta/lib/oeqa/selftest/cases/recipetool.py | 8 ++++---- meta/lib/oeqa/selftest/cases/runqemu.py | 4 ++-- meta/lib/oeqa/selftest/cases/runtime_test.py | 4 ++-- meta/lib/oeqa/selftest/cases/sstatetests.py | 2 +- meta/lib/oeqa/selftest/cases/wic.py | 4 ++-- meta/lib/oeqa/selftest/context.py | 8 ++++---- meta/lib/oeqa/targetcontrol.py | 8 ++++---- meta/lib/oeqa/utils/dump.py | 4 ++-- meta/lib/oeqa/utils/targetbuild.py | 4 ++-- meta/lib/patchtest/tests/base.py | 4 ++-- scripts/lib/argparse_oe.py | 14 ++++++------- scripts/lib/buildstats.py | 2 +- scripts/lib/checklayer/context.py | 2 +- scripts/lib/devtool/__init__.py | 2 +- scripts/test-remote-image | 4 ++-- 55 files changed, 126 insertions(+), 126 deletions(-) mode change 100755 => 100644 scripts/test-remote-image diff --git a/meta/lib/oe/classutils.py b/meta/lib/oe/classutils.py index ec3f6ad720f..a73e0ebb1b5 100644 --- a/meta/lib/oe/classutils.py +++ b/meta/lib/oe/classutils.py @@ -25,7 +25,7 @@ control over whether the class will be added to the registry (e.g. to keep abstract base classes out of the registry).""" priority = 0 def __init__(cls, name, bases, attrs): - super(ClassRegistry, cls).__init__(name, bases, attrs) + super().__init__(name, bases, attrs) try: if not cls.implemented: return diff --git a/meta/lib/oe/package_manager/common_deb_ipk.py b/meta/lib/oe/package_manager/common_deb_ipk.py index b93089e523a..cb337cce462 100644 --- a/meta/lib/oe/package_manager/common_deb_ipk.py +++ b/meta/lib/oe/package_manager/common_deb_ipk.py @@ -18,7 +18,7 @@ class OpkgDpkgPM(PackageManager): """ This is an abstract class. Do not instantiate this directly. """ - super(OpkgDpkgPM, self).__init__(d, target_rootfs) + super().__init__(d, target_rootfs) def package_info(self, pkg): """ diff --git a/meta/lib/oe/package_manager/deb/__init__.py b/meta/lib/oe/package_manager/deb/__init__.py index e878401468b..c2325f17bd7 100644 --- a/meta/lib/oe/package_manager/deb/__init__.py +++ b/meta/lib/oe/package_manager/deb/__init__.py @@ -115,7 +115,7 @@ class PMPkgsList(PkgsList): class DpkgPM(OpkgDpkgPM): def __init__(self, d, target_rootfs, archs, base_archs, apt_conf_dir=None, deb_repo_workdir="oe-rootfs-repo", filterbydependencies=True): - super(DpkgPM, self).__init__(d, target_rootfs) + super().__init__(d, target_rootfs) self.deploy_dir = oe.path.join(self.d.getVar('WORKDIR'), deb_repo_workdir) create_packages_dir(self.d, self.deploy_dir, d.getVar("DEPLOY_DIR_DEB"), "package_write_deb", filterbydependencies) diff --git a/meta/lib/oe/package_manager/deb/rootfs.py b/meta/lib/oe/package_manager/deb/rootfs.py index d2b077cc374..df3932b0294 100644 --- a/meta/lib/oe/package_manager/deb/rootfs.py +++ b/meta/lib/oe/package_manager/deb/rootfs.py @@ -14,7 +14,7 @@ from oe.package_manager.deb import DpkgPM class DpkgOpkgRootfs(Rootfs): def __init__(self, d, progress_reporter=None, logcatcher=None): - super(DpkgOpkgRootfs, self).__init__(d, progress_reporter, logcatcher) + super().__init__(d, progress_reporter, logcatcher) def _get_pkgs_postinsts(self, status_file): def _get_pkg_depends_list(pkg_depends): @@ -124,7 +124,7 @@ class DpkgOpkgRootfs(Rootfs): class PkgRootfs(DpkgOpkgRootfs): def __init__(self, d, manifest_dir, progress_reporter=None, logcatcher=None): - super(PkgRootfs, self).__init__(d, progress_reporter, logcatcher) + super().__init__(d, progress_reporter, logcatcher) self.log_check_regex = '^E:' self.log_check_expected_regexes = \ [ diff --git a/meta/lib/oe/package_manager/deb/sdk.py b/meta/lib/oe/package_manager/deb/sdk.py index 46dcc16cc74..f4134c21300 100644 --- a/meta/lib/oe/package_manager/deb/sdk.py +++ b/meta/lib/oe/package_manager/deb/sdk.py @@ -14,7 +14,7 @@ from oe.package_manager.deb.manifest import PkgManifest class PkgSdk(Sdk): def __init__(self, d, manifest_dir=None): - super(PkgSdk, self).__init__(d, manifest_dir) + super().__init__(d, manifest_dir) self.target_conf_dir = os.path.join(self.d.getVar("APTCONF_TARGET"), "apt") self.host_conf_dir = os.path.join(self.d.getVar("APTCONF_TARGET"), "apt-sdk") diff --git a/meta/lib/oe/package_manager/ipk/__init__.py b/meta/lib/oe/package_manager/ipk/__init__.py index 6c0b896a086..489fe4d3796 100644 --- a/meta/lib/oe/package_manager/ipk/__init__.py +++ b/meta/lib/oe/package_manager/ipk/__init__.py @@ -67,7 +67,7 @@ class OpkgIndexer(Indexer): class PMPkgsList(PkgsList): def __init__(self, d, rootfs_dir): - super(PMPkgsList, self).__init__(d, rootfs_dir) + super().__init__(d, rootfs_dir) config_file = d.getVar("IPKGCONF_TARGET") self.opkg_cmd = bb.utils.which(os.getenv('PATH'), "opkg") @@ -95,7 +95,7 @@ class PMPkgsList(PkgsList): class OpkgPM(OpkgDpkgPM): def __init__(self, d, target_rootfs, config_file, archs, task_name='target', ipk_repo_workdir="oe-rootfs-repo", filterbydependencies=True, prepare_index=True): - super(OpkgPM, self).__init__(d, target_rootfs) + super().__init__(d, target_rootfs) self.config_file = config_file self.pkg_archs = archs diff --git a/meta/lib/oe/package_manager/ipk/rootfs.py b/meta/lib/oe/package_manager/ipk/rootfs.py index a760000d3fa..3509413d87b 100644 --- a/meta/lib/oe/package_manager/ipk/rootfs.py +++ b/meta/lib/oe/package_manager/ipk/rootfs.py @@ -15,7 +15,7 @@ from oe.package_manager.ipk import OpkgPM class DpkgOpkgRootfs(Rootfs): def __init__(self, d, progress_reporter=None, logcatcher=None): - super(DpkgOpkgRootfs, self).__init__(d, progress_reporter, logcatcher) + super().__init__(d, progress_reporter, logcatcher) def _get_pkgs_postinsts(self, status_file): def _get_pkg_depends_list(pkg_depends): @@ -125,7 +125,7 @@ class DpkgOpkgRootfs(Rootfs): class PkgRootfs(DpkgOpkgRootfs): def __init__(self, d, manifest_dir, progress_reporter=None, logcatcher=None): - super(PkgRootfs, self).__init__(d, progress_reporter, logcatcher) + super().__init__(d, progress_reporter, logcatcher) self.log_check_regex = '(exit 1|Collected errors)' self.manifest = PkgManifest(d, manifest_dir) diff --git a/meta/lib/oe/package_manager/ipk/sdk.py b/meta/lib/oe/package_manager/ipk/sdk.py index 9a7ff9f0c9e..3c916ccead5 100644 --- a/meta/lib/oe/package_manager/ipk/sdk.py +++ b/meta/lib/oe/package_manager/ipk/sdk.py @@ -14,7 +14,7 @@ from oe.package_manager.ipk import OpkgPM class PkgSdk(Sdk): def __init__(self, d, manifest_dir=None): - super(PkgSdk, self).__init__(d, manifest_dir) + super().__init__(d, manifest_dir) # In sdk_list_installed_packages the call to opkg is hardcoded to # always use IPKGCONF_TARGET and there's no exposed API to change this diff --git a/meta/lib/oe/package_manager/rpm/__init__.py b/meta/lib/oe/package_manager/rpm/__init__.py index 3460a6bb35e..c2595f3b3c6 100644 --- a/meta/lib/oe/package_manager/rpm/__init__.py +++ b/meta/lib/oe/package_manager/rpm/__init__.py @@ -64,7 +64,7 @@ class RpmPM(PackageManager): rpm_repo_workdir="oe-rootfs-repo", filterbydependencies=True, needfeed=True): - super(RpmPM, self).__init__(d, target_rootfs) + super().__init__(d, target_rootfs) self.target_vendor = target_vendor self.task_name = task_name if arch_var == None: diff --git a/meta/lib/oe/package_manager/rpm/rootfs.py b/meta/lib/oe/package_manager/rpm/rootfs.py index 8d54b5ab48c..19ec2e47906 100644 --- a/meta/lib/oe/package_manager/rpm/rootfs.py +++ b/meta/lib/oe/package_manager/rpm/rootfs.py @@ -12,7 +12,7 @@ from oe.package_manager.rpm import RpmPM class PkgRootfs(Rootfs): def __init__(self, d, manifest_dir, progress_reporter=None, logcatcher=None): - super(PkgRootfs, self).__init__(d, progress_reporter, logcatcher) + super().__init__(d, progress_reporter, logcatcher) self.log_check_regex = r'(unpacking of archive failed|Cannot find package'\ r'|exit 1\b|ERROR: |Error: |Error |ERROR '\ r'|Failed |Failed: |Failed$|Failed\(\d+\):)' diff --git a/meta/lib/oe/package_manager/rpm/sdk.py b/meta/lib/oe/package_manager/rpm/sdk.py index ea79fe050bc..b74d566690f 100644 --- a/meta/lib/oe/package_manager/rpm/sdk.py +++ b/meta/lib/oe/package_manager/rpm/sdk.py @@ -13,7 +13,7 @@ from oe.package_manager.rpm import RpmPM class PkgSdk(Sdk): def __init__(self, d, manifest_dir=None, rpm_workdir="oe-sdk-repo"): - super(PkgSdk, self).__init__(d, manifest_dir) + super().__init__(d, manifest_dir) self.target_manifest = PkgManifest(d, self.manifest_dir, Manifest.MANIFEST_TYPE_SDK_TARGET) diff --git a/meta/lib/oe/terminal.py b/meta/lib/oe/terminal.py index a8d3840153f..f762ef6c8c7 100644 --- a/meta/lib/oe/terminal.py +++ b/meta/lib/oe/terminal.py @@ -24,7 +24,7 @@ class Registry(oe.classutils.ClassRegistry): command = None def __init__(cls, name, bases, attrs): - super(Registry, cls).__init__(name.lower(), bases, attrs) + super().__init__(name.lower(), bases, attrs) @property def implemented(cls): diff --git a/meta/lib/oeqa/buildperf/base.py b/meta/lib/oeqa/buildperf/base.py index 5d656c781a7..944314d7c29 100644 --- a/meta/lib/oeqa/buildperf/base.py +++ b/meta/lib/oeqa/buildperf/base.py @@ -90,7 +90,7 @@ class BuildPerfTestResult(unittest.TextTestResult): test_run_queue = [] def __init__(self, out_dir, *args, **kwargs): - super(BuildPerfTestResult, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.out_dir = out_dir self.hostname = socket.gethostname() @@ -100,30 +100,30 @@ class BuildPerfTestResult(unittest.TextTestResult): def addSuccess(self, test): """Record results from successful tests""" - super(BuildPerfTestResult, self).addSuccess(test) + super().addSuccess(test) self.successes.append(test) def addError(self, test, err): """Record results from crashed test""" test.err = err - super(BuildPerfTestResult, self).addError(test, err) + super().addError(test, err) def addFailure(self, test, err): """Record results from failed test""" test.err = err - super(BuildPerfTestResult, self).addFailure(test, err) + super().addFailure(test, err) def addExpectedFailure(self, test, err): """Record results from expectedly failed test""" test.err = err - super(BuildPerfTestResult, self).addExpectedFailure(test, err) + super().addExpectedFailure(test, err) def startTest(self, test): """Pre-test hook""" test.base_dir = self.out_dir log.info("Executing test %s: %s", test.name, test.shortDescription()) self.stream.write(datetime.now().strftime("[%Y-%m-%d %H:%M:%S] ")) - super(BuildPerfTestResult, self).startTest(test) + super().startTest(test) def startTestRun(self): """Pre-run hook""" @@ -248,7 +248,7 @@ class BuildPerfTestCase(unittest.TestCase): build_target = None def __init__(self, *args, **kwargs): - super(BuildPerfTestCase, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.name = self._testMethodName self.base_dir = None self.start_time = None @@ -268,7 +268,7 @@ class BuildPerfTestCase(unittest.TestCase): return os.path.join(self.base_dir, self.name + '.tmp') def shortDescription(self): - return super(BuildPerfTestCase, self).shortDescription() or "" + return super().shortDescription() or "" def setUp(self): """Set-up fixture for each test""" @@ -285,7 +285,7 @@ class BuildPerfTestCase(unittest.TestCase): def run(self, *args, **kwargs): """Run test""" self.start_time = datetime.now() - super(BuildPerfTestCase, self).run(*args, **kwargs) + super().run(*args, **kwargs) self.elapsed_time = datetime.now() - self.start_time def run_cmd(self, cmd): @@ -496,7 +496,7 @@ class BuildPerfTestRunner(unittest.TextTestRunner): sortTestMethodsUsing = None def __init__(self, out_dir, *args, **kwargs): - super(BuildPerfTestRunner, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.out_dir = out_dir def _makeResult(self): diff --git a/meta/lib/oeqa/controllers/controllerimage.py b/meta/lib/oeqa/controllers/controllerimage.py index 78a4aaff873..e71143bdacd 100644 --- a/meta/lib/oeqa/controllers/controllerimage.py +++ b/meta/lib/oeqa/controllers/controllerimage.py @@ -29,7 +29,7 @@ class ControllerImageHardwareTarget(oeqa.targetcontrol.BaseTarget, metaclass=ABC supported_image_fstypes = ['tar.gz', 'tar.bz2'] def __init__(self, d): - super(ControllerImageHardwareTarget, self).__init__(d) + super().__init__(d) # target ip addr = d.getVar("TEST_TARGET_IP") or bb.fatal('Please set TEST_TARGET_IP with the IP address of the machine you want to run the tests on.') @@ -119,7 +119,7 @@ class ControllerImageHardwareTarget(oeqa.targetcontrol.BaseTarget, metaclass=ABC def deploy(self): # base class just sets the ssh log file for us - super(ControllerImageHardwareTarget, self).deploy() + super().deploy() self.controller = sshcontrol.SSHControl(ip=self.ip, logfile=self.sshlog, timeout=600, port=self.port) status, output = self.controller.run("cat /etc/controllerimage") if status != 0: @@ -162,7 +162,7 @@ class ControllerImageHardwareTarget(oeqa.targetcontrol.BaseTarget, metaclass=ABC class SystemdbootTarget(ControllerImageHardwareTarget): def __init__(self, d): - super(SystemdbootTarget, self).__init__(d) + super().__init__(d) # this the value we need to set in the LoaderEntryOneShot EFI variable # so the system boots the 'test' bootloader label and not the default # The first four bytes are EFI bits, and the rest is an utf-16le string diff --git a/meta/lib/oeqa/core/decorator/depends.py b/meta/lib/oeqa/core/decorator/depends.py index 33f0841cab0..41a324e61fb 100644 --- a/meta/lib/oeqa/core/decorator/depends.py +++ b/meta/lib/oeqa/core/decorator/depends.py @@ -81,7 +81,7 @@ class OETestDepends(OETestDiscover): attrs = ('depends',) def bind(self, registry, case): - super(OETestDepends, self).bind(registry, case) + super().bind(registry, case) if not registry.get('depends'): registry['depends'] = {} _add_depends(registry['depends'], case, self.depends) diff --git a/meta/lib/oeqa/core/loader.py b/meta/lib/oeqa/core/loader.py index 84448325804..1c964dadae6 100644 --- a/meta/lib/oeqa/core/loader.py +++ b/meta/lib/oeqa/core/loader.py @@ -95,7 +95,7 @@ class OETestLoader(unittest.TestLoader): self._patchCaseClass(self.caseClass) - super(OETestLoader, self).__init__() + super().__init__() def _patchCaseClass(self, testCaseClass): # Adds custom attributes to the OETestCase class @@ -274,7 +274,7 @@ class OETestLoader(unittest.TestLoader): big_suite = self.suiteClass() for path in self.module_paths: _find_duplicated_modules(big_suite, path) - suite = super(OETestLoader, self).discover(path, + suite = super().discover(path, pattern='*.py', top_level_dir=path) big_suite.addTests(suite) @@ -329,7 +329,7 @@ class OETestLoader(unittest.TestLoader): load_module, load_underscore = self._filterModule(module) if load_module or load_underscore: - return super(OETestLoader, self).loadTestsFromModule( + return super().loadTestsFromModule( module, *args, pattern=pattern, **kws) else: return self.suiteClass() diff --git a/meta/lib/oeqa/core/runner.py b/meta/lib/oeqa/core/runner.py index 0d2bc3a3ed0..8ad65facead 100644 --- a/meta/lib/oeqa/core/runner.py +++ b/meta/lib/oeqa/core/runner.py @@ -37,7 +37,7 @@ class OEStreamLogger(object): class OETestResult(_TestResult): def __init__(self, tc, *args, **kwargs): - super(OETestResult, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.successes = [] self.starttime = {} @@ -58,14 +58,14 @@ class OETestResult(_TestResult): # May have been set by concurrencytest if test.id() not in self.starttime: self.starttime[test.id()] = time.time() - super(OETestResult, self).startTest(test) + super().startTest(test) def stopTest(self, test): self.endtime[test.id()] = time.time() if self.buffer: self.logged_output[test.id()] = ( sys.stdout.getvalue(), sys.stderr.getvalue()) - super(OETestResult, self).stopTest(test) + super().stopTest(test) if test.id() in self.progressinfo: self.tc.logger.info(self.progressinfo[test.id()]) @@ -153,25 +153,25 @@ class OETestResult(_TestResult): def addError(self, test, *args, details = None): self.extractExtraResults(test, details = details) - return super(OETestResult, self).addError(test, *args) + return super().addError(test, *args) def addFailure(self, test, *args, details = None): self.extractExtraResults(test, details = details) - return super(OETestResult, self).addFailure(test, *args) + return super().addFailure(test, *args) def addSuccess(self, test, details = None): #Added so we can keep track of successes too self.successes.append((test, None)) self.extractExtraResults(test, details = details) - return super(OETestResult, self).addSuccess(test) + return super().addSuccess(test) def addExpectedFailure(self, test, *args, details = None): self.extractExtraResults(test, details = details) - return super(OETestResult, self).addExpectedFailure(test, *args) + return super().addExpectedFailure(test, *args) def addUnexpectedSuccess(self, test, details = None): self.extractExtraResults(test, details = details) - return super(OETestResult, self).addUnexpectedSuccess(test) + return super().addUnexpectedSuccess(test) def logDetails(self, json_file_dir=None, configuration=None, result_id=None, dump_streams=False): @@ -252,7 +252,7 @@ class OETestRunner(_TestRunner): def __init__(self, tc, *args, **kwargs): kwargs['stream'] = self.streamLoggerClass(tc.logger) - super(OETestRunner, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.tc = tc self.resultclass = OETestResult diff --git a/meta/lib/oeqa/core/target/qemu.py b/meta/lib/oeqa/core/target/qemu.py index 76c1ada02e6..a4f53747b01 100644 --- a/meta/lib/oeqa/core/target/qemu.py +++ b/meta/lib/oeqa/core/target/qemu.py @@ -24,7 +24,7 @@ class OEQemuTarget(OESSHTarget): tmpdir='', dir_image='', boottime=60, serial_ports=2, boot_patterns = defaultdict(str), ovmf=False, tmpfsdir=None, native_sysroot=None, **kwargs): - super(OEQemuTarget, self).__init__(logger, None, server_ip, timeout, + super().__init__(logger, None, server_ip, timeout, user, port) self.server_ip = server_ip diff --git a/meta/lib/oeqa/core/target/serial.py b/meta/lib/oeqa/core/target/serial.py index 7c2cd8b2485..bafcaf9a95d 100644 --- a/meta/lib/oeqa/core/target/serial.py +++ b/meta/lib/oeqa/core/target/serial.py @@ -25,7 +25,7 @@ class OESerialTarget(OETarget): fileHandler.setFormatter(formatter) logger.addHandler(fileHandler) - super(OESerialTarget, self).__init__(logger) + super().__init__(logger) if serialcontrol_ps1: self.target_ps1 = serialcontrol_ps1 diff --git a/meta/lib/oeqa/core/target/ssh.py b/meta/lib/oeqa/core/target/ssh.py index 0ac3ae43889..757ab67580c 100644 --- a/meta/lib/oeqa/core/target/ssh.py +++ b/meta/lib/oeqa/core/target/ssh.py @@ -27,7 +27,7 @@ class OESSHTarget(OETarget): fileHandler.setFormatter(formatter) logger.addHandler(fileHandler) - super(OESSHTarget, self).__init__(logger) + super().__init__(logger) self.ip = ip self.server_ip = server_ip self.server_port = server_port diff --git a/meta/lib/oeqa/core/utils/concurrencytest.py b/meta/lib/oeqa/core/utils/concurrencytest.py index d10f8f7f04c..5a760c620b2 100644 --- a/meta/lib/oeqa/core/utils/concurrencytest.py +++ b/meta/lib/oeqa/core/utils/concurrencytest.py @@ -51,7 +51,7 @@ _all__ = [ class BBThreadsafeForwardingResult(ThreadsafeForwardingResult): def __init__(self, target, semaphore, threadnum, totalinprocess, totaltests, output, finalresult): - super(BBThreadsafeForwardingResult, self).__init__(target, semaphore) + super().__init__(target, semaphore) self.threadnum = threadnum self.totalinprocess = totalinprocess self.totaltests = totaltests @@ -81,7 +81,7 @@ class BBThreadsafeForwardingResult(ThreadsafeForwardingResult): self.semaphore.release() self.finalresult._stderr_buffer = io.StringIO(initial_value=self.outputbuf.getvalue().decode("utf-8")) self.finalresult._stdout_buffer = io.StringIO() - super(BBThreadsafeForwardingResult, self)._add_result_with_semaphore(method, test, *args, **kwargs) + super()._add_result_with_semaphore(method, test, *args, **kwargs) class ProxyTestResult: # a very basic TestResult proxy, in order to modify add* calls @@ -194,7 +194,7 @@ class dummybuf(object): class ConcurrentTestSuite(unittest.TestSuite): def __init__(self, suite, processes, setupfunc, removefunc, bb_vars): - super(ConcurrentTestSuite, self).__init__([suite]) + super().__init__([suite]) self.processes = processes self.setupfunc = setupfunc self.removefunc = removefunc diff --git a/meta/lib/oeqa/oetest.py b/meta/lib/oeqa/oetest.py index bcb6a878c7a..af555bea620 100644 --- a/meta/lib/oeqa/oetest.py +++ b/meta/lib/oeqa/oetest.py @@ -88,7 +88,7 @@ class oeTest(unittest.TestCase): class oeRuntimeTest(oeTest): def __init__(self, methodName='runTest'): self.target = oeRuntimeTest.tc.target - super(oeRuntimeTest, self).__init__(methodName) + super().__init__(methodName) def setUp(self): # Install packages in the DUT @@ -346,7 +346,7 @@ class TestContext(object): class RuntimeTestContext(TestContext): def __init__(self, d, target, exported=False): - super(RuntimeTestContext, self).__init__(d, exported) + super().__init__(d, exported) self.target = target @@ -549,7 +549,7 @@ class RuntimeTestContext(TestContext): class ImageTestContext(RuntimeTestContext): def __init__(self, d, target, host_dumper): - super(ImageTestContext, self).__init__(d, target) + super().__init__(d, target) self.tagexp = d.getVar("TEST_SUITES_TAGS") @@ -570,7 +570,7 @@ class ImageTestContext(RuntimeTestContext): """ pkg_dir = self.d.getVar("TEST_EXTRACTED_DIR") - super(ImageTestContext, self).install_uninstall_packages(test_id, pkg_dir, install) + super().install_uninstall_packages(test_id, pkg_dir, install) class ExportTestContext(RuntimeTestContext): def __init__(self, d, target, exported=False, parsedArgs={}): @@ -580,7 +580,7 @@ class ExportTestContext(RuntimeTestContext): parsedArgs can contain the following: - tag: Filter test by tag. """ - super(ExportTestContext, self).__init__(d, target, exported) + super().__init__(d, target, exported) tag = parsedArgs.get("tag", None) self.tagexp = tag if tag != None else d.getVar("TEST_SUITES_TAGS") @@ -595,4 +595,4 @@ class ExportTestContext(RuntimeTestContext): export_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) extracted_dir = self.d.getVar("TEST_EXPORT_EXTRACTED_DIR") pkg_dir = os.path.join(export_dir, extracted_dir) - super(ExportTestContext, self).install_uninstall_packages(test_id, pkg_dir, install) + super().install_uninstall_packages(test_id, pkg_dir, install) diff --git a/meta/lib/oeqa/runtime/case.py b/meta/lib/oeqa/runtime/case.py index af1e3ca4ab3..4a6a0a1b816 100644 --- a/meta/lib/oeqa/runtime/case.py +++ b/meta/lib/oeqa/runtime/case.py @@ -15,11 +15,11 @@ class OERuntimeTestCase(OETestCase): target = None def setUp(self): - super(OERuntimeTestCase, self).setUp() + super().setUp() install_package(self) def tearDown(self): - super(OERuntimeTestCase, self).tearDown() + super().tearDown() uninstall_package(self) def run_network_serialdebug(target): diff --git a/meta/lib/oeqa/runtime/context.py b/meta/lib/oeqa/runtime/context.py index daabc449109..0763fb25ac0 100644 --- a/meta/lib/oeqa/runtime/context.py +++ b/meta/lib/oeqa/runtime/context.py @@ -21,7 +21,7 @@ class OERuntimeTestContext(OETestContext): def __init__(self, td, logger, target, image_packages, extract_dir): - super(OERuntimeTestContext, self).__init__(td, logger) + super().__init__(td, logger) self.target = target self.image_packages = image_packages @@ -56,7 +56,7 @@ class OERuntimeTestContextExecutor(OETestContextExecutor): default_extract_dir = 'packages/extracted' def register_commands(self, logger, subparsers): - super(OERuntimeTestContextExecutor, self).register_commands(logger, subparsers) + super().register_commands(logger, subparsers) runtime_group = self.parser.add_argument_group('runtime options') @@ -204,7 +204,7 @@ class OERuntimeTestContextExecutor(OETestContextExecutor): if not args.packages_manifest: raise TypeError('Manifest file not provided') - super(OERuntimeTestContextExecutor, self)._process_args(logger, args) + super()._process_args(logger, args) td = self.tc_kwargs['init']['td'] diff --git a/meta/lib/oeqa/runtime/loader.py b/meta/lib/oeqa/runtime/loader.py index 7041ddfde82..e999d812ebb 100644 --- a/meta/lib/oeqa/runtime/loader.py +++ b/meta/lib/oeqa/runtime/loader.py @@ -11,7 +11,7 @@ class OERuntimeTestLoader(OETestLoader): caseClass = OERuntimeTestCase def _getTestCase(self, testCaseClass, tcName): - case = super(OERuntimeTestLoader, self)._getTestCase(testCaseClass, tcName) + case = super()._getTestCase(testCaseClass, tcName) # Adds custom attributes to the OERuntimeTestCase setattr(case, 'target', self.tc.target) diff --git a/meta/lib/oeqa/sdk/context.py b/meta/lib/oeqa/sdk/context.py index d4fdd832070..891910d218c 100644 --- a/meta/lib/oeqa/sdk/context.py +++ b/meta/lib/oeqa/sdk/context.py @@ -16,7 +16,7 @@ class OESDKTestContext(OETestContext): def __init__(self, td=None, logger=None, sdk_dir=None, sdk_env=None, target_pkg_manifest=None, host_pkg_manifest=None): - super(OESDKTestContext, self).__init__(td, logger) + super().__init__(td, logger) self.sdk_dir = sdk_dir self.sdk_env = sdk_env @@ -63,7 +63,7 @@ class OESDKTestContextExecutor(OETestContextExecutor): default_test_data = None def register_commands(self, logger, subparsers): - super(OESDKTestContextExecutor, self).register_commands(logger, subparsers) + super().register_commands(logger, subparsers) sdk_group = self.parser.add_argument_group('sdk options') sdk_group.add_argument('--sdk-env', action='store', @@ -99,7 +99,7 @@ class OESDKTestContextExecutor(OETestContextExecutor): return pkg_manifest def _process_args(self, logger, args): - super(OESDKTestContextExecutor, self)._process_args(logger, args) + super()._process_args(logger, args) self.tc_kwargs['init']['sdk_dir'] = args.sdk_dir self.tc_kwargs['init']['sdk_env'] = self.sdk_env @@ -151,6 +151,6 @@ class OESDKTestContextExecutor(OETestContextExecutor): "environment (%s) specified" % args.sdk_env, self.name) self.sdk_env = sdk_envs[args.sdk_env] - return super(OESDKTestContextExecutor, self).run(logger, args) + return super().run(logger, args) _executor_class = OESDKTestContextExecutor diff --git a/meta/lib/oeqa/sdk/utils/sdkbuildproject.py b/meta/lib/oeqa/sdk/utils/sdkbuildproject.py index 32f5e3310de..66edf56f6a1 100644 --- a/meta/lib/oeqa/sdk/utils/sdkbuildproject.py +++ b/meta/lib/oeqa/sdk/utils/sdkbuildproject.py @@ -32,10 +32,10 @@ class SDKBuildProject(BuildProject): self.targetdir = os.path.join(self.targetdir, self.fname) def run_configure(self, configure_args='', extra_cmds=''): - return super(SDKBuildProject, self).run_configure(configure_args=(configure_args or '$CONFIGURE_FLAGS'), extra_cmds=extra_cmds) + return super().run_configure(configure_args=(configure_args or '$CONFIGURE_FLAGS'), extra_cmds=extra_cmds) def run_install(self, install_args=''): - return super(SDKBuildProject, self).run_install(install_args=(install_args or "DESTDIR=%s/../install" % self.targetdir)) + return super().run_install(install_args=(install_args or "DESTDIR=%s/../install" % self.targetdir)) def log(self, msg): if self.logfile: diff --git a/meta/lib/oeqa/selftest/case.py b/meta/lib/oeqa/selftest/case.py index b0b55053786..bcbd9811407 100644 --- a/meta/lib/oeqa/selftest/case.py +++ b/meta/lib/oeqa/selftest/case.py @@ -17,11 +17,11 @@ import bb.utils class OESelftestTestCase(OETestCase): def __init__(self, methodName="runTest"): self._extra_tear_down_commands = [] - super(OESelftestTestCase, self).__init__(methodName) + super().__init__(methodName) @classmethod def setUpClass(cls): - super(OESelftestTestCase, cls).setUpClass() + super().setUpClass() cls.testlayer_path = cls.tc.config_paths['testlayer_path'] cls.builddir = cls.tc.config_paths['builddir'] @@ -46,7 +46,7 @@ class OESelftestTestCase(OETestCase): def tearDownClass(cls): cls.remove_include() cls.remove_inc_files() - super(OESelftestTestCase, cls).tearDownClass() + super().tearDownClass() @classmethod def add_include(cls): @@ -94,7 +94,7 @@ class OESelftestTestCase(OETestCase): pass def setUp(self): - super(OESelftestTestCase, self).setUp() + super().setUp() os.chdir(self.builddir) # we don't know what the previous test left around in config or inc files # if it failed so we need a fresh start @@ -144,7 +144,7 @@ class OESelftestTestCase(OETestCase): self._track_for_cleanup = [] self.tearDownLocal() - super(OESelftestTestCase, self).tearDown() + super().tearDown() def tearDownLocal(self): pass diff --git a/meta/lib/oeqa/selftest/cases/_sstatetests_noauto.py b/meta/lib/oeqa/selftest/cases/_sstatetests_noauto.py index 2c9584d3291..ef6c23d1e73 100644 --- a/meta/lib/oeqa/selftest/cases/_sstatetests_noauto.py +++ b/meta/lib/oeqa/selftest/cases/_sstatetests_noauto.py @@ -16,7 +16,7 @@ class RebuildFromSState(SStateBase): @classmethod def setUpClass(self): - super(RebuildFromSState, self).setUpClass() + super().setUpClass() self.builddir = os.path.join(os.environ.get('BUILDDIR')) def get_dep_targets(self, primary_targets): diff --git a/meta/lib/oeqa/selftest/cases/bblayers.py b/meta/lib/oeqa/selftest/cases/bblayers.py index 1817e2c68a8..849afe36718 100644 --- a/meta/lib/oeqa/selftest/cases/bblayers.py +++ b/meta/lib/oeqa/selftest/cases/bblayers.py @@ -16,7 +16,7 @@ class BitbakeLayers(OESelftestTestCase): @classmethod def setUpClass(cls): - super(BitbakeLayers, cls).setUpClass() + super().setUpClass() bitbake("python3-jsonschema-native") bitbake("-c addto_recipe_sysroot python3-jsonschema-native") diff --git a/meta/lib/oeqa/selftest/cases/bblock.py b/meta/lib/oeqa/selftest/cases/bblock.py index 6ed1172f2e9..a18ebee46fd 100644 --- a/meta/lib/oeqa/selftest/cases/bblock.py +++ b/meta/lib/oeqa/selftest/cases/bblock.py @@ -18,7 +18,7 @@ from oeqa.selftest.case import OESelftestTestCase class BBLock(OESelftestTestCase): @classmethod def setUpClass(cls): - super(BBLock, cls).setUpClass() + super().setUpClass() cls.lockfile = cls.builddir + "/conf/bblock.conf" def unlock_recipes(self, recipes=None, tasks=None): diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py index c72bb494873..c748c8504bb 100644 --- a/meta/lib/oeqa/selftest/cases/devtool.py +++ b/meta/lib/oeqa/selftest/cases/devtool.py @@ -110,7 +110,7 @@ class DevtoolTestCase(OESelftestTestCase): def setUp(self): """Test case setup function""" - super(DevtoolTestCase, self).setUp() + super().setUp() self.workspacedir = os.path.join(self.builddir, 'workspace') self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory ' @@ -315,7 +315,7 @@ class DevtoolBase(DevtoolTestCase): @classmethod def setUpClass(cls): - super(DevtoolBase, cls).setUpClass() + super().setUpClass() bb_vars = get_bb_vars(['TOPDIR', 'SSTATE_DIR']) cls.original_sstate = bb_vars['SSTATE_DIR'] cls.devtool_sstate = os.path.join(bb_vars['TOPDIR'], 'sstate_devtool') @@ -328,11 +328,11 @@ class DevtoolBase(DevtoolTestCase): def tearDownClass(cls): cls.logger.debug('Deleting devtool sstate cache on %s' % cls.devtool_sstate) runCmd('rm -rf %s' % cls.devtool_sstate) - super(DevtoolBase, cls).tearDownClass() + super().tearDownClass() def setUp(self): """Test case setup function""" - super(DevtoolBase, self).setUp() + super().setUp() self.append_config(self.sstate_conf) diff --git a/meta/lib/oeqa/selftest/cases/esdk.py b/meta/lib/oeqa/selftest/cases/esdk.py index 691a80cc8d4..a3b06ac3652 100644 --- a/meta/lib/oeqa/selftest/cases/esdk.py +++ b/meta/lib/oeqa/selftest/cases/esdk.py @@ -69,7 +69,7 @@ CORE_IMAGE_EXTRA_INSTALL = "perl" @classmethod def setUpClass(cls): - super(oeSDKExtSelfTest, cls).setUpClass() + super().setUpClass() cls.image = 'core-image-minimal' bb_vars = get_bb_vars(['SSTATE_DIR', 'WORKDIR'], cls.image) diff --git a/meta/lib/oeqa/selftest/cases/gotoolchain.py b/meta/lib/oeqa/selftest/cases/gotoolchain.py index ee2cf4b09a2..a856b6fdb8d 100644 --- a/meta/lib/oeqa/selftest/cases/gotoolchain.py +++ b/meta/lib/oeqa/selftest/cases/gotoolchain.py @@ -33,7 +33,7 @@ class oeGoToolchainSelfTest(OESelftestTestCase): @classmethod def setUpClass(cls): - super(oeGoToolchainSelfTest, cls).setUpClass() + super().setUpClass() cls.tmpdir_SDKQA = tempfile.mkdtemp(prefix='SDKQA') cls.go_path = os.path.join(cls.tmpdir_SDKQA, "go") # Build the SDK and locate it in DEPLOYDIR @@ -46,7 +46,7 @@ class oeGoToolchainSelfTest(OESelftestTestCase): @classmethod def tearDownClass(cls): shutil.rmtree(cls.tmpdir_SDKQA, ignore_errors=True) - super(oeGoToolchainSelfTest, cls).tearDownClass() + super().tearDownClass() def run_sdk_go_command(self, gocmd, proj, name): cmd = "cd %s/src/%s/%s; " % (self.go_path, proj, name) diff --git a/meta/lib/oeqa/selftest/cases/kerneldevelopment.py b/meta/lib/oeqa/selftest/cases/kerneldevelopment.py index b1f78a0cd17..39111d7513e 100644 --- a/meta/lib/oeqa/selftest/cases/kerneldevelopment.py +++ b/meta/lib/oeqa/selftest/cases/kerneldevelopment.py @@ -13,7 +13,7 @@ class KernelDev(OESelftestTestCase): @classmethod def setUpClass(cls): - super(KernelDev, cls).setUpClass() + super().setUpClass() # Create the recipe directory structure inside the created layer cls.layername = 'meta-kerneltest' runCmd('bitbake-layers create-layer %s' % cls.layername) @@ -27,10 +27,10 @@ class KernelDev(OESelftestTestCase): def tearDownClass(cls): runCmd('bitbake-layers remove-layer %s' % cls.layername, ignore_status=True) runCmd('rm -rf %s' % cls.layername) - super(KernelDev, cls).tearDownClass() + super().tearDownClass() def setUp(self): - super(KernelDev, self).setUp() + super().setUp() self.set_machine_config('MACHINE = "qemux86-64"\n') def test_apply_patches(self): diff --git a/meta/lib/oeqa/selftest/cases/layerappend.py b/meta/lib/oeqa/selftest/cases/layerappend.py index e8634d9fc84..afd65b485f1 100644 --- a/meta/lib/oeqa/selftest/cases/layerappend.py +++ b/meta/lib/oeqa/selftest/cases/layerappend.py @@ -53,7 +53,7 @@ SRC_URI:append = " file://appendtest.txt" def tearDownLocal(self): if self.layerappend: ftools.remove_from_file(self.builddir + "/conf/bblayers.conf", self.layerappend) - super(LayerAppendTests, self).tearDownLocal() + super().tearDownLocal() def test_layer_appends(self): corebase = get_bb_var("COREBASE") diff --git a/meta/lib/oeqa/selftest/cases/manifest.py b/meta/lib/oeqa/selftest/cases/manifest.py index 07a6c804896..bbb92c17409 100644 --- a/meta/lib/oeqa/selftest/cases/manifest.py +++ b/meta/lib/oeqa/selftest/cases/manifest.py @@ -52,7 +52,7 @@ class VerifyManifest(OESelftestTestCase): @classmethod def setUpClass(self): - super(VerifyManifest, self).setUpClass() + super().setUpClass() self.buildtarget = 'core-image-minimal' self.classname = 'VerifyManifest' diff --git a/meta/lib/oeqa/selftest/cases/meta_ide.py b/meta/lib/oeqa/selftest/cases/meta_ide.py index f105302d8ba..295ad3da6b4 100644 --- a/meta/lib/oeqa/selftest/cases/meta_ide.py +++ b/meta/lib/oeqa/selftest/cases/meta_ide.py @@ -16,7 +16,7 @@ class MetaIDE(OESelftestTestCase): @classmethod def setUpClass(cls): - super(MetaIDE, cls).setUpClass() + super().setUpClass() bitbake('meta-ide-support') bitbake('build-sysroots -c build_native_sysroot') bitbake('build-sysroots -c build_target_sysroot') @@ -30,7 +30,7 @@ class MetaIDE(OESelftestTestCase): @classmethod def tearDownClass(cls): shutil.rmtree(cls.tmpdir_metaideQA, ignore_errors=True) - super(MetaIDE, cls).tearDownClass() + super().tearDownClass() def test_meta_ide_had_installed_meta_ide_support(self): self.assertExists(self.environment_script_path) diff --git a/meta/lib/oeqa/selftest/cases/pkgdata.py b/meta/lib/oeqa/selftest/cases/pkgdata.py index 69196ccf129..8accf1be097 100644 --- a/meta/lib/oeqa/selftest/cases/pkgdata.py +++ b/meta/lib/oeqa/selftest/cases/pkgdata.py @@ -15,7 +15,7 @@ class OePkgdataUtilTests(OESelftestTestCase): @classmethod def setUpClass(cls): - super(OePkgdataUtilTests, cls).setUpClass() + super().setUpClass() # Ensure we have the right data in pkgdata cls.logger.info('Running bitbake to generate pkgdata') bitbake('target-sdk-provides-dummy -c clean') diff --git a/meta/lib/oeqa/selftest/cases/prservice.py b/meta/lib/oeqa/selftest/cases/prservice.py index 32b499c1d90..ee03a4044dd 100644 --- a/meta/lib/oeqa/selftest/cases/prservice.py +++ b/meta/lib/oeqa/selftest/cases/prservice.py @@ -20,7 +20,7 @@ class BitbakePrTests(OESelftestTestCase): @classmethod def setUpClass(cls): - super(BitbakePrTests, cls).setUpClass() + super().setUpClass() cls.pkgdata_dir = get_bb_var('PKGDATA_DIR') cls.exported_db_path = os.path.join(cls.builddir, 'export.inc') diff --git a/meta/lib/oeqa/selftest/cases/recipetool.py b/meta/lib/oeqa/selftest/cases/recipetool.py index 54b7cb3a651..e2365141ac5 100644 --- a/meta/lib/oeqa/selftest/cases/recipetool.py +++ b/meta/lib/oeqa/selftest/cases/recipetool.py @@ -43,7 +43,7 @@ def needTomllib(test): class RecipetoolBase(devtool.DevtoolTestCase): def setUpLocal(self): - super(RecipetoolBase, self).setUpLocal() + super().setUpLocal() self.templayerdir = templayerdir self.tempdir = tempfile.mkdtemp(prefix='recipetoolqa') self.track_for_cleanup(self.tempdir) @@ -55,7 +55,7 @@ class RecipetoolBase(devtool.DevtoolTestCase): def tearDownLocal(self): runCmd('rm -rf %s/recipes-*' % self.templayerdir) - super(RecipetoolBase, self).tearDownLocal() + super().tearDownLocal() def _try_recipetool_appendcmd(self, cmd, testrecipe, expectedfiles, expectedlines=None): result = runCmd(cmd) @@ -89,7 +89,7 @@ class RecipetoolAppendTests(RecipetoolBase): @classmethod def setUpClass(cls): - super(RecipetoolAppendTests, cls).setUpClass() + super().setUpClass() # Ensure we have the right data in shlibs/pkgdata cls.logger.info('Running bitbake to generate pkgdata') bitbake('-c packagedata base-files coreutils busybox selftest-recipetool-appendfile') @@ -858,7 +858,7 @@ class RecipetoolTests(RecipetoolBase): def setUpClass(cls): import sys - super(RecipetoolTests, cls).setUpClass() + super().setUpClass() bb_vars = get_bb_vars(['BBPATH']) cls.bbpath = bb_vars['BBPATH'] libpath = os.path.join(get_bb_var('COREBASE'), 'scripts', 'lib', 'recipetool') diff --git a/meta/lib/oeqa/selftest/cases/runqemu.py b/meta/lib/oeqa/selftest/cases/runqemu.py index bfa76812ae2..84309231eb4 100644 --- a/meta/lib/oeqa/selftest/cases/runqemu.py +++ b/meta/lib/oeqa/selftest/cases/runqemu.py @@ -22,7 +22,7 @@ class RunqemuTests(OESelftestTestCase): deploy_dir_image = '' def setUpLocal(self): - super(RunqemuTests, self).setUpLocal() + super().setUpLocal() self.recipe = 'core-image-minimal' self.machine = self.td['MACHINE'] self.image_link_name = get_bb_var('IMAGE_LINK_NAME', self.recipe) @@ -187,7 +187,7 @@ class QemuTest(OESelftestTestCase): @classmethod def setUpClass(cls): - super(QemuTest, cls).setUpClass() + super().setUpClass() cls.recipe = 'core-image-minimal' cls.image_fstypes = "tar.zst" diff --git a/meta/lib/oeqa/selftest/cases/runtime_test.py b/meta/lib/oeqa/selftest/cases/runtime_test.py index 658253d2964..0e7ccf45856 100644 --- a/meta/lib/oeqa/selftest/cases/runtime_test.py +++ b/meta/lib/oeqa/selftest/cases/runtime_test.py @@ -475,7 +475,7 @@ class SystemTap(OESelftestTestCase): @classmethod def setUpClass(cls): - super(SystemTap, cls).setUpClass() + super().setUpClass() cls.image = "core-image-minimal" def default_config(self): @@ -545,7 +545,7 @@ IMAGE_INSTALL:append = " systemtap-runtime" class RustKernel(OESelftestTestCase): @classmethod def setUpClass(cls): - super(RustKernel, cls).setUpClass() + super().setUpClass() cls.image = "core-image-minimal" def test_kernel_rust_sample(self): diff --git a/meta/lib/oeqa/selftest/cases/sstatetests.py b/meta/lib/oeqa/selftest/cases/sstatetests.py index 5da8caf1c39..d33a696ba85 100644 --- a/meta/lib/oeqa/selftest/cases/sstatetests.py +++ b/meta/lib/oeqa/selftest/cases/sstatetests.py @@ -26,7 +26,7 @@ keep_temp_files = False class SStateBase(OESelftestTestCase): def setUpLocal(self): - super(SStateBase, self).setUpLocal() + super().setUpLocal() self.temp_sstate_location = None needed_vars = ['SSTATE_DIR', 'TCLIBC', 'TUNE_ARCH', 'TOPDIR', 'TARGET_VENDOR', 'TARGET_OS'] diff --git a/meta/lib/oeqa/selftest/cases/wic.py b/meta/lib/oeqa/selftest/cases/wic.py index 5b90c64cfd6..1ce3255407e 100644 --- a/meta/lib/oeqa/selftest/cases/wic.py +++ b/meta/lib/oeqa/selftest/cases/wic.py @@ -63,7 +63,7 @@ class WicTestCase(OESelftestTestCase): """This code is executed before each test method.""" self.resultdir = os.path.join(self.builddir, "wic-tmp") self._old_path = os.environ.get('PATH') - super(WicTestCase, self).setUpLocal() + super().setUpLocal() # Do this here instead of in setUpClass as the base setUp does some # clean up which can result in the native tools built earlier in @@ -96,7 +96,7 @@ class WicTestCase(OESelftestTestCase): else: os.environ['PATH'] = self._old_path rmtree(self.resultdir, ignore_errors=True) - super(WicTestCase, self).tearDownLocal() + super().tearDownLocal() def _get_wic_path(self): if WicTestCase.wic_bindir is None: diff --git a/meta/lib/oeqa/selftest/context.py b/meta/lib/oeqa/selftest/context.py index c9eb4817253..eb38012eae3 100644 --- a/meta/lib/oeqa/selftest/context.py +++ b/meta/lib/oeqa/selftest/context.py @@ -72,7 +72,7 @@ def removebuilddir(d): class OESelftestTestContext(OETestContext): def __init__(self, td=None, logger=None, machines=None, config_paths=None, newbuilddir=None, keep_builddir=None): - super(OESelftestTestContext, self).__init__(td, logger) + super().__init__(td, logger) self.config_paths = config_paths self.newbuilddir = newbuilddir @@ -173,10 +173,10 @@ class OESelftestTestContext(OETestContext): return NonConcurrentTestSuite(suites, processes, self.setup_builddir, self.removebuilddir, self.bb_vars) def runTests(self, processes=None, machine=None, skips=[]): - return super(OESelftestTestContext, self).runTests(processes, skips) + return super().runTests(processes, skips) def listTests(self, display_type, machine=None): - return super(OESelftestTestContext, self).listTests(display_type) + return super().listTests(display_type) class OESelftestTestContextExecutor(OETestContextExecutor): _context_class = OESelftestTestContext @@ -261,7 +261,7 @@ class OESelftestTestContextExecutor(OETestContextExecutor): bb.utils.mkdirhier(logdir) args.output_log = logdir + '/%s-results-%s.log' % (self.name, args.test_start_time) - super(OESelftestTestContextExecutor, self)._process_args(logger, args) + super()._process_args(logger, args) if args.list_modules: args.list_tests = 'module' diff --git a/meta/lib/oeqa/targetcontrol.py b/meta/lib/oeqa/targetcontrol.py index 1deea2e5cea..283290cd227 100644 --- a/meta/lib/oeqa/targetcontrol.py +++ b/meta/lib/oeqa/targetcontrol.py @@ -93,7 +93,7 @@ class QemuTarget(BaseTarget): import oe.types - super(QemuTarget, self).__init__(d, logger) + super().__init__(d, logger) self.rootfs = '' self.kernel = '' @@ -161,7 +161,7 @@ class QemuTarget(BaseTarget): self.logger.info("rootfs file: %s" % self.rootfs) self.logger.info("Qemu log file: %s" % self.qemulog) - super(QemuTarget, self).deploy() + super().deploy() def start(self, params=None, ssh=True, extra_bootparams='', runqemuparams='', launch_cmd='', discard_writes=True): if 'slirp' in runqemuparams.split(): @@ -228,7 +228,7 @@ class QemuTarget(BaseTarget): class SimpleRemoteTarget(BaseTarget): def __init__(self, d): - super(SimpleRemoteTarget, self).__init__(d) + super().__init__(d) addr = d.getVar("TEST_TARGET_IP") or bb.fatal('Please set TEST_TARGET_IP with the IP address of the machine you want to run the tests on.') self.ip = addr.split(":")[0] try: @@ -245,7 +245,7 @@ class SimpleRemoteTarget(BaseTarget): self.logger.info("Server IP: %s" % self.server_ip) def deploy(self): - super(SimpleRemoteTarget, self).deploy() + super().deploy() def start(self, params=None, ssh=True, extra_bootparams=None): if ssh: diff --git a/meta/lib/oeqa/utils/dump.py b/meta/lib/oeqa/utils/dump.py index d4d271369fe..588547e3a34 100644 --- a/meta/lib/oeqa/utils/dump.py +++ b/meta/lib/oeqa/utils/dump.py @@ -82,7 +82,7 @@ class TargetDumper(BaseDumper): """ def __init__(self, cmds, parent_dir, runner): - super(TargetDumper, self).__init__(cmds, parent_dir) + super().__init__(cmds, parent_dir) self.runner = runner self.errors = 0 @@ -112,7 +112,7 @@ class MonitorDumper(BaseDumper): """ def __init__(self, cmds, parent_dir, runner): - super(MonitorDumper, self).__init__(cmds, parent_dir) + super().__init__(cmds, parent_dir) self.runner = runner self.errors = 0 diff --git a/meta/lib/oeqa/utils/targetbuild.py b/meta/lib/oeqa/utils/targetbuild.py index 677f125a4f6..2365dda11bd 100644 --- a/meta/lib/oeqa/utils/targetbuild.py +++ b/meta/lib/oeqa/utils/targetbuild.py @@ -129,10 +129,10 @@ class SDKBuildProject(BuildProject): self.targetdir = os.path.join(self.targetdir, self.fname) def run_configure(self, configure_args='', extra_cmds=' gnu-configize; '): - return super(SDKBuildProject, self).run_configure(configure_args=(configure_args or '$CONFIGURE_FLAGS'), extra_cmds=extra_cmds) + return super().run_configure(configure_args=(configure_args or '$CONFIGURE_FLAGS'), extra_cmds=extra_cmds) def run_install(self, install_args=''): - return super(SDKBuildProject, self).run_install(install_args=(install_args or "DESTDIR=%s/../install" % self.targetdir)) + return super().run_install(install_args=(install_args or "DESTDIR=%s/../install" % self.targetdir)) def log(self, msg): if self.logfile: diff --git a/meta/lib/patchtest/tests/base.py b/meta/lib/patchtest/tests/base.py index 8263932dda9..3fb9882cb4e 100644 --- a/meta/lib/patchtest/tests/base.py +++ b/meta/lib/patchtest/tests/base.py @@ -109,7 +109,7 @@ class Base(unittest.TestCase): if data: value['data'] = data - return super(Base, self).fail(json.dumps(value)) + return super().fail(json.dumps(value)) def skip(self, issue, data=None): """ Convert the skip string to JSON""" @@ -120,7 +120,7 @@ class Base(unittest.TestCase): if data: value['data'] = data - return super(Base, self).skipTest(json.dumps(value)) + return super().skipTest(json.dumps(value)) def shortid(self): return self.id().split('.')[-1] diff --git a/scripts/lib/argparse_oe.py b/scripts/lib/argparse_oe.py index 176b732bbc3..9d4d2cde268 100644 --- a/scripts/lib/argparse_oe.py +++ b/scripts/lib/argparse_oe.py @@ -19,7 +19,7 @@ class ArgumentParser(argparse.ArgumentParser): def __init__(self, *args, **kwargs): kwargs.setdefault('formatter_class', OeHelpFormatter) self._subparser_groups = OrderedDict() - super(ArgumentParser, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self._positionals.title = 'arguments' self._optionals.title = 'options' @@ -49,7 +49,7 @@ class ArgumentParser(argparse.ArgumentParser): if 'dest' not in kwargs: kwargs['dest'] = '_subparser_name' - ret = super(ArgumentParser, self).add_subparsers(*args, **kwargs) + ret = super().add_subparsers(*args, **kwargs) # Need a way of accessing the parent parser ret._parent_parser = self # Ensure our class gets instantiated @@ -100,7 +100,7 @@ class ArgumentSubParser(ArgumentParser): self._group = kwargs.pop('group') if 'order' in kwargs: self._order = kwargs.pop('order') - super(ArgumentSubParser, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def parse_known_args(self, args=None, namespace=None): # This works around argparse not handling optional positional arguments being @@ -117,7 +117,7 @@ class ArgumentSubParser(ArgumentParser): action.save_nargs = action.nargs action.nargs = 0 - namespace, remaining_args = super(ArgumentSubParser, self).parse_known_args(args, namespace) + namespace, remaining_args = super().parse_known_args(args, namespace) for action in positionals: # remove the empty positional values from namespace if hasattr(namespace, action.dest): @@ -125,7 +125,7 @@ class ArgumentSubParser(ArgumentParser): for action in positionals: action.nargs = action.save_nargs # parse positionals - namespace, extras = super(ArgumentSubParser, self).parse_known_args(remaining_args, namespace) + namespace, extras = super().parse_known_args(remaining_args, namespace) return namespace, extras def format_help(self): @@ -134,7 +134,7 @@ class ArgumentSubParser(ArgumentParser): for action in positionals: if hasattr(action, 'save_nargs'): action.nargs = action.save_nargs - return super(ArgumentParser, self).format_help() + return super().format_help() class OeHelpFormatter(argparse.HelpFormatter): @@ -172,7 +172,7 @@ class OeHelpFormatter(argparse.HelpFormatter): lines.append('%s%s' % (groupindent, self._format_action(subaction).rstrip())) return '\n'.join(lines) else: - return super(OeHelpFormatter, self)._format_action(action) + return super()._format_action(action) def int_positive(value): ivalue = int(value) diff --git a/scripts/lib/buildstats.py b/scripts/lib/buildstats.py index 6db60d5bcf2..ab845d82b45 100644 --- a/scripts/lib/buildstats.py +++ b/scripts/lib/buildstats.py @@ -33,7 +33,7 @@ class BSTask(dict): self['iostat'] = {} self['rusage'] = {} self['child_rusage'] = {} - super(BSTask, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) @property def cputime(self): diff --git a/scripts/lib/checklayer/context.py b/scripts/lib/checklayer/context.py index 4de8f668fd2..aff2534fcfd 100644 --- a/scripts/lib/checklayer/context.py +++ b/scripts/lib/checklayer/context.py @@ -12,6 +12,6 @@ from oeqa.core.context import OETestContext class CheckLayerTestContext(OETestContext): def __init__(self, td=None, logger=None, layer=None, test_software_layer_signatures=True): - super(CheckLayerTestContext, self).__init__(td, logger) + super().__init__(td, logger) self.layer = layer self.test_software_layer_signatures = test_software_layer_signatures diff --git a/scripts/lib/devtool/__init__.py b/scripts/lib/devtool/__init__.py index 9d227e20326..8e016cfb214 100644 --- a/scripts/lib/devtool/__init__.py +++ b/scripts/lib/devtool/__init__.py @@ -20,7 +20,7 @@ logger = logging.getLogger('devtool') class DevtoolError(Exception): """Exception for handling devtool errors""" def __init__(self, message, exitcode=1): - super(DevtoolError, self).__init__(message) + super().__init__(message) self.exitcode = exitcode diff --git a/scripts/test-remote-image b/scripts/test-remote-image old mode 100755 new mode 100644 index 1d018992b07..ee90231a576 --- a/scripts/test-remote-image +++ b/scripts/test-remote-image @@ -126,7 +126,7 @@ class BaseTargetProfile(object, metaclass=ABCMeta): class AutoTargetProfile(BaseTargetProfile): def __init__(self, image_type): - super(AutoTargetProfile, self).__init__(image_type) + super().__init__(image_type) self.image_name = get_bb_var('IMAGE_LINK_NAME', target=image_type) self.kernel_type = get_bb_var('KERNEL_IMAGETYPE', target=image_type) self.controller = self.get_controller() @@ -203,7 +203,7 @@ class BaseRepoProfile(object, metaclass=ABCMeta): class PublicAB(BaseRepoProfile): def __init__(self, repolink, localdir=None): - super(PublicAB, self).__init__(repolink, localdir) + super().__init__(repolink, localdir) if localdir is None: self.localdir = os.path.join(os.environ['BUILDDIR'], 'PublicABMirror') From patchwork Sun Nov 15 08:48:06 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104191 Received: from mail-wm1-f44.google.com (mail-wm1-f44.google.com [209.85.128.44]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4314.1794732535237309867 for ; Sun, 15 Nov 2026 00:48:55 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=V1TNgo0j; spf=pass (domain: linuxfoundation.org, ip: 209.85.128.44, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wm1-f44.google.com with SMTP id 5b1f17b1804b1-4a9a8d6cea8so24119925e9.1 for ; Sun, 15 Nov 2026 00:48:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732533; x=1795337333; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=QYuaxLemdfL95X4//S4QM+6sgKs1Vr+z/ypcBf85GPM=; b=V1TNgo0jPrE/qhEqJstyCoG86+TCKO146Scr2YzsnXcmhXQF7iSSCTnASHN4jrJ3qy R///bxGDFplHZG1ffNSA/a6nH+OhkPmdER831mPN1ASjHgal4DSKRGftvsw45CbLReXk ETKRRomN/Q1z1FtMOqAg9+mFHJ0glcickqK9I= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732533; x=1795337333; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=QYuaxLemdfL95X4//S4QM+6sgKs1Vr+z/ypcBf85GPM=; b=clyC/5qhxtqDm9q2Uu4BSTOsOj6NcpjBsn5XN3tfnSSdd+iG1//yB9G58A2Sx/MYb2 Fzaghpei+xa3hGeMA8ZzWQHgZL0wno0jjYrBw76OsKYr4cp9thhjOEvYarSPiWeGLw66 5pcDvdGDzCDqUZBFFT/nzkumzMiV9Iex2+T01GjwoR3Y3WHXHN2NE5Bi9qWQKFfw5TEw bj6KalTQKUPG06sti8jqtHle5jx8uwcgltWu98pXvL/4huCsXWEKS+pd3FW/B/klrVl/ ir0oc3xoMv4S8m/4UeoWmaZ4CiVNVrFVSC/PILGkhGLqGqf4Kq1xQa1ZmN+0qL6XHCGL nvRQ== X-Gm-Message-State: APuU4Z+7EeGK3aqP3noUEEDHC3zWwnfsAEoO86Ar76FrIhoAwkLAmD6F Y8AXAGT1nsB2LohoPBQSKRxj5ExaCKs8QTwO4QWiO54lz3sgPxkxJMiP10WSjeITKpYVGQLJuro quctsWyU= X-Gm-Gg: AYBFou2tYa2bPRIcUOiA+35/ciLqzDzWDx02H3FsY84JXg3xyHKwfP6MgbkKj6dWOja BrBB025kepy2oNWXGfJuMINKMM2/L5IrmHdhsD6muiqBn/cl64V4Cvpewu2TU1HHhmCtQWDp/af QDNBwV1DsDUuWh5DnI+5vGNyehKvlseG/z3YK0WhcWJIArrxSLaN+oQRBzpYQJQuQ+xvUCpoqLB KRD6fElQ8TG1ewAJpBDpYnkLWx11DcWxW/nWRPD4vrQlQXCzFmGe9j+f5uw5Swcg+xqc0KZPJ9c MH/x7OssXh/RCUw3bQaYEnO3IfzLwgwZU0Bhcsmgr5J7zGzsqHQ4FLRk8AGFfpd5HcpM0ydEAxE I7SEDJO9uji5Gyc+R0XfYHuThcR6b2BUCS2pxPcEmE4WleVxh8H7Lx8kv31hMH3EtFj/ElbpAhd TkM+F1dD3U+An4oyR0mEed+Atcvv8OSLjX5ImM2t5WBTEredF21qpfLH/wROoqyY40KAt4g8YW9 KUljpfObr13cPSA9rBWQNo6F/RTGMhH78QadmYbIdUdpWebXeUbsoWy9av1s2zyS8WVtuY52Bqn IY6WDKTDdRsaRvYhhVUN9TTvga3LW7mT/NMwbkcBchNaEw5pZI+whWc9thw= X-Received: by 2002:a05:600c:2784:b0:4a1:d49e:9ce with SMTP id 5b1f17b1804b1-4bb4e2918b1mr202251625e9.2.1794732533132; Sun, 15 Nov 2026 00:48:53 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.48.52 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:48:52 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 03/41] oe-buildenv-internal: Correct minimum python version Date: Sun, 15 Nov 2026 08:48:06 +0000 Message-ID: <20261115084845.701136-3-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:48:59 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250233 We have python 3.9 as the minimum version now. Signed-off-by: Richard Purdie --- scripts/oe-buildenv-internal | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/oe-buildenv-internal b/scripts/oe-buildenv-internal index 2fdb19565a0..58e300c0e92 100755 --- a/scripts/oe-buildenv-internal +++ b/scripts/oe-buildenv-internal @@ -32,12 +32,12 @@ fi # We potentially have code that doesn't parse correctly with older versions # of Python, and rather than fixing that and being eternally vigilant for # any other new feature use, just check the version here. -py_v38_check=$(python3 -c 'import sys; print(sys.version_info >= (3,8,0))') -if [ "$py_v38_check" != "True" ]; then - echo >&2 "BitBake requires Python 3.8.0 or later as 'python3' (scripts/install-buildtools can be used if needed)" +py_v39_check=$(python3 -c 'import sys; print(sys.version_info >= (3,9,0))') +if [ "$py_v39_check" != "True" ]; then + echo >&2 "BitBake requires Python 3.9.0 or later as 'python3' (scripts/install-buildtools can be used if needed)" return 1 fi -unset py_v38_check +unset py_v39_check if [ -z "$BDIR" ]; then if [ -z "$1" ]; then From patchwork Sun Nov 15 08:48:07 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104193 Received: from mail-wr1-f42.google.com (mail-wr1-f42.google.com [209.85.221.42]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.4369.1794732537003152915 for ; Sun, 15 Nov 2026 00:48:57 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=A50gPLo+; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.42, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f42.google.com with SMTP id ffacd0b85a97d-49134c8509fso2510712f8f.1 for ; Sun, 15 Nov 2026 00:48:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732535; x=1795337335; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=fDafWhfS57IN6BUVA9DgO9lUiAM9f0P3+K7c+7r6TW0=; b=A50gPLo+iEH+KdlJvQFDbR/djtYFVjgFkCYGr+Zr8fI7bkL/ddzTWNS4P1x+DrWkT8 UcbGGynt4Qm1MtYTvRfhcPxHUGjVywFtKcBK1UtulzhWzPEB52Ce60EyqgaWPkU69h9G K6Zrfux8URcm9eoslqXkYLeIqUf5lumJfqZgw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732535; x=1795337335; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=fDafWhfS57IN6BUVA9DgO9lUiAM9f0P3+K7c+7r6TW0=; b=Jt4er9A9MX5fbzPyeDLn91O/wpdhvCFD3CVaWRdLyCFtK0oRI+HRhMdJ1hJ7rdZtN/ wd/9lqkM3M4LlwS3xhre2q9dCxReFLIME0sRCz5zegERM3rdtDAldzD9j7uVDfnY+gb8 RQ3oNbeEgwHQuYoR7pRLNNn7lP+epBJU6yTyORNIhA7lZZtuqKuE5PnCobogjMCSOvqP 0zyjMk27Ve4DPMVZnrSn953twJ9GBsAcNVLWRt/CQDDLATrSBNp8nmoZIWNkBeP+PfF8 0lD5bV2VYtfSaoKslUq+UT4WfDG1Oo9nyAHsihQZgBjWGqjeUEdBepG/2TpbHhXLGlP9 SLhg== X-Gm-Message-State: APuU4Z/vCFtv0RWIEIxEQ6zbb/RR2brESJMGina3uVv7yRQMCAQTULI8 n9ewyhWsGQXgVYJmPWcOb2xwpPYRMz7FifCI3ULBkylsvn6CdvZWhzrYfAaigZOoLWfYvK3ouAg k9uESHWY= X-Gm-Gg: AYBFou2JFmlcwqBHaJPVkOTWgCJfblB+/8s40TYfrW49AVZONYxLy/x08Si+pvnXrgW Gc5AnQcatidF0M4CQnGm/SggAoDfBzyu75Ax05RZ4eFxkn5ONskra4OrzvvS3GU1Il0MhpdPqWj pCT6KgNOqu5vo+i4NeLwdR3GjPQ3kTN+LaV6yfogTvkhGmXNPeohKOaQkPSjPPx37QztHJzRJG2 4TbtKOQcwMf6E1wpik7AT4ze8Tli11j3iQqcPAXeyugwdaEwwcnf/5t6fH3OVygl+pTBmvm0HB3 6LgqpzitmRaPIoW/0/pyOHacL/A4yOHUEsF9dWErn92Dy59gBYaOhi3Fm4lfvJ7QAJoF67+DlHq Tu9QIsViuVEEl8NWzjYZeBKAfHFN5KpbzhBuIDYhrEMebzoxg47jXF+JvUrFu0afv54naAIkurC dwFifSoAyAyVKdkIl1bFOVqHgeUySgCN9BMRdDyiUcIwLdE/9OBGv1uywkRgLN4FaZq7BAaTmoB LXTUnNL5aTWOg+zJBwleNfVNZpsbTdH3Wvnjy/onKbIwP4yEd5XGYPjn1bZBk7QvLTVjhvlhgr0 6mA5LFSL8fWdhl4hzTdpNcz26qDQ0n0AlafNcrSlkDtsI3TXLAlHYbnoIA== X-Received: by 2002:a05:6000:25ec:b0:493:803e:800f with SMTP id ffacd0b85a97d-49c725e5749mr15967021f8f.29.1794732535196; Sun, 15 Nov 2026 00:48:55 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.48.53 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:48:54 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 04/41] oeqa/core/utils/concurrencytest: Fix losing results after class setup failures Date: Sun, 15 Nov 2026 08:48:07 +0000 Message-ID: <20261115084845.701136-4-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:00 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250235 When setUpClass() or setUpModule() fails or skips in a test process, the result is reported outside of any test. The subunit parser patches which handle this reported the outcome and the stopTest() which follows it without a startTest(). testtools tracks per test state between those calls, so this broke its forwarding result and the thread reading that process' results crashed on the next test, losing the results of all the remaining tests in the process. These were then reported as UNKNOWN. Start the placeholder test before reporting its outcome, as the parser does for normal tests, and add a test comparing results from a concurrent run with a normal run. The test is skipped if testtools, subunit or bitbake aren't available. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/core/tests/test_concurrency.py | 42 ++++++++++++++++++++ meta/lib/oeqa/core/utils/concurrencytest.py | 6 +++ 2 files changed, 48 insertions(+) create mode 100644 meta/lib/oeqa/core/tests/test_concurrency.py diff --git a/meta/lib/oeqa/core/tests/test_concurrency.py b/meta/lib/oeqa/core/tests/test_concurrency.py new file mode 100644 index 00000000000..16e6619ad7f --- /dev/null +++ b/meta/lib/oeqa/core/tests/test_concurrency.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +import os +import unittest +from unittest import mock + +from common import setup_sys_path, TestBase +setup_sys_path() + +try: + from oeqa.core.utils.concurrencytest import ConcurrentTestSuite +except ImportError: + ConcurrentTestSuite = None + +@unittest.skipIf(ConcurrentTestSuite is None, "concurrencytest needs testtools, subunit and bitbake") +class TestConcurrency(TestBase): + def _statuses(self, modules, processes=None): + tc = self._testLoader(modules=modules) + if processes: + setup = lambda suffix, selftestdir, suite: (None, None) + tc.prepareSuite = lambda suites, processes: ConcurrentTestSuite(suites, processes, setup, None, {'BBLAYERS': ''}) + # fork_for_tests() only looks up the selftest layer with BUILDDIR set + with mock.patch.dict(os.environ, {'BUILDDIR': '/nonexistent'}): + result = tc.runTests(processes=processes) + return {case_id: result._getTestResultDetails(case)[0] + for case_id, case in tc._registry['cases'].items()} + + def test_concurrent_status(self): + # Class and module setup failures must not stop the results of the + # other tests run by the same process being reported + modules = ['results', 'resultsmodule', 'subtest'] + sequential = self._statuses(modules) + self.assertNotIn('UNKNOWN', sequential.values()) + self.assertEqual(self._statuses(modules, processes=1), sequential) + +if __name__ == '__main__': + unittest.main() diff --git a/meta/lib/oeqa/core/utils/concurrencytest.py b/meta/lib/oeqa/core/utils/concurrencytest.py index 5a760c620b2..09d621446ee 100644 --- a/meta/lib/oeqa/core/utils/concurrencytest.py +++ b/meta/lib/oeqa/core/utils/concurrencytest.py @@ -156,6 +156,9 @@ def outSideTestaddError(self, offset, line): test_name = line[offset:-1].decode('utf8') self.parser._current_test = subunit.RemotedTestCase(test_name) self.parser.current_test_description = test_name + # The outcome is followed by stopTest(), which testtools needs to match + # a startTest() or it loses track and breaks on the following tests + self.parser.client.startTest(self.parser._current_test) self.parser._state = self.parser._reading_error_details self.parser._reading_error_details.set_simple() self.parser.subunitLineReceived(line) @@ -171,6 +174,9 @@ def outSideTestaddSkip(self, offset, line): test_name = line[offset:-1].decode('utf8') self.parser._current_test = subunit.RemotedTestCase(test_name) self.parser.current_test_description = test_name + # The outcome is followed by stopTest(), which testtools needs to match + # a startTest() or it loses track and breaks on the following tests + self.parser.client.startTest(self.parser._current_test) self.parser._state = self.parser._reading_skip_details self.parser._reading_skip_details.set_simple() self.parser.subunitLineReceived(line) From patchwork Sun Nov 15 08:48:08 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104194 Received: from mail-wr1-f46.google.com (mail-wr1-f46.google.com [209.85.221.46]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.4370.1794732539412952440 for ; Sun, 15 Nov 2026 00:48:59 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=DN3n3sIu; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.46, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f46.google.com with SMTP id ffacd0b85a97d-48e20ed3b9dso2732462f8f.2 for ; Sun, 15 Nov 2026 00:48:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732538; x=1795337338; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=gwd1OUgyMi0hEupha6o7tQatB0OzSUbwfZIqDMfM9zk=; b=DN3n3sIuZiCtu14lQBPEXhGRxOZY5gSmq3Ywk3zZvoOixAqx92/rhVQaxUkXjlkmcJ qjlju0fYnS2c2TZa1KhLKzRIAACzbC3GRL2HIbtaFHhm/1MOEwgEEHsAMgKekUaFdDQA 2YpCm1OdMVT3Q1BfXCy3Rs3LMX3SGStdjIasA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732538; x=1795337338; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=gwd1OUgyMi0hEupha6o7tQatB0OzSUbwfZIqDMfM9zk=; b=qZJKguz/DhEju8UTBeJhP9pYQDzAUdrjdoXI0jlyTOvHJI2jsJk+j+RK0kx2xoUfMH CvS6ek9TgKBW/NyabQ8oc+UyGhd3z+IlF85B8aX3xMAmVlhGs2XAlcYfy501JR9Jn8mO ItINHQ6oCR6J4yatcYXdhtJMml9TNOsu7vMJRIlwTJP/x3kh3dQFn+tZNd0MJnPt3B+p 9ZzwpjeaYf2aP3YOpfbO/umz2HEjIUf4Xt6HWpl8Nwgf7mJJTuDp6TNLip5OwX8d7BM9 MyvnFdLyRxSR5bd6QvuiO9gpkK5aBxjqBoA8o9d8Q++eDumt+i8VL5BZJlTBfuS0bZW/ Q8Qw== X-Gm-Message-State: APuU4Z92AsWU3Ie74WsJ62PXMw8Q/lRNzVCwRPYzakSBWKmcN9eXe+E4 qJ5tAYPRhn1wIvOK8LG4aS96PD87ZaiEXHv/b0pGirtdtKRT7bockYa6ltJFNVtgt2i8MwslPzo iBWyBmUk= X-Gm-Gg: AYBFou0iCVOnbr9vQMR7jVjEx6BvqAOJez7FAis3axOtgdXucRDBMFPBIBppaaSi59L iYyvuOBUoAYnqo5UWxux9LdsJozL6HNAhJopN8lfsQtuuKR5vxHzkCvZeXngzNR5M14Y4fbr+Du hZy+baiYYmsKFuWqRpofpAqeBOVvfNJ8nh1oXTmgAm90D6RdixGSf7otruV2Te9FY6Mwy5AMMg7 o/MaqXBl8PSkoaYhmDS0xUAyyEzGJtmhXEzyB2Dt2J0s6zzkZ3ZnFilfa1bM9Ds3R39NMYsyhkV nLyOkvj07llaU5sIh6b0dpWU+j3rBR3qg7a8EfEnVsivMPhuFRX0r4lOs3haaCVKNTZ0XtMcY5F vB/yp6zxGUkaFWcdeZ4J1f5MSWl8+xOAbI5yLJjwFhxVfDCqtdEHJui9uOcfF9jOCC7mQXKehn+ FAacn47WhfDHd67YVkCe2zGJwfzLJ7txuAWqujfuc0/QHvgDkYIGX9n0hyhn2JQWoX2UtL5BO4u 6frDnGziDkjAgzpZ4MmY6KTYD3D9/1VQv/5zHqM+w0pksB2azrmah0kWFyqcu4QaTeKNPnJ1ecI mOyg9sa9Zo5x7eXRu9B3/80ZM0+2LiSmBm0zUgArs29DWW6Z4eemhTziiQ== X-Received: by 2002:a05:6000:22c6:b0:492:3982:a80c with SMTP id ffacd0b85a97d-49c712ac755mr16316462f8f.29.1794732537591; Sun, 15 Nov 2026 00:48:57 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.48.55 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:48:55 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 05/41] oeqa/core/utils/concurrencytest: Only show each test's own output Date: Sun, 15 Nov 2026 08:48:08 +0000 Message-ID: <20261115084845.701136-5-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:00 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250236 When tests run in separate processes, each process' output is collected in a buffer as it arrives. Each result was given the whole buffer as its output, so a failing test showed the output of every earlier test run by the same process, as did the stdout/stderr saved in the results. Each process runs its tests one at a time, so only give a result the output received since the previous one, and add a test. stdout and stderr still share a pipe and are reported together as stderr. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/core/tests/cases/streams.py | 24 ++++++++++++++++++++ meta/lib/oeqa/core/tests/test_concurrency.py | 17 +++++++++++++- meta/lib/oeqa/core/utils/concurrencytest.py | 10 +++++++- 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 meta/lib/oeqa/core/tests/cases/streams.py diff --git a/meta/lib/oeqa/core/tests/cases/streams.py b/meta/lib/oeqa/core/tests/cases/streams.py new file mode 100644 index 00000000000..f165e7124a1 --- /dev/null +++ b/meta/lib/oeqa/core/tests/cases/streams.py @@ -0,0 +1,24 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +import sys + +from oeqa.core.case import OETestCase + +class StreamsTest(OETestCase): + + def testStreams1(self): + print("Output from testStreams1") + sys.stderr.write("Error output from testStreams1\n") + + def testStreams2(self): + print("Output from testStreams2") + sys.stderr.write("Error output from testStreams2\n") + self.fail("Failed on purpose") + + def testStreams3(self): + print("Output from testStreams3") + self.fail("Failed on purpose") diff --git a/meta/lib/oeqa/core/tests/test_concurrency.py b/meta/lib/oeqa/core/tests/test_concurrency.py index 16e6619ad7f..b44c006d532 100644 --- a/meta/lib/oeqa/core/tests/test_concurrency.py +++ b/meta/lib/oeqa/core/tests/test_concurrency.py @@ -19,7 +19,7 @@ except ImportError: @unittest.skipIf(ConcurrentTestSuite is None, "concurrencytest needs testtools, subunit and bitbake") class TestConcurrency(TestBase): - def _statuses(self, modules, processes=None): + def _run(self, modules, processes=None): tc = self._testLoader(modules=modules) if processes: setup = lambda suffix, selftestdir, suite: (None, None) @@ -27,6 +27,10 @@ class TestConcurrency(TestBase): # fork_for_tests() only looks up the selftest layer with BUILDDIR set with mock.patch.dict(os.environ, {'BUILDDIR': '/nonexistent'}): result = tc.runTests(processes=processes) + return tc, result + + def _statuses(self, modules, processes=None): + tc, result = self._run(modules, processes) return {case_id: result._getTestResultDetails(case)[0] for case_id, case in tc._registry['cases'].items()} @@ -38,5 +42,16 @@ class TestConcurrency(TestBase): self.assertNotIn('UNKNOWN', sequential.values()) self.assertEqual(self._statuses(modules, processes=1), sequential) + def test_concurrent_output(self): + # Each test's results must only have the output from that test, not + # everything its process has output so far + tc, result = self._run(['streams'], processes=1) + for n in (1, 2, 3): + stdout, stderr = result.logged_output['streams.StreamsTest.testStreams%d' % n] + output = stdout + stderr + self.assertIn("Output from testStreams%d" % n, output) + for other in {1, 2, 3} - {n}: + self.assertNotIn("testStreams%d" % other, output) + if __name__ == '__main__': unittest.main() diff --git a/meta/lib/oeqa/core/utils/concurrencytest.py b/meta/lib/oeqa/core/utils/concurrencytest.py index 09d621446ee..455b70faff2 100644 --- a/meta/lib/oeqa/core/utils/concurrencytest.py +++ b/meta/lib/oeqa/core/utils/concurrencytest.py @@ -57,6 +57,9 @@ class BBThreadsafeForwardingResult(ThreadsafeForwardingResult): self.totaltests = totaltests self.buffer = True self.outputbuf = output + # The process' output accumulates in outputbuf; this is how much of + # it was given to earlier results + self.outputoffset = 0 self.finalresult = finalresult self.finalresult.buffer = True self.target = target @@ -79,8 +82,13 @@ class BBThreadsafeForwardingResult(ThreadsafeForwardingResult): test.id()) finally: self.semaphore.release() - self.finalresult._stderr_buffer = io.StringIO(initial_value=self.outputbuf.getvalue().decode("utf-8")) + # The process runs its tests one at a time, so the output since the + # previous result is this test's. stdout and stderr share one pipe so + # it is all given as stderr. + output = self.outputbuf.getvalue() + self.finalresult._stderr_buffer = io.StringIO(initial_value=output[self.outputoffset:].decode("utf-8")) self.finalresult._stdout_buffer = io.StringIO() + self.outputoffset = len(output) super()._add_result_with_semaphore(method, test, *args, **kwargs) class ProxyTestResult: From patchwork Sun Nov 15 08:48:09 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104195 Received: from mail-wr1-f51.google.com (mail-wr1-f51.google.com [209.85.221.51]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4316.1794732540382916794 for ; Sun, 15 Nov 2026 00:49:00 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=DEAyk0dF; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.51, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f51.google.com with SMTP id ffacd0b85a97d-498f5fa4f70so2750057f8f.0 for ; Sun, 15 Nov 2026 00:49:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732539; x=1795337339; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=FZ0KoOQtUXYQz9YbBAv9LSX7PGvSPCRxqDtAdyPumPQ=; b=DEAyk0dFPAJD/vg77oaoop0G7woF4b1NHBBPKxQlN0+clZrce9QsknpvVy+oLS/QkK 2k7Lt+4+Mfls+6XKgmbrMq6cCiyhYhi6JFqQUoeH96sfyRiwFlPenBME28klhoUh8Hx2 LZQ3UyzVULHX8sZrvNXaSJedM24CfqNAdAMBU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732539; x=1795337339; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=FZ0KoOQtUXYQz9YbBAv9LSX7PGvSPCRxqDtAdyPumPQ=; b=b8nA3XYb8RUVYWvgKrISwp3P5rKn1J66E3/3TkRaKY9ZJH6cfh8+iZnZFDPxK8fTOc KyjywzG5BoH8aTQWZiCxI0U8uNL+Za9yuqyF0N9yzngD0bV01dGoaKT2aR7w0GILvm4A F5gScJ3HIIQyRRlfZrPo2DTotO+lGB2kUTnYhapNKcI8Nn23JYchFWidY+fAeUN2RHjd DECO/HmakJ1lJ58+oxB2MOSmNfHiiHhjjOr5v0ZuwsOVR9ap/9oG4y7yQp7NKeUgmTHE ol1vEisMhyyQ6FzDBq5lcYqGDqxT7M60bUcBENGNXRRZnf1Jb5wnPyw7CX4kewhm/wZ0 IZgQ== X-Gm-Message-State: APuU4Z8RvKgupojY9HvO8x/cEDy+D6dG33wMZ3eWukhv6ppOI0NcCEky chLLTyCx3pNhK894B+N4xGjBL+pXY5qcuMpRelu2aa3OvKLHZsMTW/4v8obRZl6UvHRQsg5DKOr VAJY/B5U= X-Gm-Gg: AYBFou3jRRyvQK3cneTzqxt+Q29/vQGSidNUhtBYmsaJQKt9L5vwgQpjazL5DJ0c45a ABgnWeUlFJ+YUIs/SxPSAJA9P9AUY4GZF3oXS+JdxmFp0m6yEl4Ky89I3UKe4Ja05FFf+ClYWtn 9elddlFNP/rnkIIqpQ46N+FWOTajFAb1SHIVKTX6FEzE1Pd4YV76F8CmQH9su3I+e2bhEUtpXQo FppcqVgEqJaK7yK+fAeVoE6kp7JOyoN8Pvr7QtAkS6idzYElUZaL2OJlAlG/Jrv/wAgRApGQKth RioPFqsEP2/tm78XbB2cRxUL05H2HeIeV+PyksBwkX0cVWv67haFrw8a9AlN9C/y+6laxig1lgu f/1phct8PhiCpR0r7fn9sRSbSdNFxeCPBDvH3oPrxhxQvRqwU74Sr9toRnKWcePGJMtRdIuqwD1 G/Udw6rDHrqLMLOaE8k1QOf1bDStno2AQo3eR69XB5ouvYiA29QnIoIOx7qAiEX3qspXIB6uy/A ldeAM1gQGN25UiS5ADne4Px/muxO7ziOHypQnx6x4xWKDggnRsaGXp5gwzO7A86xwAvZrlGdGa8 4ERC5S6szyNT5YJLJBdMkaqb5M6Qt4GI5HE5xVg1UZy+6uaoP+tsAjIDuA== X-Received: by 2002:a05:6000:4201:b0:490:9fe2:6a37 with SMTP id ffacd0b85a97d-49c70ed8f15mr18152968f8f.17.1794732538545; Sun, 15 Nov 2026 00:48:58 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.48.57 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:48:57 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 06/41] oeqa/core/utils/concurrencytest: Don't buffer output in the forwarding results Date: Sun, 15 Nov 2026 08:48:09 +0000 Message-ID: <20261115084845.701136-6-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:10 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250237 BBThreadsafeForwardingResult set buffer = True, so the forwarding result for each test process swapped sys.stdout and sys.stderr for buffers in its startTest() and restored them in stopTest(). These run in separate reader threads without any locking, and each result records the streams to restore when it is created, which happens after the reader threads for earlier processes have started. sys.stdout/stderr could be left pointing at a buffer after the tests ran, losing later output and making any later forked test process fail at sys.stdout.fileno(). The output of the test processes comes through the passthrough buffer and is given to the final result, which does its own buffering under the semaphore, so don't buffer in the forwarding results. Add a test which checks the streams are restored after concurrent runs. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/core/tests/test_concurrency.py | 11 +++++++++++ meta/lib/oeqa/core/utils/concurrencytest.py | 4 +++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/meta/lib/oeqa/core/tests/test_concurrency.py b/meta/lib/oeqa/core/tests/test_concurrency.py index b44c006d532..f7b1f554c96 100644 --- a/meta/lib/oeqa/core/tests/test_concurrency.py +++ b/meta/lib/oeqa/core/tests/test_concurrency.py @@ -6,6 +6,7 @@ # import os +import sys import unittest from unittest import mock @@ -53,5 +54,15 @@ class TestConcurrency(TestBase): for other in {1, 2, 3} - {n}: self.assertNotIn("testStreams%d" % other, output) + def test_concurrent_streams_restored(self): + # Each process' results are read in a separate thread; after running, + # sys.stdout and sys.stderr must be the original streams again. Any + # problem here is a race, so run several times. + stdout, stderr = sys.stdout, sys.stderr + for i in range(50): + self._run(['results'], processes=2) + self.assertIs(sys.stdout, stdout) + self.assertIs(sys.stderr, stderr) + if __name__ == '__main__': unittest.main() diff --git a/meta/lib/oeqa/core/utils/concurrencytest.py b/meta/lib/oeqa/core/utils/concurrencytest.py index 455b70faff2..24b391cdb96 100644 --- a/meta/lib/oeqa/core/utils/concurrencytest.py +++ b/meta/lib/oeqa/core/utils/concurrencytest.py @@ -55,7 +55,9 @@ class BBThreadsafeForwardingResult(ThreadsafeForwardingResult): self.threadnum = threadnum self.totalinprocess = totalinprocess self.totaltests = totaltests - self.buffer = True + # Don't set self.buffer, the output comes through outputbuf. Buffering + # here would swap sys.stdout/stderr in each reader thread, unlocked, + # and could leave them replaced after the tests have run. self.outputbuf = output # The process' output accumulates in outputbuf; this is how much of # it was given to earlier results From patchwork Sun Nov 15 08:48:10 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104198 Received: from mail-wr1-f42.google.com (mail-wr1-f42.google.com [209.85.221.42]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4317.1794732542599677645 for ; Sun, 15 Nov 2026 00:49:02 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=D9oaigPX; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.42, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f42.google.com with SMTP id ffacd0b85a97d-4919a880834so1131241f8f.0 for ; Sun, 15 Nov 2026 00:49:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732541; x=1795337341; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=F1Snosp2f5pkLWMwju8gqBtnrHiAsADjotrnsEEm4+M=; b=D9oaigPX1qzVhPaMbBnwK+GV2g/3OjhE++z3PXCvvuNbtpPR66lN4GjfNEgaBQuMRV fOwTnJT7w/ldpyUka6hMfiRKhB4Z1Iao0FwEJClO6r3pCQlPItOI/J2vocp0ONaF86x/ rymrSdKNoPM+S7cQo7hpjB+EiaCt1/e5Fsi1Y= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732541; x=1795337341; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=F1Snosp2f5pkLWMwju8gqBtnrHiAsADjotrnsEEm4+M=; b=yh4FJMzzHETcWNu8VPFHNyTe34kZKewCv44rcU2qkSQ36peUuAk5tHhAVDddylvswO e5QYSS22V5dLG8bGVXiSlqwFRQaT6nmIwgwVr4NE+7OwKyhYQsrhHHpkvMcfffKapgq+ SI/tw8D5N3rFtTDxQEMRvT5K4xI6NXrKxBfJwmCVkpeosgwoTKcOtbwyuX8ebxQC0Ynj cLmtDRMHhLG5BunbNJZgSy+cBt4ReOhb+7gqeNzrDvq0PkyTNuI+VfTWiKDA8p8UB1M6 Yz6xRgHeefFeYptHJ4jwCz23TD4EhSUtYTseJbOEGIUTgihcnRoFtYnD/ecjRwsaPXA2 UdiQ== X-Gm-Message-State: APuU4Z+gBxEZ0yEQKi0sDAw4tureyGlFSCZNztk77WZjAcgVTABr24in A+JBEToNCIuaMlnDr7aXwD5mVYTAOup/lsv6UWckX3WkJY0N7bj7kHX2ixcoMUJXGuSyFKGSTU1 d/DeOV0o= X-Gm-Gg: AYBFou0nwcWjPKZYWT6PfXK6xgmT+2nq9JAHnQguX44FgpT6r3hYvwjKgzd5IFdK6vZ +h7JW/SzggcV+L4w9pLpGSQUaSeDIFN0AAlk1TwgVl9bsudDkrmLj6ArmTTXAfYF3rJOdvSP2JJ /rWBVSGqvsuphTS0HYZopKJA/jZ0FYQPeTXIQo/rXK95jR8ySmnM9+DQ5wQ1jJnZ8+Gq41hljnT mtVDxzO06QLY7Khd1gOJKY/AJt2pRz5eAw5P9/1ZoZoWyuk4iYnos9dq/dGph95KSeX6EvuPt8Y S6EvhSc4uPzPNgDi3yObYGV/A6+0z6c+M0LOn8XyGyFORGM5+Z/umDk7NnQ0vTaYZF3oSgrcm+O lO3W6uAoVKyB1OJqqM0O/MueLPXxpItcw+c4t02LjAvJOMtcc67/IZGOh9CPotGMxg60nxt9RE5 Dg81vTLgIOVTdDm0nYkUq8Ica+dNuEkxNYdiCan+quCZRZpj+hHX/YXheC7gWkBmzPNRXfY5noz JdPi7yytESTe07jkWZ6lIpn6/jNp02r6K1WsF6c/f/XTNu1zcJwp4hYa6WX+NTGcNxnGFZCknoA 7GtWP+g6lUoRQpMGVGMjrBdq5/lu5oy8jhtVRjrQpsCVDNt6SNZPvolTmVq1cdoXv3oEqm9em/C OtQY= X-Received: by 2002:a05:6000:26ce:b0:48b:e50:7159 with SMTP id ffacd0b85a97d-49c71b5bfbemr14575708f8f.30.1794732540734; Sun, 15 Nov 2026 00:49:00 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.48.58 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:48:58 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 07/41] oeqa/core/utils/concurrencytest: Fix the failed count in the test progress Date: Sun, 15 Nov 2026 08:48:10 +0000 Message-ID: <20261115084845.701136-7-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:11 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250238 The "(N failed)" count shown in the progress line for each test when running tests concurrently came from the result proxy for the process which ran the test. It was only that process' count, was read before the current test's result was counted, and counted each failure twice since testtools first passes a failure with details, which OETestResult rejects, and then retries without. Count the failing tests across all processes on the final result in _add_result_with_semaphore(), which is called once per result under the semaphore shared by the reader threads, before the progress line is formatted. Add a test which checks the count in each progress line. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/core/tests/cases/failures.py | 29 ++++++++++++++++++++ meta/lib/oeqa/core/tests/test_concurrency.py | 16 +++++++++++ meta/lib/oeqa/core/utils/concurrencytest.py | 8 +++++- 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 meta/lib/oeqa/core/tests/cases/failures.py diff --git a/meta/lib/oeqa/core/tests/cases/failures.py b/meta/lib/oeqa/core/tests/cases/failures.py new file mode 100644 index 00000000000..371a277537a --- /dev/null +++ b/meta/lib/oeqa/core/tests/cases/failures.py @@ -0,0 +1,29 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +from oeqa.core.case import OETestCase + +class FailuresATest(OETestCase): + + def testFailuresA1(self): + self.fail("Failed on purpose") + + def testFailuresA2(self): + pass + + def testFailuresA3(self): + raise Exception("Error on purpose") + +class FailuresBTest(OETestCase): + + def testFailuresB1(self): + pass + + def testFailuresB2(self): + self.fail("Failed on purpose") + + def testFailuresB3(self): + self.fail("Failed on purpose") diff --git a/meta/lib/oeqa/core/tests/test_concurrency.py b/meta/lib/oeqa/core/tests/test_concurrency.py index f7b1f554c96..0f382308b2f 100644 --- a/meta/lib/oeqa/core/tests/test_concurrency.py +++ b/meta/lib/oeqa/core/tests/test_concurrency.py @@ -6,6 +6,7 @@ # import os +import re import sys import unittest from unittest import mock @@ -64,5 +65,20 @@ class TestConcurrency(TestBase): self.assertIs(sys.stdout, stdout) self.assertIs(sys.stderr, stderr) + def test_concurrent_failed_count(self): + # The failed count in the progress shown for each test must be the + # number of tests which failed so far in all processes + tc, result = self._run(['failures'], processes=2) + failed = {test.id() for test, _ in result.failures + result.errors} + self.assertEqual(len(failed), 4) + # progressinfo is in the order the results were received + seen = set() + for test_id, progress in result.progressinfo.items(): + if test_id in failed: + seen.add(test_id) + count = int(re.search(r"\((\d+) failed\)", progress).group(1)) + self.assertEqual(count, len(seen), msg=progress) + self.assertEqual(seen, failed) + if __name__ == '__main__': unittest.main() diff --git a/meta/lib/oeqa/core/utils/concurrencytest.py b/meta/lib/oeqa/core/utils/concurrencytest.py index 24b391cdb96..9da0c5e661e 100644 --- a/meta/lib/oeqa/core/utils/concurrencytest.py +++ b/meta/lib/oeqa/core/utils/concurrencytest.py @@ -70,6 +70,11 @@ class BBThreadsafeForwardingResult(ThreadsafeForwardingResult): self.semaphore.acquire() try: if self._test_start: + # Count failing tests across all the processes. This is called + # once per result, unlike the add* methods of the target which + # testtools may call twice. + if method.__name__ in ('addError', 'addFailure'): + self.finalresult.failedtests.add(test.id()) self.result.starttime[test.id()] = self._test_start.timestamp() self.result.threadprogress[self.threadnum].append(test.id()) totalprogress = sum(len(x) for x in self.result.threadprogress.values()) @@ -80,7 +85,7 @@ class BBThreadsafeForwardingResult(ThreadsafeForwardingResult): totalprogress, self.totaltests, "{0:.2f}".format(time.time()-self._test_start.timestamp()), - self.target.failed_tests, + len(self.finalresult.failedtests), test.id()) finally: self.semaphore.release() @@ -223,6 +228,7 @@ class ConcurrentTestSuite(unittest.TestSuite): queue = Queue() semaphore = threading.Semaphore(1) result.threadprogress = {} + result.failedtests = set() for i, (testserver, testnum, output) in enumerate(testservers): result.threadprogress[i] = [] process_result = BBThreadsafeForwardingResult( From patchwork Sun Nov 15 08:48:11 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104199 Received: from mail-wr1-f45.google.com (mail-wr1-f45.google.com [209.85.221.45]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4318.1794732543756010918 for ; Sun, 15 Nov 2026 00:49:04 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=D6qBw5RK; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.45, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f45.google.com with SMTP id ffacd0b85a97d-48dfc0421d9so2243163f8f.1 for ; Sun, 15 Nov 2026 00:49:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732542; x=1795337342; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=7PNKYsu/Yg/4CIhEfVMzas0QHiMGaz1f10476JiYFvA=; b=D6qBw5RKz65LpP2MQb3kgZpcLV5tqjLZ9+/4vuDx7j8+n9pA/TLmmHCrIEx/GN4QJ2 1wdBjImJp+rb/2NiL9MXwmTJd9E3Mif4MGmK3bXIxhRQR6cpyXTt7mcODKiXRFEaajfU pkiPwk9SKGjvcwVE0Nxpg1kyA01YYaFH6C4jA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732542; x=1795337342; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=7PNKYsu/Yg/4CIhEfVMzas0QHiMGaz1f10476JiYFvA=; b=LfmW9Vb5TQS1XnZSXAFDeYCYEEl7NOKO01vPsF2DU9sJ6W1FEzm4+aFsAH1HYMwzJF TB7CVQ+A2ZSPyUuq1jMEVg9aRwZiMQSevQQfVV1udhZSWz0ja/VuHjLIG7OKBQ+gZbgl XDLV9ZWGOlmJG3ohW7cr1Cq18W8CfM4OvJynskitHEJ/1ViprYZOGI8h2pVLwe6J/ORH FGpHgdtazBabSXnJyfyPedf4eTxe0X4/KXGOYod8mP1GwEN1d8xfaJAjODxUKLlMHjm4 sGZ5OYYQ2oPVLlo3Ry/t5I2hM2DKi5MAMckaWdg3muNZnggWBtgUwtrFGCgTqJ6SUcwQ 3mEA== X-Gm-Message-State: APuU4Z+Eh/b5fpZKMcNzbH4KaaPqtvgfmIxzSSU1+Sr9ORN8fuGSGUb2 fV9Gdetqdo2HsJXCWgtTeXA5Yin94OpHXb1enwTqHn4uwgb6iGEO4syEBLxqd3iSWxrmtrQa1P5 OazDGtio= X-Gm-Gg: AYBFou0BuPJGXSh69BPaYnKktGBbWmwi4qzNahmA4bLr6noo7ofVwaRwd3akK2Ehgqd OE4O+NOlVGSng9TtN97RhoGxmTRURE6FMJpUD8C/6poLqFBaDuLslzgKL2obIF8/Mnu651yQCkZ 2uDx8BHHTBXyDeppBrv3xDlIHxaO3KuqLxFZQAqqjDXr9rqVBEEXgwNqYhCbPrEXCJ31I8EY5JS mVbJTdXao4IWxLM0vG9QSp1cNgs+RhevaWwGPEm27Ox06tDaGUAhWZh/IZY1T6A7anhDhtEqhTP JWNt/br7eaMrOUiWMjBFR7glhBYOM3ZVjCD0WsB7/WPIpRjDDRoeAHBqMGnrEYTa80RwlXU79UM +Me6zFle7Rl7m0aKYHLjo1k9eT66jVMqfDLhqJ+R7w20aSNvzbr0tkE3Kgg+7si+zpRkLgRFPxG 61V3mz4QnEhIFITA0aI78lqXO5cSD9/7PPh+feqDa8hrxFMeljHXJYirXT3kvV6TUmbF1NbjFmm F/ypUA8ZJUTuGifbrvQYMmgFczZSoG96HPd6wRbcc2AhfHtdwnMkQLlWGGx9Fq2zOaYN8a471Mm UFebMbrScl/9RNiWiJthEpQ0MruO1m9TuJSmZvrPdqVcv2hpHg9GFAltOA== X-Received: by 2002:a05:6000:290c:b0:493:a59d:880e with SMTP id ffacd0b85a97d-49c713add85mr15792415f8f.30.1794732541844; Sun, 15 Nov 2026 00:49:01 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.00 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:01 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 08/41] oeqa: Drop explicit 'object' base classes Date: Sun, 15 Nov 2026 08:48:11 +0000 Message-ID: <20261115084845.701136-8-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:11 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250239 All classes are new-style in Python 3 so inheriting from object is redundant. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/buildperf/base.py | 2 +- meta/lib/oeqa/core/context.py | 4 ++-- meta/lib/oeqa/core/runner.py | 6 +++--- meta/lib/oeqa/core/target/__init__.py | 2 +- meta/lib/oeqa/core/utils/concurrencytest.py | 2 +- meta/lib/oeqa/oetest.py | 2 +- meta/lib/oeqa/runexported.py | 2 +- meta/lib/oeqa/sdk/testmetaidesupport.py | 2 +- meta/lib/oeqa/sdk/testsdk.py | 2 +- meta/lib/oeqa/selftest/cases/reproducible.py | 4 ++-- meta/lib/oeqa/selftest/cases/runcmd.py | 2 +- meta/lib/oeqa/selftest/cases/spdx.py | 2 +- meta/lib/oeqa/utils/commands.py | 4 ++-- meta/lib/oeqa/utils/decorators.py | 2 +- meta/lib/oeqa/utils/dump.py | 2 +- meta/lib/oeqa/utils/git.py | 2 +- meta/lib/oeqa/utils/logparser.py | 4 ++-- meta/lib/oeqa/utils/sshcontrol.py | 4 ++-- 18 files changed, 25 insertions(+), 25 deletions(-) diff --git a/meta/lib/oeqa/buildperf/base.py b/meta/lib/oeqa/buildperf/base.py index 944314d7c29..37696466f4e 100644 --- a/meta/lib/oeqa/buildperf/base.py +++ b/meta/lib/oeqa/buildperf/base.py @@ -32,7 +32,7 @@ log = logging.getLogger('build-perf') runCmd2 = partial(runCmd, assert_error=False, limit_exc_output=40) -class KernelDropCaches(object): +class KernelDropCaches: """Container of the functions for dropping kernel caches""" sudo_passwd = None diff --git a/meta/lib/oeqa/core/context.py b/meta/lib/oeqa/core/context.py index 46de9135c17..9745286548e 100644 --- a/meta/lib/oeqa/core/context.py +++ b/meta/lib/oeqa/core/context.py @@ -15,7 +15,7 @@ from oeqa.core.loader import OETestLoader from oeqa.core.runner import OETestRunner from oeqa.core.exception import OEQAMissingManifest, OEQATestNotFound -class OETestContext(object): +class OETestContext: loaderClass = OETestLoader runnerClass = OETestRunner @@ -97,7 +97,7 @@ class OETestContext(object): self.runner = self.runnerClass(self, verbosity=2) return self.runner.list_tests(self.suites, display_type) -class OETestContextExecutor(object): +class OETestContextExecutor: _context_class = OETestContext _script_executor = 'oe-test' diff --git a/meta/lib/oeqa/core/runner.py b/meta/lib/oeqa/core/runner.py index 8ad65facead..9164ee6bcca 100644 --- a/meta/lib/oeqa/core/runner.py +++ b/meta/lib/oeqa/core/runner.py @@ -15,7 +15,7 @@ import sys from unittest import TextTestResult as _TestResult from unittest import TextTestRunner as _TestRunner -class OEStreamLogger(object): +class OEStreamLogger: def __init__(self, logger): self.logger = logger self.buffer = "" @@ -243,7 +243,7 @@ class OETestResult(_TestResult): # Account for expected failures return not self.wasSuccessful() or len(self.expectedFailures) -class OEListTestsResult(object): +class OEListTestsResult: def wasSuccessful(self): return True @@ -333,7 +333,7 @@ class OETestRunner(_TestRunner): return OEListTestsResult() -class OETestResultJSONHelper(object): +class OETestResultJSONHelper: testresult_filename = 'testresults.json' diff --git a/meta/lib/oeqa/core/target/__init__.py b/meta/lib/oeqa/core/target/__init__.py index 177f648fe35..38655743425 100644 --- a/meta/lib/oeqa/core/target/__init__.py +++ b/meta/lib/oeqa/core/target/__init__.py @@ -6,7 +6,7 @@ from abc import abstractmethod -class OETarget(object): +class OETarget: def __init__(self, logger, *args, **kwargs): self.logger = logger diff --git a/meta/lib/oeqa/core/utils/concurrencytest.py b/meta/lib/oeqa/core/utils/concurrencytest.py index 9da0c5e661e..ade0a83cb82 100644 --- a/meta/lib/oeqa/core/utils/concurrencytest.py +++ b/meta/lib/oeqa/core/utils/concurrencytest.py @@ -203,7 +203,7 @@ subunit._OutSideTest.addSkip = outSideTestaddSkip # is available and accepts writes. This allows unittest with buffer=True # to interact ok with subunit which wants to access sys.stdout.buffer. # -class dummybuf(object): +class dummybuf: def __init__(self, parent): self.p = parent def write(self, data): diff --git a/meta/lib/oeqa/oetest.py b/meta/lib/oeqa/oetest.py index af555bea620..ac972cfb223 100644 --- a/meta/lib/oeqa/oetest.py +++ b/meta/lib/oeqa/oetest.py @@ -155,7 +155,7 @@ def custom_verbose(msg, *args, **kwargs): logger.info(_buffer_logger.rstrip("\n"), *args, **kwargs) _buffer_logger = "" -class TestContext(object): +class TestContext: def __init__(self, d, exported=False): self.d = d diff --git a/meta/lib/oeqa/runexported.py b/meta/lib/oeqa/runexported.py index 7e37213df69..982d8affa03 100755 --- a/meta/lib/oeqa/runexported.py +++ b/meta/lib/oeqa/runexported.py @@ -37,7 +37,7 @@ from oeqa.utils.sshcontrol import SSHControl # this isn't pretty but we need a fake target object # for running the tests externally as we don't care # about deploy/start we only care about the connection methods (run, copy) -class FakeTarget(object): +class FakeTarget: def __init__(self, d): self.connection = None self.ip = None diff --git a/meta/lib/oeqa/sdk/testmetaidesupport.py b/meta/lib/oeqa/sdk/testmetaidesupport.py index 1110c40b9bf..c7a4041e08a 100644 --- a/meta/lib/oeqa/sdk/testmetaidesupport.py +++ b/meta/lib/oeqa/sdk/testmetaidesupport.py @@ -4,7 +4,7 @@ # SPDX-License-Identifier: MIT # -class TestSDK(object): +class TestSDK: def run(self, d): import json import logging diff --git a/meta/lib/oeqa/sdk/testsdk.py b/meta/lib/oeqa/sdk/testsdk.py index 7b0765f2726..747608f260c 100644 --- a/meta/lib/oeqa/sdk/testsdk.py +++ b/meta/lib/oeqa/sdk/testsdk.py @@ -6,7 +6,7 @@ from oeqa.sdk.context import OESDKTestContext, OESDKTestContextExecutor -class TestSDKBase(object): +class TestSDKBase: @staticmethod def get_sdk_configuration(d, test_type): import platform diff --git a/meta/lib/oeqa/selftest/cases/reproducible.py b/meta/lib/oeqa/selftest/cases/reproducible.py index 28236a28d52..f0eda2ac4ab 100644 --- a/meta/lib/oeqa/selftest/cases/reproducible.py +++ b/meta/lib/oeqa/selftest/cases/reproducible.py @@ -30,7 +30,7 @@ DIFFERENT = 'DIFFERENT' SAME = 'SAME' @functools.total_ordering -class CompareResult(object): +class CompareResult: def __init__(self): self.reference = None self.test = None @@ -42,7 +42,7 @@ class CompareResult(object): def __lt__(self, other): return (self.status, self.test) < (other.status, other.test) -class PackageCompareResults(object): +class PackageCompareResults: def __init__(self, exclusions): self.total = [] self.missing = [] diff --git a/meta/lib/oeqa/selftest/cases/runcmd.py b/meta/lib/oeqa/selftest/cases/runcmd.py index 70047ca0caa..589c0c28e01 100644 --- a/meta/lib/oeqa/selftest/cases/runcmd.py +++ b/meta/lib/oeqa/selftest/cases/runcmd.py @@ -13,7 +13,7 @@ import threading import time import signal -class MemLogger(object): +class MemLogger: def __init__(self): self.info_msgs = [] self.error_msgs = [] diff --git a/meta/lib/oeqa/selftest/cases/spdx.py b/meta/lib/oeqa/selftest/cases/spdx.py index a9b47119243..ce9a8af4f65 100644 --- a/meta/lib/oeqa/selftest/cases/spdx.py +++ b/meta/lib/oeqa/selftest/cases/spdx.py @@ -12,7 +12,7 @@ from oeqa.utils.commands import bitbake, get_bb_var, get_bb_vars import oe.spdx30 -class SPDX3CheckBase(object): +class SPDX3CheckBase: """ Base class for checking SPDX 3 based tests """ diff --git a/meta/lib/oeqa/utils/commands.py b/meta/lib/oeqa/utils/commands.py index 3473ffb74bc..f8d6a793550 100644 --- a/meta/lib/oeqa/utils/commands.py +++ b/meta/lib/oeqa/utils/commands.py @@ -25,7 +25,7 @@ try: except ImportError: pass -class Command(object): +class Command: def __init__(self, command, bg=False, timeout=None, data=None, output_log=None, **options): self.defaultopts = { @@ -161,7 +161,7 @@ class Command(object): self.log.debug("Last 20 lines:\n%s" % lout) -class Result(object): +class Result: pass diff --git a/meta/lib/oeqa/utils/decorators.py b/meta/lib/oeqa/utils/decorators.py index ea90164e5e7..c45d5f4512c 100644 --- a/meta/lib/oeqa/utils/decorators.py +++ b/meta/lib/oeqa/utils/decorators.py @@ -16,7 +16,7 @@ import threading import signal from functools import wraps -class testcase(object): +class testcase: def __init__(self, test_case): self.test_case = test_case diff --git a/meta/lib/oeqa/utils/dump.py b/meta/lib/oeqa/utils/dump.py index 588547e3a34..c32e6f7b9ae 100644 --- a/meta/lib/oeqa/utils/dump.py +++ b/meta/lib/oeqa/utils/dump.py @@ -12,7 +12,7 @@ import datetime import itertools from .commands import runCmd -class BaseDumper(object): +class BaseDumper: """ Base class to dump commands from host/target """ def __init__(self, cmds, parent_dir): diff --git a/meta/lib/oeqa/utils/git.py b/meta/lib/oeqa/utils/git.py index ea35a766eb7..e1f377bb0fd 100644 --- a/meta/lib/oeqa/utils/git.py +++ b/meta/lib/oeqa/utils/git.py @@ -13,7 +13,7 @@ class GitError(Exception): """Git error handling""" pass -class GitRepo(object): +class GitRepo: """Class representing a Git repository clone""" def __init__(self, path, is_topdir=False): git_dir = self._run_git_cmd_at(['rev-parse', '--git-dir'], path) diff --git a/meta/lib/oeqa/utils/logparser.py b/meta/lib/oeqa/utils/logparser.py index d445b4e2a01..c0d68339953 100644 --- a/meta/lib/oeqa/utils/logparser.py +++ b/meta/lib/oeqa/utils/logparser.py @@ -9,7 +9,7 @@ import os import re # A parser that can be used to identify weather a line is a test result or a section statement. -class PtestParser(object): +class PtestParser: def __init__(self): self.results = {} self.sections = {} @@ -144,7 +144,7 @@ class LtpParser: # ltp Compliance log parsing -class LtpComplianceParser(object): +class LtpComplianceParser: def __init__(self): self.results = {} self.section = {'duration': "", 'log': ""} diff --git a/meta/lib/oeqa/utils/sshcontrol.py b/meta/lib/oeqa/utils/sshcontrol.py index 88a61aff635..2aca59554d4 100644 --- a/meta/lib/oeqa/utils/sshcontrol.py +++ b/meta/lib/oeqa/utils/sshcontrol.py @@ -14,7 +14,7 @@ import os import select -class SSHProcess(object): +class SSHProcess: def __init__(self, **options): self.defaultopts = { @@ -99,7 +99,7 @@ class SSHProcess(object): raise return (self.status, self.output) -class SSHControl(object): +class SSHControl: def __init__(self, ip, logfile=None, timeout=300, user='root', port=None): self.ip = ip self.defaulttimeout = timeout From patchwork Sun Nov 15 08:48:12 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104200 Received: from mail-wm1-f43.google.com (mail-wm1-f43.google.com [209.85.128.43]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.4372.1794732545181152162 for ; Sun, 15 Nov 2026 00:49:05 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=E9Y28zqT; spf=pass (domain: linuxfoundation.org, ip: 209.85.128.43, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wm1-f43.google.com with SMTP id 5b1f17b1804b1-4bb55cda775so10182555e9.0 for ; Sun, 15 Nov 2026 00:49:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732543; x=1795337343; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=mwPeoKvd7dATDQ+NfIudsGtsRXIkuGzNEZiaPump97o=; b=E9Y28zqTrmDNUhoC3fFEE4EvijqTLFheZxrz8NvopmJI1t7/f/pGsWAIapMKRjDDJo OWyX9yjwJXdSObvPyO52EwX6ejAVsuo1OcOjTMxbg5t8mvV0u3GdhQL0kyasnUCnaQrI 5ZzMXFiXPxRQS7oHQxe0506zvTxM76yiqDayQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732543; x=1795337343; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=mwPeoKvd7dATDQ+NfIudsGtsRXIkuGzNEZiaPump97o=; b=Oh0Nt6wsliENHFZq+j6dujNW0CdTZK6bpXHFazGN+TVjaaJGZptwiNHXyvG6lEp6iz ESH+FBP2VS+Hn6g9he3IIC9ti4T0C3SCEmLWwXF2QznJiMhQQgNTPTMhoZkKf35pGaNA ZnCkM5MMQ5ItpgP36pivyqKyO/CgxxbV5GGSDhjo9azzM/emYyWYLYBaUPrmerEXUq1R R/+R9z6DAJHNygwk3kl0BP/S10ujSfpi8CzqhAe0O2pW7YxKF0Jf7mERpqPQQ1VjzXlc x3xOYxKwQBTSxTuS2hMA68ykZvLa891qsOOKFz4ndxJieu7KVaLxWBpCrm4L/cuYbyx9 yVSA== X-Gm-Message-State: APuU4Z9353tVIjdFyyywO4cM3VyTV9/gktzEkfqA5nzOWU4UqvORDQdN A6eQO3p8B3ljtxU+qt2Ca4B7I5OLjFPOrxwdvIV0l0Pw5iv6NQdHzSAZmBjwT0I828zQITXciok yvNh+SFQ= X-Gm-Gg: AYBFou1Ln9ebW9VAgEcHEDoPWwfriWUgNzv3v5CoBpHx16FlVxhNVxVKtqyrGmZCgM9 Vxe0YPynnbxfyMWXtUZ/CZ/RapRYEaLjYwhxuVmnD8fz61+VWAmoU/aGPOJrFJXEmdA9maR9mHz wwjo0VGEWeFrE4MyHxbxcCX+USscJ3YI/J9OiZxBNTyPhUhZvbcpJk7FfRiHAe6neZkKddijfSO Wx0VYUPNHiQIWCIpfepWgkEcT9X+zzqk6uTeP5g1Fk86F/gsdTZ/diW9qGItzoXw7+17mjasbNj IWpZ0b3u265E8AmbrcXugsWkMdyW7Kvdash6h+XA9sG9qFwKkPJHdhNg01BCyzb8x5jjvCC5sgS t6ikwMHiwK1+tY3+Jv+fWrgLgJuMvSohq+kBmFHUDZoSSNPw3Z7Y8VC4DMKUEhvnjtgFYvcTdT4 LsCWJZh/vf9tqwryMQe1hZEjNe4e3AS14d2qHRU8jANW6gRycYZSwn2NZrpH4ipB+7+SnyUzj1S 7tf/4VEDK8pNgk+4Y5K+heGLYdIHwLAqMEfW3Z9wmwSs1igm0PitSj7+81vwArSSSJWZuqyfPOh ncf+YbnQvbRqCS8pOhxWaauaxeLoK0ugB40ZUnu5xfUD7gk5hxNvultycQ== X-Received: by 2002:a05:600c:a596:b0:4b5:d95c:2380 with SMTP id 5b1f17b1804b1-4bb55a86fb2mr89489695e9.11.1794732543184; Sun, 15 Nov 2026 00:49:03 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.01 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:02 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 09/41] oeqa: Use OSError instead of IOError and socket.error Date: Sun, 15 Nov 2026 08:48:12 +0000 Message-ID: <20261115084845.701136-9-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:11 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250240 IOError and socket.error are aliases of OSError in Python 3. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/oetest.py | 2 +- meta/lib/oeqa/selftest/cases/manifest.py | 12 ++++++------ meta/lib/oeqa/utils/ftools.py | 2 +- meta/lib/oeqa/utils/qemurunner.py | 6 +++--- meta/lib/oeqa/utils/qemutinyrunner.py | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/meta/lib/oeqa/oetest.py b/meta/lib/oeqa/oetest.py index ac972cfb223..a57cea74b46 100644 --- a/meta/lib/oeqa/oetest.py +++ b/meta/lib/oeqa/oetest.py @@ -360,7 +360,7 @@ class RuntimeTestContext(TestContext): for line in f: (pkg, arch, version) = line.strip().split() self.pkgmanifest[pkg] = (version, arch) - except IOError as e: + except OSError as e: bb.fatal("No package manifest file found. Did you build the image?\n%s" % e) def _get_test_namespace(self): diff --git a/meta/lib/oeqa/selftest/cases/manifest.py b/meta/lib/oeqa/selftest/cases/manifest.py index bbb92c17409..2c103c06fe3 100644 --- a/meta/lib/oeqa/selftest/cases/manifest.py +++ b/meta/lib/oeqa/selftest/cases/manifest.py @@ -94,7 +94,7 @@ class VerifyManifest(OESelftestTestCase): if not os.path.isfile(mpath[k]): self.logger.debug("{}: {} does not exist".format( self.classname, mpath[k])) - raise IOError + raise OSError m_entry[k] = ManifestEntry(mpath[k]) pkgdata_dir[k] = self.get_dir_from_bb_var('PKGDATA_DIR', @@ -104,11 +104,11 @@ class VerifyManifest(OESelftestTestCase): if not os.path.exists(reverse_dir[k]): self.logger.debug("{}: {} does not exist".format( self.classname, reverse_dir[k])) - raise IOError + raise OSError except OSError: raise self.skipTest("{}: Error in obtaining manifest dirs"\ .format(self.classname)) - except IOError: + except OSError: msg = "{}: Error cannot find manifests in the specified dir:\n{}"\ .format(self.classname, mdir) self.fail(msg) @@ -137,18 +137,18 @@ class VerifyManifest(OESelftestTestCase): mfilename = get_bb_var("IMAGE_LINK_NAME", self.buildtarget)\ + ".manifest" mpath = os.path.join(mdir, mfilename) - if not os.path.isfile(mpath): raise IOError + if not os.path.isfile(mpath): raise OSError m_entry = ManifestEntry(mpath) pkgdata_dir = {} pkgdata_dir = self.get_dir_from_bb_var('PKGDATA_DIR', self.buildtarget) revdir = os.path.join(pkgdata_dir, 'runtime-reverse') - if not os.path.exists(revdir): raise IOError + if not os.path.exists(revdir): raise OSError except OSError: raise self.skipTest("{}: Error in obtaining manifest dirs"\ .format(self.classname)) - except IOError: + except OSError: msg = "{}: Error cannot find manifests in dir:\n{}"\ .format(self.classname, mdir) self.fail(msg) diff --git a/meta/lib/oeqa/utils/ftools.py b/meta/lib/oeqa/utils/ftools.py index a50aaa84c29..3a10ae79d45 100644 --- a/meta/lib/oeqa/utils/ftools.py +++ b/meta/lib/oeqa/utils/ftools.py @@ -36,7 +36,7 @@ def remove_from_file(path, data): return try: rdata = read_file(path) - except IOError as e: + except OSError as e: # if file does not exit, just quit, otherwise raise an exception if e.errno == errno.ENOENT: return diff --git a/meta/lib/oeqa/utils/qemurunner.py b/meta/lib/oeqa/utils/qemurunner.py index dada3166187..26782518e4e 100644 --- a/meta/lib/oeqa/utils/qemurunner.py +++ b/meta/lib/oeqa/utils/qemurunner.py @@ -119,7 +119,7 @@ class QemuRunner: self.logger.debug("Created listening socket for qemu serial console on: 127.0.0.1:%s" % port) return (sock, port) - except socket.error: + except OSError: sock.close() raise @@ -216,7 +216,7 @@ class QemuRunner: if self.serial_ports >= 2: self.threadsock, threadport = self.create_socket() self.server_socket, self.serverport = self.create_socket() - except socket.error as msg: + except OSError as msg: self.logger.error("Failed to create listening socket: %s" % msg[1]) return False @@ -858,7 +858,7 @@ class LoggingThread(threading.Thread): def recv(self, count, sock): try: data = sock.recv(count) - except socket.error as e: + except OSError as e: if e.errno == errno.EAGAIN or e.errno == errno.EWOULDBLOCK: return b'' else: diff --git a/meta/lib/oeqa/utils/qemutinyrunner.py b/meta/lib/oeqa/utils/qemutinyrunner.py index d1ccf65223f..d4a42304e23 100644 --- a/meta/lib/oeqa/utils/qemutinyrunner.py +++ b/meta/lib/oeqa/utils/qemutinyrunner.py @@ -55,7 +55,7 @@ class QemuTinyRunner(QemuRunner): self.server_socket.connect(self.socketfile) bb.note("Created listening socket for qemu serial console.") tries = 0 - except socket.error as msg: + except OSError as msg: self.server_socket.close() bb.fatal("Failed to create listening socket.") tries -= 1 From patchwork Sun Nov 15 08:48:13 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104201 Received: from mail-wm1-f54.google.com (mail-wm1-f54.google.com [209.85.128.54]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4320.1794732546813233541 for ; Sun, 15 Nov 2026 00:49:07 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=DoQbdD23; spf=pass (domain: linuxfoundation.org, ip: 209.85.128.54, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wm1-f54.google.com with SMTP id 5b1f17b1804b1-4a214c5c4c0so26085785e9.3 for ; Sun, 15 Nov 2026 00:49:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732545; x=1795337345; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=o5KzdtHiO68HQtBVOHZpkOLC1gZpGTHOF5BngzqBzPo=; b=DoQbdD23gply9F0gZaaIUY335P+bYgqXrEncuWn42lfw8qQOkMyGHayhigk1g6ddxK eMO5DSUM0rJcdUEK7h3vMePBGSu0SFh9zZmgjlTbADXCzhLmB2+S+WJ930dhrZ7rH8R+ jTkCPeNZPsJblBPDfh+dRqx8NMF3T9OX0aQDg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732545; x=1795337345; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=o5KzdtHiO68HQtBVOHZpkOLC1gZpGTHOF5BngzqBzPo=; b=hw+wHGv+7eoUs2/Iiq8ToveklNl1EqquGEEAQa2bi4SeoqrvinMiWMynn0rwN9L5/h MwKr/pQK9e3DOBVibrj6bfxfrO9wJIzv3ndMlRifFYIWNOE9/tI7pehsxboTZeaqUxiS mumUyK8sOj654dmldOzCgtGz7SoAspGpix2efIsRlJThIVOsCj5hQyclu991zN4O8kp+ NCIKe2B68zT5iWOcnw3mSuFHPg0ut8N0QkF18PfBjCi1pj1HtzMH6KyZIk0UV/uJIztH 7xAlmQNseVYjvM0aB/vIRjHxtKZdrUai39hYOUCwBXVSvS/OhxxbQkKSfW1P2ZJO6IVc wdeg== X-Gm-Message-State: APuU4Z+yBsVUarttppf/zhaSXOs8v1UVy7wuV6NbpepB1w82GSEAASlj QBKTREmgbBUef8T9/xWhWVzp80qtm3qkH9BCyyNpdsoZcxUzZsr1UrM8lrXIqAhvJU/Rq5xS4g2 Xu+biuAc= X-Gm-Gg: AYBFou3XzKkOfGiiS2UB/fTjj3xOAKcU6vIptQxnQRMaIwrZ2s2IxVdNyxlopWhmoMn Xe0V4E6JMIU4BfrbGqgbaOuoMTOW3R4PJhhaLKDXQHoepYdW3To+uQ2v9dHJo/6PYxoysxaZCXv RFAdMTQ2JBpmonI5vfTbNSf/V+yYwG4JdLcivLDnmkPv9IhBAcU0letnjOzA8gpbAHfOr23ceuT 5DjdfJ1vWpj3RFXBACIuv3MxmNwja/LTIm3TRXnS5OTSbMVXdSuUdoLCTxkMESovrYZoXTizVXV snMd5oUkH85jM42159lPEg1iUSDoGOpgq/jw5ndoN4+Hxpm/w4sBzjcbbrJSVqNACQMwAii3A0D X6GV/6y0KKa1SCclfp8LY16N6FLNE3vqukohop87oEbXAhRfVM2Rl2c5ltMD9DH4JzmX3yTgUKp I+eTaOncVmKx/A54fot1zJ8xTMRIIT+h/LetxzOvVTc/Su5ApjCBIAfCFwC+SJjcZukWcmqs0tD tNlAZJXrUTuqaIipmNqcPBcWETtAIk8+otqgxtYXkMFCGjawIXpqgYyGyxBpnJguVLpaSLB9S9p UwnN6uNG7zACLhC3XBd8VgBjGzYIZ3fVdf63C9Kb4XpsR0yWyang94Z5tRDgqyF3Ma44U6nQTGd qsf0= X-Received: by 2002:a05:600c:6208:b0:4a7:6bc7:f778 with SMTP id 5b1f17b1804b1-4bb55a93a9amr145815115e9.30.1794732545024; Sun, 15 Nov 2026 00:49:05 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.03 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:03 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 10/41] oeqa: Use 'is None' for None comparisons Date: Sun, 15 Nov 2026 08:48:13 +0000 Message-ID: <20261115084845.701136-10-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:12 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250241 Comparing to None with == or != is unidiomatic and can be overridden by __eq__; use identity checks instead. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/core/loader.py | 2 +- meta/lib/oeqa/core/target/ssh.py | 4 ++-- meta/lib/oeqa/oetest.py | 2 +- meta/lib/oeqa/selftest/cases/oelib/path.py | 2 +- meta/lib/oeqa/utils/subprocesstweak.py | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/meta/lib/oeqa/core/loader.py b/meta/lib/oeqa/core/loader.py index 1c964dadae6..5e96988b7a9 100644 --- a/meta/lib/oeqa/core/loader.py +++ b/meta/lib/oeqa/core/loader.py @@ -40,7 +40,7 @@ def _find_duplicated_modules(suite, directory): def _built_modules_dict(modules, logger): modules_dict = {} - if modules == None: + if modules is None: return modules_dict for module in modules: diff --git a/meta/lib/oeqa/core/target/ssh.py b/meta/lib/oeqa/core/target/ssh.py index 757ab67580c..e380fd84854 100644 --- a/meta/lib/oeqa/core/target/ssh.py +++ b/meta/lib/oeqa/core/target/ssh.py @@ -293,7 +293,7 @@ def SSHCall(command, logger, timeout=None, raw=False, **opts): logger.debug('No output from SSH call') # timout or not, make sure process exits and is not hanging - if process.returncode == None: + if process.returncode is None: try: process.wait(timeout=5) except TimeoutExpired: @@ -339,7 +339,7 @@ def SSHCall(command, logger, timeout=None, raw=False, **opts): # whilst running and ensure we don't leave a process behind. if process.poll() is None: process.kill() - if process.returncode == None: + if process.returncode is None: process.wait() logger.debug('Something went wrong, killing SSH process') raise diff --git a/meta/lib/oeqa/oetest.py b/meta/lib/oeqa/oetest.py index a57cea74b46..f5703ea9cd3 100644 --- a/meta/lib/oeqa/oetest.py +++ b/meta/lib/oeqa/oetest.py @@ -583,7 +583,7 @@ class ExportTestContext(RuntimeTestContext): super().__init__(d, target, exported) tag = parsedArgs.get("tag", None) - self.tagexp = tag if tag != None else d.getVar("TEST_SUITES_TAGS") + self.tagexp = tag if tag is not None else d.getVar("TEST_SUITES_TAGS") self.sigterm = None diff --git a/meta/lib/oeqa/selftest/cases/oelib/path.py b/meta/lib/oeqa/selftest/cases/oelib/path.py index b963e447e37..f573dcbd580 100644 --- a/meta/lib/oeqa/selftest/cases/oelib/path.py +++ b/meta/lib/oeqa/selftest/cases/oelib/path.py @@ -67,7 +67,7 @@ class TestRealPath(TestCase): def test_norm(self): for l in self.LINKS: - if l[2] == None: + if l[2] is None: continue target_p = self.__realpath(l[0], True) diff --git a/meta/lib/oeqa/utils/subprocesstweak.py b/meta/lib/oeqa/utils/subprocesstweak.py index 046667faa98..0da836c48de 100644 --- a/meta/lib/oeqa/utils/subprocesstweak.py +++ b/meta/lib/oeqa/utils/subprocesstweak.py @@ -13,7 +13,7 @@ class OETestCalledProcessError(subprocess.CalledProcessError): s = super().__str__() s = s + "\nStandard Output: " + strify(self.output) # stderr is not available for check_output method - if self.stderr != None: + if self.stderr is not None: s = s + "\nStandard Error: " + strify(self.stderr) return s From patchwork Sun Nov 15 08:48:14 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104196 Received: from mail-wm1-f50.google.com (mail-wm1-f50.google.com [209.85.128.50]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4322.1794732549170850980 for ; Sun, 15 Nov 2026 00:49:09 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=GOt45eer; spf=pass (domain: linuxfoundation.org, ip: 209.85.128.50, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wm1-f50.google.com with SMTP id 5b1f17b1804b1-4bb5b8ef642so12443415e9.1 for ; Sun, 15 Nov 2026 00:49:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732547; x=1795337347; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=aPcZS7rE6fRziMQObKw2iNHYwWSbT/mH6fA4iDEF2Dw=; b=GOt45eersgCNwEe/k2l8XF/YU0tkLCsYtGO9BPNIfES++fqVJkRSbhrCOp9ltsTmLb imIXPrYoLqg+SUuCsFJyv5psgvg1/W7fXYyrne0Pau4kPPJFe2QekalXlDWt3Gb5ScO2 ShdY+kz19yBzj8Br7OF7FBRbu2l7anaMAWh/E= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732547; x=1795337347; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=aPcZS7rE6fRziMQObKw2iNHYwWSbT/mH6fA4iDEF2Dw=; b=ObskzVZaCmjZm3W72GP9qlrxqK6RK3WbtqOHiZyyJ+Zfgbnn9NBN7eplfGd7YMomIB zJZP4lYgi139W4JI3WMTG31zVUeFVI1FmGAj/lw4gyBhWM7vo6PUiMxZn/qzkXM8UXkk 2Foqifaw4iJ0nbK2TbeqIUyifUKAq6jDUgIHY82Nz7sVAQHK2q87yZlxuljo25S5s8fh 1PacnujJPNArG6i59rq8zLon00XWg3HEYAVwxbrgak+6lpBaJ9D/iOH4YGKqEshnyEE8 jlRA0tZVNJd/IVMR3fmc4lCIwQfeQoO3kGqDkmJnM9W59EKgXQoMGbHNOUFrTq2Za6eX NFsQ== X-Gm-Message-State: APuU4Z/vmhaVzrpJdKz3PRZS7ZR6FHphGkYGt5aIVh/A9XQDDv8rfDty wjVkNnjLF+4aSn1nnRX0kpjJ6jHersoemgwjpXXpLWuzJQySQ8/gTdIpGXCSpzdFh1qstgI5pKp igVfXb5M= X-Gm-Gg: AYBFou1EF645FnJ8C4t3Qw3BKYjqp5ACXlouZiEU1KwTi5Yz+32hxL65vWWD8lMZxTj 3Y/gR0Mva57Po2FcO8R6mMvNS+dz7eb81HqkiOZsd390YccrEXWzcCn4AXWiCKirXs/Q98WMgq9 Xx2A2L0rvnUXV26kYxaWBQsLpJGYV7TW936MVQAuP2xw826UR6yqSYbDp83YOWnmusHS9hoxyPO sX3PvwNNY0CK/iJCvqtDgQ4Lyqk42xL1OQnk/M2rgyQNFoNungKfVU5pGhanRFUAX2wjw4e3dXK iRdp/qDEkwenY3zou1F+gaN+JEN9nglVGuMRVrvWf3/b4LUvXAFqbWrT4/+Aipt1+6FexWT8X59 CPDMQU/NITC7feZvOtVsQLKF5aJCOaW1Dr6RV5ZnIkg3As5HBX9Pyv/IeuO9D75uAxSckxIkvOU u1ExKAgSq3olIVoCIjgvNKBXWQ3Q0eXF4Yz18D2HgvWj1z1ek8U3F+74Hujxpz2qtHz6gaQK25b 41SCKuxlzsc933ObLYj+SbPgFWmK1WwSHklsOKHcZGP3aHPgeIk22WCLSewJVXuS41QHJltaX9y yfHM9B+wz4sg5eAPDXxoFb5PRpoEZXiHg3PnCHbshTqUbeSt7hVb2c4dtw== X-Received: by 2002:a05:600c:6091:b0:4bb:6a2d:b426 with SMTP id 5b1f17b1804b1-4bb6a2db60amr27405875e9.1.1794732547244; Sun, 15 Nov 2026 00:49:07 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.05 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:05 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 11/41] oeqa: Drop redundant .keys() calls on dicts Date: Sun, 15 Nov 2026 08:48:14 +0000 Message-ID: <20261115084845.701136-11-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:10 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250242 Dict membership tests and iteration work on the dict directly, so wrapping in list(d.keys()) or calling .keys() is unnecessary. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/sdk/context.py | 4 +- meta/lib/oeqa/selftest/cases/manifest.py | 4 +- meta/lib/oeqa/selftest/cases/pkgdata.py | 56 ++++++++++++------------ 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/meta/lib/oeqa/sdk/context.py b/meta/lib/oeqa/sdk/context.py index 891910d218c..f00e40eb6c6 100644 --- a/meta/lib/oeqa/sdk/context.py +++ b/meta/lib/oeqa/sdk/context.py @@ -34,12 +34,12 @@ class OESDKTestContext(OETestContext): if regex: # do regex match pat = re.compile(pkg) - for p in manifest.keys(): + for p in manifest: if pat.search(p): return True else: # do exact match - if pkg in manifest.keys(): + if pkg in manifest: return True return False diff --git a/meta/lib/oeqa/selftest/cases/manifest.py b/meta/lib/oeqa/selftest/cases/manifest.py index 2c103c06fe3..08b0ceca05b 100644 --- a/meta/lib/oeqa/selftest/cases/manifest.py +++ b/meta/lib/oeqa/selftest/cases/manifest.py @@ -87,7 +87,7 @@ class VerifyManifest(OESelftestTestCase): host = 'nativesdk-packagegroup-sdk-host') try: mdir = self.get_dir_from_bb_var('SDK_DEPLOY', self.buildtarget) - for k in d_target.keys(): + for k in d_target: toolchain_outputname = get_bb_var('TOOLCHAIN_OUTPUTNAME', self.buildtarget) mfilename[k] = "{}.{}.manifest".format(toolchain_outputname, k) mpath[k] = os.path.join(mdir, mfilename[k]) @@ -113,7 +113,7 @@ class VerifyManifest(OESelftestTestCase): .format(self.classname, mdir) self.fail(msg) - for k in d_target.keys(): + for k in d_target: self.logger.debug("{}: Check manifest {}".format( self.classname, m_entry[k].file)) diff --git a/meta/lib/oeqa/selftest/cases/pkgdata.py b/meta/lib/oeqa/selftest/cases/pkgdata.py index 8accf1be097..082c69f8a0d 100644 --- a/meta/lib/oeqa/selftest/cases/pkgdata.py +++ b/meta/lib/oeqa/selftest/cases/pkgdata.py @@ -129,15 +129,15 @@ class OePkgdataUtilTests(OESelftestTestCase): # Test recipe-space package name result = runCmd('oe-pkgdata-util list-pkg-files zlib-dev zlib-doc') files = splitoutput(result.output) - self.assertIn('zlib-dev', list(files.keys()), "listed pkgs. files: %s" %result.output) - self.assertIn('zlib-doc', list(files.keys()), "listed pkgs. files: %s" %result.output) + self.assertIn('zlib-dev', files, "listed pkgs. files: %s" %result.output) + self.assertIn('zlib-doc', files, "listed pkgs. files: %s" %result.output) self.assertIn(os.path.join(includedir, 'zlib.h'), files['zlib-dev']) self.assertIn(os.path.join(mandir, 'man3/zlib.3'), files['zlib-doc']) # Test runtime package name result = runCmd('oe-pkgdata-util list-pkg-files -r libz1 libz-dev') files = splitoutput(result.output) - self.assertIn('libz1', list(files.keys()), "listed pkgs. files: %s" %result.output) - self.assertIn('libz-dev', list(files.keys()), "listed pkgs. files: %s" %result.output) + self.assertIn('libz1', files, "listed pkgs. files: %s" %result.output) + self.assertIn('libz-dev', files, "listed pkgs. files: %s" %result.output) self.assertGreater(len(files['libz1']), 1) libspec = os.path.join(libdir, 'libz.so.1.*') found = False @@ -150,12 +150,12 @@ class OePkgdataUtilTests(OESelftestTestCase): # Test recipe result = runCmd('oe-pkgdata-util list-pkg-files -p zlib') files = splitoutput(result.output) - self.assertIn('zlib-dbg', list(files.keys()), "listed pkgs. files: %s" %result.output) - self.assertIn('zlib-doc', list(files.keys()), "listed pkgs. files: %s" %result.output) - self.assertIn('zlib-dev', list(files.keys()), "listed pkgs. files: %s" %result.output) - self.assertIn('zlib-staticdev', list(files.keys()), "listed pkgs. files: %s" %result.output) - self.assertIn('zlib', list(files.keys()), "listed pkgs. files: %s" %result.output) - self.assertNotIn('zlib-locale', list(files.keys()), "listed pkgs. files: %s" %result.output) + self.assertIn('zlib-dbg', files, "listed pkgs. files: %s" %result.output) + self.assertIn('zlib-doc', files, "listed pkgs. files: %s" %result.output) + self.assertIn('zlib-dev', files, "listed pkgs. files: %s" %result.output) + self.assertIn('zlib-staticdev', files, "listed pkgs. files: %s" %result.output) + self.assertIn('zlib', files, "listed pkgs. files: %s" %result.output) + self.assertNotIn('zlib-locale', files, "listed pkgs. files: %s" %result.output) # (ignore ptest, might not be there depending on config) self.assertIn(os.path.join(includedir, 'zlib.h'), files['zlib-dev']) self.assertIn(os.path.join(mandir, 'man3/zlib.3'), files['zlib-doc']) @@ -163,36 +163,36 @@ class OePkgdataUtilTests(OESelftestTestCase): # Test recipe, runtime result = runCmd('oe-pkgdata-util list-pkg-files -p zlib -r') files = splitoutput(result.output) - self.assertIn('libz-dbg', list(files.keys()), "listed pkgs. files: %s" %result.output) - self.assertIn('libz-doc', list(files.keys()), "listed pkgs. files: %s" %result.output) - self.assertIn('libz-dev', list(files.keys()), "listed pkgs. files: %s" %result.output) - self.assertIn('libz-staticdev', list(files.keys()), "listed pkgs. files: %s" %result.output) - self.assertIn('libz1', list(files.keys()), "listed pkgs. files: %s" %result.output) - self.assertNotIn('libz-locale', list(files.keys()), "listed pkgs. files: %s" %result.output) + self.assertIn('libz-dbg', files, "listed pkgs. files: %s" %result.output) + self.assertIn('libz-doc', files, "listed pkgs. files: %s" %result.output) + self.assertIn('libz-dev', files, "listed pkgs. files: %s" %result.output) + self.assertIn('libz-staticdev', files, "listed pkgs. files: %s" %result.output) + self.assertIn('libz1', files, "listed pkgs. files: %s" %result.output) + self.assertNotIn('libz-locale', files, "listed pkgs. files: %s" %result.output) self.assertIn(os.path.join(includedir, 'zlib.h'), files['libz-dev']) self.assertIn(os.path.join(mandir, 'man3/zlib.3'), files['libz-doc']) self.assertIn(os.path.join(libdir, 'libz.a'), files['libz-staticdev']) # Test recipe, unpackaged result = runCmd('oe-pkgdata-util list-pkg-files -p zlib -u') files = splitoutput(result.output) - self.assertIn('zlib-dbg', list(files.keys()), "listed pkgs. files: %s" %result.output) - self.assertIn('zlib-doc', list(files.keys()), "listed pkgs. files: %s" %result.output) - self.assertIn('zlib-dev', list(files.keys()), "listed pkgs. files: %s" %result.output) - self.assertIn('zlib-staticdev', list(files.keys()), "listed pkgs. files: %s" %result.output) - self.assertIn('zlib', list(files.keys()), "listed pkgs. files: %s" %result.output) - self.assertIn('zlib-locale', list(files.keys()), "listed pkgs. files: %s" %result.output) # this is the key one + self.assertIn('zlib-dbg', files, "listed pkgs. files: %s" %result.output) + self.assertIn('zlib-doc', files, "listed pkgs. files: %s" %result.output) + self.assertIn('zlib-dev', files, "listed pkgs. files: %s" %result.output) + self.assertIn('zlib-staticdev', files, "listed pkgs. files: %s" %result.output) + self.assertIn('zlib', files, "listed pkgs. files: %s" %result.output) + self.assertIn('zlib-locale', files, "listed pkgs. files: %s" %result.output) # this is the key one self.assertIn(os.path.join(includedir, 'zlib.h'), files['zlib-dev']) self.assertIn(os.path.join(mandir, 'man3/zlib.3'), files['zlib-doc']) self.assertIn(os.path.join(libdir, 'libz.a'), files['zlib-staticdev']) # Test recipe, runtime, unpackaged result = runCmd('oe-pkgdata-util list-pkg-files -p zlib -r -u') files = splitoutput(result.output) - self.assertIn('libz-dbg', list(files.keys()), "listed pkgs. files: %s" %result.output) - self.assertIn('libz-doc', list(files.keys()), "listed pkgs. files: %s" %result.output) - self.assertIn('libz-dev', list(files.keys()), "listed pkgs. files: %s" %result.output) - self.assertIn('libz-staticdev', list(files.keys()), "listed pkgs. files: %s" %result.output) - self.assertIn('libz1', list(files.keys()), "listed pkgs. files: %s" %result.output) - self.assertIn('libz-locale', list(files.keys()), "listed pkgs. files: %s" %result.output) # this is the key one + self.assertIn('libz-dbg', files, "listed pkgs. files: %s" %result.output) + self.assertIn('libz-doc', files, "listed pkgs. files: %s" %result.output) + self.assertIn('libz-dev', files, "listed pkgs. files: %s" %result.output) + self.assertIn('libz-staticdev', files, "listed pkgs. files: %s" %result.output) + self.assertIn('libz1', files, "listed pkgs. files: %s" %result.output) + self.assertIn('libz-locale', files, "listed pkgs. files: %s" %result.output) # this is the key one self.assertIn(os.path.join(includedir, 'zlib.h'), files['libz-dev']) self.assertIn(os.path.join(mandir, 'man3/zlib.3'), files['libz-doc']) self.assertIn(os.path.join(libdir, 'libz.a'), files['libz-staticdev']) From patchwork Sun Nov 15 08:48:15 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104197 Received: from mail-wr1-f52.google.com (mail-wr1-f52.google.com [209.85.221.52]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4323.1794732550025485827 for ; Sun, 15 Nov 2026 00:49:10 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=DtwkGzB4; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.52, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f52.google.com with SMTP id ffacd0b85a97d-492690dd5daso2455307f8f.1 for ; Sun, 15 Nov 2026 00:49:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732548; x=1795337348; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=c+03J/CsK8wDzWgU89MvKmc42EQnURV+ohj2aNJ1pfQ=; b=DtwkGzB4dL+JYDopx033wcWMK53dsfkoK2PGQ+rPu7YP/d7ysBATWME/42Bv7a6j3M m6YRm+TeJn1nYc4iCyclhCBd1Z2F5U0GHDlLHzKswbzF9VMUldLu107EFlwbFsQlk7PB gZmCM2oLSYVk5gkAEPVAbe7vpZ92UkcGO0xmc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732548; x=1795337348; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=c+03J/CsK8wDzWgU89MvKmc42EQnURV+ohj2aNJ1pfQ=; b=hSZNdlau6FSPmyN9Y5qIFoOf8omhYXgx0VohlSdwKpUQFghu+P++U8gPJJCYa0I4Gy urMdxcVgnNOnVk2MFIqmGOJ/TGciEAS8/ZLTc2GE/McWwDA+/ppMjkSXgazIf7swwh9t 1+mF13Jjsdapmnmg1n89YiDd7rP3kqrnq6bJVJ0OOwoEyMgtkjLNhCu78OpBw8Wyoyii UN5JXdg8kjl6LBUz6kByJGzJqEJLcwZSZgzvWRuB3KTcJjUdoJetjvY2zmEBh5NAB6vQ aOT1tafg5wnyOWhHRMzp6bESDA4DknUegkAPyy4cGIsuEtt+y6So7+xmPiQEhLdYpEeN EB3g== X-Gm-Message-State: APuU4Z8k0zhioVVmNW8HYqAZSqOi4nE8IyFua980XOK7V7kbX6Xa5EKL 9f/C76WcDcXRrJwV4/DUcop5P2ChhHI5oMsgIdxnJ81TVtA3oefGxitwXax/xwdJesB5pEsbqjd uN8err1g= X-Gm-Gg: AYBFou3CvMbuqnSacngPyAtEOFsoRQzlmLgXnfPZDhJxDo5d3HR05djKYQ/3uA4MLAq daNS3oh/Ksc7n4bC6xystYtQcYq+7yPEbf2NDmf5dOh+Dvg2K7oo4/3Nb5S9fHV4tL7on0CTCNc iT9rDoYR1Kn6JxN0uiXTA0ndTCEpaunHhljMnyR2BJ/CGuwqV3xeArJ/DfWZaGh7C7BFVjA5AP/ Wz+B+anVz+vT51uxQ0H5czr2eQEYdtXhAE//ybJZQk1EFXXEBjDgH6HEGNClbuoyog0Yu5r0i2u RFJa4x3ocijOj4rUjXanqz93Gh4wRlmtJAwirnXymUnIh2qGQvyNIBlQbT/By4b8buLzB6K+r4D myB+WzNRGWarwK6TXINQq2JGo1OFJ8vu9fY8sEfFtv0XD5SJax7WHXpxgbLNhwsnBXdX/LaiQuP PWiMjwRYhj6pTW9/baVbNd0RkzGFLR/QsP2SxEpsSlwKexQkXuBOkVKpRdhSD1PuTcKw81L6ia1 IUyWv8S26e4uowaKSpC2oNmYyIX4UhCNPmrunAUZ35z5ft81AEm8NdBmxaTL3kAOOV3CkZdkQ5z 7CBoPslaY6yysCJ1RNYbNxGwNc95YItjLhXoZq68m7gxijABNDQCdHhhed8= X-Received: by 2002:a05:6000:1863:b0:48f:bf3c:1631 with SMTP id ffacd0b85a97d-49c7026386fmr17779202f8f.21.1794732548267; Sun, 15 Nov 2026 00:49:08 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.07 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:07 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 12/41] oeqa/core/context: Use isinstance() for type check Date: Sun, 15 Nov 2026 08:48:15 +0000 Message-ID: <20261115084845.701136-12-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:10 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250243 AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/core/context.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/lib/oeqa/core/context.py b/meta/lib/oeqa/core/context.py index 9745286548e..3bd65ba35f6 100644 --- a/meta/lib/oeqa/core/context.py +++ b/meta/lib/oeqa/core/context.py @@ -23,7 +23,7 @@ class OETestContext: os.path.abspath(__file__)), "../files")) def __init__(self, td=None, logger=None): - if not type(td) is dict: + if not isinstance(td, dict): raise TypeError("td isn't dictionary type") self.td = td From patchwork Sun Nov 15 08:48:16 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104202 Received: from mail-wr1-f47.google.com (mail-wr1-f47.google.com [209.85.221.47]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4324.1794732551041578320 for ; Sun, 15 Nov 2026 00:49:11 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=FDs8/ms+; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.47, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f47.google.com with SMTP id ffacd0b85a97d-48b001cd92bso1631999f8f.2 for ; Sun, 15 Nov 2026 00:49:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732549; x=1795337349; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=NYzKplmDQ7p03h+oA8+B/qv5QS0AOejn6iNUKy2oB+M=; b=FDs8/ms+O+p6HCbP63btmL6fKNT6+jitI9UFqB43SceZ2sjFqypKByTiq9cwapQs2I 5n5zuu5nXiOVWri1xqTTkuB6kiySqKNXT6guZbsRBbvgawbyxeImF5DxjdEESJAQAO8M mWsGdQlZI5Bt/hEEB02BKnN0XuyEFmLMuDxbw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732549; x=1795337349; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=NYzKplmDQ7p03h+oA8+B/qv5QS0AOejn6iNUKy2oB+M=; b=EDXaZB7OibCbInKdkgundajK4b1c8M50uG3rZtnOjYLKHFEDNN9laHgUJGHiRzkodj xPxPhidzZaJoCYjUcsbyieGyRg93giNG5OTb0mwFLuqcSTkd9yea96zhQTeVOSrHJeqP AY3Tf5dhLBbN1i3zW3yHAjA7ClSPNSFZuP1kuNGZBXjFhx6XWIlBOLQukRsUwVseubPX BIwMmTgD4DfgWOXvGAxTPrBkL2jWQ2CM5WJ+bRRtiNQdkq+kstaVLjOHEKGfynKPg6Ki KN8aMtuVh7I0TqMdpRrTXwjVHEZkmc0v3hm3XrqIkIb7xyo5TfwzIHUT8AvTr6Zomoo1 Cdug== X-Gm-Message-State: APuU4Z/EhVSUwRSzfqiaXbHSCad4wdtQniwMNa54wRXqR6XjK3pMXbnR OYGYGwpzuRiy3kTFuLwM0+GuJP9fUH15aEm08NLvYcHL8mVj7LmeE30fomfngrTNdUaf+zmyCXT YPLXOYTE= X-Gm-Gg: AYBFou1TUs+MoilnrOkSTlfiCXTqpk2kzX0XBnCQUpvopjtZSfGwRPnlSSnQ8TSwKJl XQsxWf1QT8EuKuKCgLhDdjBtKtvhVNYfw4Q634yGR+GGMn08VhYdNksBlfOsEs86lBbgvOcSN0e IG9PzrUC/LAuc7oO4FlJYcjzKcMDguq+nuwAnY9JwKF5ReRx6eJ6gKWmFp1qNN1F5P1qo3x93JX MaAkFi5mcuu9VjmmbagXw20Zynfy/yUlK/3TiRiQiTc6gUvzQ+xvwVCkYJlI8eExzpVSB/IPt3L EQ6hB6slmQc3fFIQPihrsYZiAngu9YVwwvxlzQFe6Y/+4YKuHH68jb2FUEQzTiW/kaDmD5UpaXm wZAjusjS/3+Qf/JfvaAT4nPq1Y9UZEQd9jVi7Cqm3wGzdhPi8IGWGV0hsUGkMH2Lrp/l6WJtSgw YYvYUU6VHkbj1dW1GSIeiSQDIiwDe0E/56lgNUJV7ZGQypD84W2FAOiro+yu1aWReGbaiTmMRXH 4KWQO8vEI8T3BJvR+nTqJLeDp042NvSaS6hVu+e1YeMq2HQDN6wQq31/HL8e1V1flWjoaqy60pa I1BBYXvo2eT3rJ1WbLQtnw1Ni4L1f1XIareLuFNJ50OG9FqoZ+HFgHoBBw== X-Received: by 2002:a05:6000:2f82:b0:48e:3df8:74cb with SMTP id ffacd0b85a97d-49c6d4539edmr16236196f8f.6.1794732549278; Sun, 15 Nov 2026 00:49:09 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.08 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:08 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 13/41] oeqa: Use bare raise to re-raise exceptions Date: Sun, 15 Nov 2026 08:48:16 +0000 Message-ID: <20261115084845.701136-13-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:12 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250244 A bare raise re-raises the current exception without needing to name it. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/selftest/cases/devtool.py | 2 +- meta/lib/oeqa/selftest/cases/manifest.py | 2 +- meta/lib/oeqa/selftest/cases/recipetool.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py index c748c8504bb..3400f90a906 100644 --- a/meta/lib/oeqa/selftest/cases/devtool.py +++ b/meta/lib/oeqa/selftest/cases/devtool.py @@ -2591,7 +2591,7 @@ class DevtoolUpgradeTests(DevtoolBase): if e.errno == errno.EROFS: return False else: - raise e + raise if p == "lib": # Can race with other tests self.add_command_to_tearDown('rmdir --ignore-fail-on-non-empty %s' % dstdir) diff --git a/meta/lib/oeqa/selftest/cases/manifest.py b/meta/lib/oeqa/selftest/cases/manifest.py index 08b0ceca05b..73d262bb43b 100644 --- a/meta/lib/oeqa/selftest/cases/manifest.py +++ b/meta/lib/oeqa/selftest/cases/manifest.py @@ -34,7 +34,7 @@ class VerifyManifest(OESelftestTestCase): except OSError as e: self.logger.debug("{}: checking of {} failed"\ .format(self.classname, manifest)) - raise e + raise return manifest_errors diff --git a/meta/lib/oeqa/selftest/cases/recipetool.py b/meta/lib/oeqa/selftest/cases/recipetool.py index e2365141ac5..a7c7ed7ddbc 100644 --- a/meta/lib/oeqa/selftest/cases/recipetool.py +++ b/meta/lib/oeqa/selftest/cases/recipetool.py @@ -878,7 +878,7 @@ class RecipetoolTests(RecipetoolBase): if e.errno == errno.EROFS: return False else: - raise e + raise if p == "lib": # Can race with other tests self.add_command_to_tearDown('rmdir --ignore-fail-on-non-empty %s' % dstdir) From patchwork Sun Nov 15 08:48:17 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104203 Received: from mail-wr1-f53.google.com (mail-wr1-f53.google.com [209.85.221.53]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4326.1794732553776882469 for ; Sun, 15 Nov 2026 00:49:14 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=MWrDjNGy; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.53, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f53.google.com with SMTP id ffacd0b85a97d-491f34b4e0fso935894f8f.2 for ; Sun, 15 Nov 2026 00:49:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732552; x=1795337352; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=VMrcEYbooq1pYljDR6hpHkfTVzQAC2HQyQLCCv+Hemg=; b=MWrDjNGy5w5iDdZXPTCzjx43irOnRGPmi9/c7DZojWJOTZBgXCVtIRCF4b/+9mOZZz 0W1RWJjqF+Pvly6QQ9x9AL/LwvdjUNZ6AscmNZnsNqBbXhho7SwEkqvV0DnfYeuJLDQM TXp4LfKZ+IvEqUuw5FAN3i/fVaXbgl4j0A5Yw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732552; x=1795337352; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=VMrcEYbooq1pYljDR6hpHkfTVzQAC2HQyQLCCv+Hemg=; b=M/1VtRowyN3ryYGCTlGILP4KEB1arwAQYTnLuL5CwH8Uf3JkV/CA+gD8Q3s1KufmF+ UUvSdgyu8vblJUswDQK7baleC6LF1NHRDbp0xy0kX7Ch18tSCPdUKG8dWfYzYWSWvSTF KoIh3Hzx7yPg+8k7XRdz4LDNPxilkvyIyavFo2CXjfPchD0MLpwNP6vF1xXlOGXLQur0 ZaDm9QvIf5wAON1OLHvURiaTg0XA9RNH6rHsEUhZmCGzjx32XwmaQYmL3eyHUptUi/uS ho/ohAhu5S511+FJBDMb0eJJQVTbdL0ZH7boatEmBrGwECyR+EHjz634i/8intnNDg90 JUSg== X-Gm-Message-State: APuU4Z9enMnIVKbCKhzXqj96DuZu5PB07H8Af9LFx2x3xVBOpjrHt9m4 mX5XEKjuScjtkBEz0hXlE1nTvP4u7pn28aYc+gHBnFe2D+Q0wf4vkkmbApeD7i9ldfl0+S6IMjv agxM5+eA= X-Gm-Gg: AYBFou3cj5Ig4wdfmHNyEt7t9YZ+XljpFf1R6kWvRSRrkQBY7ld3XSZJdiq9CqQdQ8w XuUCqbBlzYkA/RwSaXkliKnOwcR2FibkJbubQyhYh0FopXnA7G6ZXmZLxS59Q8loMlQUK40A79L vKSfTDUzvDwMyPTc9/qLuZ6S53coT+tcW+q9pvua6dgWtnNFTuRDYK4tn3aEQFUlSvDPKWy8MaV /JBQ9ZfmtZYDpGZ0UESH0/ALeGLIVs6hQzV1ngjkBUIfmlS5DGbaKr0K7dbsTFiaXZ+Hqr6BoJM EH/o0POnno0FxLBDPiGKtmA9J4f5avTLrRAgJ9LU7ypGlSJWL7SFubrSe+OkPXGJP7+2ujLQk+R RDOJm4tN1azX4I+oGXYyFQ/uLLImtPLQkaJSd/uhoth92Cij7P8+0ycg3ffkkQ+JOFDjCY4NCY8 QcPjt6Gi6Cbwilfsri02vcjSYbVMgAML3DW2aMxRN1GNEFhsak7t8fBP/L8V9oSmu5Sjnb2e3u9 ojEaDnC+VYRN18jTR582xIOB310PlxZBLNGogsyawV5OgJBACerZYtQOrZaDhwlcJp9529Jc8WZ z20KBy8vn6oZmihcCqbvX+/PvGNsKSt9u7g3/LG/S6+tdZPBV459Y25IXHDhmsXcVKzC7GJFBPK 47gs= X-Received: by 2002:a05:6000:4009:b0:48c:7143:610c with SMTP id ffacd0b85a97d-49c73bf0a80mr17528787f8f.36.1794732551828; Sun, 15 Nov 2026 00:49:11 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.09 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:10 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 14/41] oeqa: Let subprocess decode output instead of calling .decode() Date: Sun, 15 Nov 2026 08:48:17 +0000 Message-ID: <20261115084845.701136-14-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:22 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250245 Pass text=True to the subprocess calls rather than decoding the bytes afterwards. This also covers CalledProcessError.output. Raw socket/pty reads and base64 output are left as bytes. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/core/target/qemu.py | 2 +- meta/lib/oeqa/runtime/cases/boot.py | 4 ++-- meta/lib/oeqa/runtime/cases/dnf.py | 2 +- meta/lib/oeqa/runtime/cases/ping.py | 4 ++-- meta/lib/oeqa/sdk/testsdk.py | 4 ++-- meta/lib/oeqa/sdk/utils/sdkbuildproject.py | 5 +++-- meta/lib/oeqa/sdkext/testsdk.py | 4 ++-- .../lib/oeqa/selftest/cases/yoctotestresultsquerytests.py | 2 +- meta/lib/oeqa/utils/metadata.py | 8 ++++---- meta/lib/oeqa/utils/qemurunner.py | 3 +-- meta/lib/oeqa/utils/qemutinyrunner.py | 4 ++-- 11 files changed, 21 insertions(+), 21 deletions(-) diff --git a/meta/lib/oeqa/core/target/qemu.py b/meta/lib/oeqa/core/target/qemu.py index a4f53747b01..e3e5ec874d5 100644 --- a/meta/lib/oeqa/core/target/qemu.py +++ b/meta/lib/oeqa/core/target/qemu.py @@ -81,7 +81,7 @@ class OEQemuTarget(OESSHTarget): blcmd = ["tail", "-20", self.bootlog] msg += "===== start: snippet =====\n\n" try: - out = subprocess.check_output(blcmd, stderr=subprocess.STDOUT, timeout=1).decode('utf-8') + out = subprocess.check_output(blcmd, stderr=subprocess.STDOUT, timeout=1, text=True) msg += "file: %s\n\n" % self.bootlog msg += out except (subprocess.CalledProcessError, subprocess.TimeoutExpired, FileNotFoundError) as err: diff --git a/meta/lib/oeqa/runtime/cases/boot.py b/meta/lib/oeqa/runtime/cases/boot.py index dcee3311f78..1ea22ac9a63 100644 --- a/meta/lib/oeqa/runtime/cases/boot.py +++ b/meta/lib/oeqa/runtime/cases/boot.py @@ -24,8 +24,8 @@ class BootTest(OERuntimeTestCase): while count < 5: time.sleep(5) cmd = 'ping -c 1 %s' % self.target.ip - proc = Popen(cmd, shell=True, stdout=PIPE) - output += proc.communicate()[0].decode('utf-8') + proc = Popen(cmd, shell=True, stdout=PIPE, text=True) + output += proc.communicate()[0] if proc.poll() == 0: count += 1 else: diff --git a/meta/lib/oeqa/runtime/cases/dnf.py b/meta/lib/oeqa/runtime/cases/dnf.py index 1becc8d8a02..e96f2ac765d 100644 --- a/meta/lib/oeqa/runtime/cases/dnf.py +++ b/meta/lib/oeqa/runtime/cases/dnf.py @@ -103,7 +103,7 @@ class DnfRepoTest(DnfTest): @OETestDepends(['dnf.DnfRepoTest.test_dnf_install_from_disk']) def test_dnf_install_from_http(self): output = subprocess.check_output('%s %s -name dnf-test-dep*' % (bb.utils.which(os.getenv('PATH'), "find"), - os.path.join(self.tc.td['WORKDIR'], 'oe-testimage-repo')), shell=True).decode("utf-8") + os.path.join(self.tc.td['WORKDIR'], 'oe-testimage-repo')), shell=True, text=True) rpm_path = output.split("/")[-2] + "/" + output.split("/")[-1] url = 'http://%s:%s/%s' %(self.target.server_ip, self.repo_server.port, rpm_path) self.dnf_with_repo('remove -y dnf-test-dep') diff --git a/meta/lib/oeqa/runtime/cases/ping.py b/meta/lib/oeqa/runtime/cases/ping.py index baea1b385ba..f4c57f0f1ac 100644 --- a/meta/lib/oeqa/runtime/cases/ping.py +++ b/meta/lib/oeqa/runtime/cases/ping.py @@ -28,8 +28,8 @@ class PingTest(OERuntimeTestCase): try: while count < 5: cmd = 'ping -c 1 %s' % self.target.ip - proc = Popen(cmd, shell=True, stdout=PIPE) - output += proc.communicate()[0].decode('utf-8') + proc = Popen(cmd, shell=True, stdout=PIPE, text=True) + output += proc.communicate()[0] if proc.poll() == 0: count += 1 else: diff --git a/meta/lib/oeqa/sdk/testsdk.py b/meta/lib/oeqa/sdk/testsdk.py index 747608f260c..ee25d682b95 100644 --- a/meta/lib/oeqa/sdk/testsdk.py +++ b/meta/lib/oeqa/sdk/testsdk.py @@ -66,9 +66,9 @@ class TestSDK(TestSDKBase): import subprocess try: - subprocess.check_output("cd %s; %s < X-Patchwork-Id: 104206 Received: from mail-wr1-f46.google.com (mail-wr1-f46.google.com [209.85.221.46]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.4375.1794732554563772704 for ; Sun, 15 Nov 2026 00:49:14 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=S+uyfo60; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.46, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f46.google.com with SMTP id ffacd0b85a97d-48e47347279so932704f8f.1 for ; Sun, 15 Nov 2026 00:49:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732553; x=1795337353; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=4DDzpaod2tpr+xRjXxtEkl7Whr1Pi8UlTc8/bpsFLjM=; b=S+uyfo6056Dbo1EuDCJKZvzH6Jzcf0jyFuxIhhiwfzrY9z4/BZR244quKQ9JA4Ca4b 5o/25KRiv6rgKbaTPq/kxWUwMwq142Y/ly8sUWl4k7fzciquvUum7zU2VpE9Qyc7deGq C0xFMLsHeTBG9uEpGw1s4EiZkI94H4NyNNlS4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732553; x=1795337353; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=4DDzpaod2tpr+xRjXxtEkl7Whr1Pi8UlTc8/bpsFLjM=; b=J5EDvFHimr1CrmwEDq5gu+fEJoa/rrB9l4C5R5qyXFBKHuvblvZI9gM2W0MKBcP7EA k7yNMX408apIA5ygHCBI+nVbjXSWe9nvw1ba8lEh0kHkPcl1Q+7gjm63Dpq68EN0ii0W mC+wjNTXjRAhXEni7E2nNqcOxftc0WMFUUrpFzcjIkTglyKEIp44d+6kCqbTAro48Pdc kv6oYANRZKtfgXfF35fwXFGWjSS+ccg44g9M7cX1F+5+KV+gIvvNJ0pDr6qYR53OJ9m4 4Mq+2H6KgnOJ+aDiDBHY99deOs9R/bzyUyHu819T4bPbhOzztcS/J3nMbxq3THHAyso3 YkWw== X-Gm-Message-State: APuU4Z+/aCf+C+XPew8b7DufvAEhrFsyf3/boFsYf4HPiT+YEgqO/S1H +c3t1LfCMUn/S8LS0v94TgaM3PUgW4Bla9OSJdhmBGEyw2AA7wNxvb+RqQp1BBD7xhqoretuXE6 /j5d4Az4= X-Gm-Gg: AYBFou21YKKwShMKnqM+IFU+EgZX4uIwY1w/32ZPAAg8NF0icLkx/CawPSKtUH1dUJn UG3EwwLgYAX0Xf0vofe9Nye5IzcsWR0PMCKnl4sVdenEPx2IaUYcIBt519y7LOQ/7Lnmg57pSjo Zbt8e3FYlgX0EJa0ClTGnfSPKzzsOUZJ31LnHb0xnIGWvt/8Z+6AQygrfYJRAorKeYd6IYj8XQ9 ZF9mtV96qmVfvj+DV1QJwtD1BZvjfa5EYbdOx2Uf98UDxmCPUkdWotm8Seklgnofb3eKGvW57fj SSXD45Lnsyh/ebAjIyn4/2Gkaompr8ncM1RBaCedQ09hg0VxzrKvzUeTfTH28h2GXaNsLGScTdb duK5ovg1fsiCfwP+qVKF5xKCQWZb4oMX4TfskZlzNbYEvp6Y72tP4QpIU1tBHxF/8hggYB37Csj vXo3A5eBHWhPeKqzaJ8/dU470stttTvS/tcPDGWv/JZJ7bE4deOPNb8pnuir6o0gnw67YjXTQDi ZwnTlYUOSeghzzj8+3oDUuPdkggv7hBdinGZhgPPw1TwKnzGTW87g/bCIyIFPMyq00fTkujt/vL WIomJS+b/iIJGKeRVUtacIbcSr1RrUAt3VM/uyPr16pZW/i7tgwQmQLIyg== X-Received: by 2002:a5d:584c:0:b0:48a:f0cd:8712 with SMTP id ffacd0b85a97d-49c7325b837mr17553840f8f.50.1794732552845; Sun, 15 Nov 2026 00:49:12 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.11 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:12 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 15/41] oeqa/selftest/manifest: Remove broken/unused code Date: Sun, 15 Nov 2026 08:48:18 +0000 Message-ID: <20261115084845.701136-15-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:22 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250246 The code was using a broken comparison operator. We always set target anyway, so drop the broken code rather than fix it. Signed-off-by: Richard Purdie --- meta/lib/oeqa/selftest/cases/manifest.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/meta/lib/oeqa/selftest/cases/manifest.py b/meta/lib/oeqa/selftest/cases/manifest.py index 73d262bb43b..ba9106d6cd4 100644 --- a/meta/lib/oeqa/selftest/cases/manifest.py +++ b/meta/lib/oeqa/selftest/cases/manifest.py @@ -40,8 +40,7 @@ class VerifyManifest(OESelftestTestCase): #this will possibly move from here @classmethod - def get_dir_from_bb_var(self, bb_var, target = None): - target == self.buildtarget if target == None else target + def get_dir_from_bb_var(self, bb_var, target): directory = get_bb_var(bb_var, target); if not directory or not os.path.isdir(directory): self.logger.debug("{}: {} points to {} when target = {}"\ From patchwork Sun Nov 15 08:48:19 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104207 Received: from mail-wr1-f42.google.com (mail-wr1-f42.google.com [209.85.221.42]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4328.1794732555792161191 for ; Sun, 15 Nov 2026 00:49:16 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=LrPoLDOp; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.42, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f42.google.com with SMTP id ffacd0b85a97d-48e09aa5264so1076562f8f.2 for ; Sun, 15 Nov 2026 00:49:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732554; x=1795337354; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=tVH0GprHG5mqENHUnT+8gkaKJ+YKJh9i/+APQFd9NrE=; b=LrPoLDOpjMrvXgZFdSNyVLCvi5fp/0rIC7eRZ7MgLy3b5k+KwGZ5lGpAMWbKOn+t1O 5gTmY1gcDvh3qmfxqzYh69oqQ4DSRFv1PbFENkB4F+GogmoMvxkxLztvLHO5Yh1H8i8j +Q2C7zIipaDDpN5uXyYD/BfzG62JaBgn4TOtA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732554; x=1795337354; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=tVH0GprHG5mqENHUnT+8gkaKJ+YKJh9i/+APQFd9NrE=; b=kku9wArQmX85Q90p/gApHEz1a9j8AhGn5QmxSVAgRrAKHC4ZksbP6TbPSx/g57q3jI q2NtRhBHw7M+t3kNmTzRv6ecgsSUBzB+xI1lGKeoKyJNGB53koLINqoKMgVmKyCZ1+I1 Fgcc5erzEnkBgJhwfvqtlrvnuH24Wn3Kc+0kHe9lPLu6PJ5J0BazHCNyWk/E2WUmhNGS U5DNxS9euGjah051Z80NNAS+0P34P/fQep7Qk/0jI+8FU48vivEE8iokI8Qjx/fA0A3l WHAJQmpVVrgJ09zkO8zFvQqt//x1gDHP7qvxMXD23f15ZStrsTZjaos1P6TG79D9qDSd BgIw== X-Gm-Message-State: APuU4Z/lg8EfpHckanJh0c2H9tcXAxXMdj/SeAWoVWxDJryxZ6C70twS ey3c1lvkAqQVkVuLofQVgMD5Av2Vh5Y7KmfUWepekcqze2yzvlw8oEFNXEPsZ/TNVb8YdbIU/bt A+iroEwQ= X-Gm-Gg: AYBFou1bJEC0gbaFg+w4IRx+I8Mc9imCU7cfwmwG16H3KiCGBbUhQU93XcFZYi68CTe p4P28JL7PwPHWlMOlsPZUIBsUeDBCLyITCgdm9jjIGcsoOf2JMy335rGBeVCb42exLiOFcdh4Hk KquaW6o9qUAAqOqbvKHfG1RybMVdOJcUs/4sCtc2pmaw+WyNE+9SJjQTzHoFQ5xi2aA0qX9TEHo 3iCNXm8lp7ypAQkDbwVu+sIM1sRBkSNYbOOy4YvmbELvD6qqOxEuqrexaSEJK1jr0REbZCHTJyf Y/09n/pEbgKbnejXaZJOGtCJpd39LQgLrVhtL46jfxwy0nEuyB/mwy2XluI1JribYwvI/8R1xoh Jkdr7TcOOf06O0Ir2IDI+MyQEBBTGb6K2qUpzSuo9Wdw/HeT0BI2QTC2tQ+UCMjS3hNNpjY1dw3 HXrQVVLg96yzzDkEN+YDADLbh/3anRAOIRhpRfhBu92ey9qqMFeVKVs503tQ39LuWGsTSp0RR0T M/oojAsj7w/YER78hdI45dJBl9IQkJhDCpZLV3Q/LC3elN2KFGhyQYZS2WT2ptRcHQTsI+p08wR z3Q0bS/H0aL8uWTcYijZQsKq3h9Lfs7gBY3mvd1yg3QL9gzAQoYnXg8JPw== X-Received: by 2002:a05:600c:6994:b0:4bb:647d:dabe with SMTP id 5b1f17b1804b1-4bb647ddc1bmr76150015e9.3.1794732553824; Sun, 15 Nov 2026 00:49:13 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.12 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:13 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 16/41] oeqa/utils/testexport.py: Drop file Date: Sun, 15 Nov 2026 08:48:19 +0000 Message-ID: <20261115084845.701136-16-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:22 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250247 Nothing uses these functions. Signed-off-by: Richard Purdie --- meta/lib/oeqa/utils/testexport.py | 265 ------------------------------ 1 file changed, 265 deletions(-) delete mode 100644 meta/lib/oeqa/utils/testexport.py diff --git a/meta/lib/oeqa/utils/testexport.py b/meta/lib/oeqa/utils/testexport.py deleted file mode 100644 index 3ab024d9e99..00000000000 --- a/meta/lib/oeqa/utils/testexport.py +++ /dev/null @@ -1,265 +0,0 @@ -# -# Copyright (C) 2015 Intel Corporation -# -# SPDX-License-Identifier: MIT -# - -# Provides functions to help with exporting binaries obtained from built targets - -import os, re, glob as g, shutil as sh,sys -from time import sleep -from .commands import runCmd -from difflib import SequenceMatcher as SM - -try: - import bb -except ImportError: - class my_log(): - def __init__(self): - pass - def plain(self, msg): - if msg: - print(msg) - def warn(self, msg): - if msg: - print("WARNING: " + msg) - def fatal(self, msg): - if msg: - print("FATAL:" + msg) - sys.exit(1) - bb = my_log() - - -def determine_if_poky_env(): - """ - used to determine if we are inside the poky env or not. Usefull for remote machine where poky is not present - """ - check_env = True if ("/scripts" and "/bitbake/bin") in os.getenv("PATH") else False - return check_env - - -def get_dest_folder(tune_features, folder_list): - """ - Function to determine what rpm deploy dir to choose for a given architecture based on TUNE_FEATURES - """ - features_list = tune_features.split(" ") - features_list.reverse() - features_list = "_".join(features_list) - match_rate = 0 - best_match = None - for folder in folder_list: - curr_match_rate = SM(None, folder, features_list).ratio() - if curr_match_rate > match_rate: - match_rate = curr_match_rate - best_match = folder - return best_match - - -def process_binaries(d, params): - param_list = params - export_env = d.getVar("TEST_EXPORT_ONLY") - - def extract_binary(pth_to_pkg, dest_pth=None): - tar_command = runCmd("which tar") - rpm2archive_command = runCmd("ls /usr/bin/rpm2archive") - if (tar_command.status != 0) and (rpm2archive_command.status != 0): - bb.fatal("Either \"rpm2archive\" or \"tar\" tools are not available on your system." - "All binaries extraction processes will not be available, crashing all related tests." - "Please install them according to your OS recommendations") # will exit here - if dest_pth: - os.chdir(dest_pth) - else: - os.chdir("%s" % os.sep)# this is for native package - extract_bin_command = runCmd("%s -n %s | %s xv" % (rpm2archive_command.output, pth_to_pkg, tar_command.output)) # semi-hardcoded because of a bug on poky's rpm2cpio - return extract_bin_command - - if determine_if_poky_env(): # machine with poky environment - exportpath = d.getVar("TEST_EXPORT_DIR") if export_env else d.getVar("DEPLOY_DIR") - rpm_deploy_dir = d.getVar("DEPLOY_DIR_RPM") - arch = get_dest_folder(d.getVar("TUNE_FEATURES"), os.listdir(rpm_deploy_dir)) - arch_rpm_dir = os.path.join(rpm_deploy_dir, arch) - extracted_bin_dir = os.path.join(exportpath,"binaries", arch, "extracted_binaries") - packaged_bin_dir = os.path.join(exportpath,"binaries", arch, "packaged_binaries") - # creating necessary directory structure in case testing is done in poky env. - if export_env == "0": - if not os.path.exists(extracted_bin_dir): bb.utils.mkdirhier(extracted_bin_dir) - if not os.path.exists(packaged_bin_dir): bb.utils.mkdirhier(packaged_bin_dir) - - if param_list[3] == "native": - if export_env == "1": #this is a native package and we only need to copy it. no need for extraction - native_rpm_dir = os.path.join(rpm_deploy_dir, get_dest_folder("{} nativesdk".format(d.getVar("BUILD_SYS")), os.listdir(rpm_deploy_dir))) - native_rpm_file_list = [item for item in os.listdir(native_rpm_dir) if re.search("nativesdk-" + param_list[0] + "-([0-9]+\.*)", item)] - if not native_rpm_file_list: - bb.warn("Couldn't find any version of {} native package. Related tests will most probably fail.".format(param_list[0])) - return "" - for item in native_rpm_file_list:# will copy all versions of package. Used version will be selected on remote machine - bb.plain("Copying native package file: %s" % item) - sh.copy(os.path.join(rpm_deploy_dir, native_rpm_dir, item), os.path.join(d.getVar("TEST_EXPORT_DIR"), "binaries", "native")) - else: # nothing to do here; running tests under bitbake, so we asume native binaries are in sysroots dir. - if param_list[1] or param_list[4]: - bb.warn("Native binary %s %s%s. Running tests under bitbake environment. Version can't be checked except when the test itself does it" - " and binary can't be removed."%(param_list[0],"has assigned ver. " + param_list[1] if param_list[1] else "", - ", is marked for removal" if param_list[4] else "")) - else:# the package is target aka DUT intended and it is either required to be delivered in an extracted form or in a packaged version - target_rpm_file_list = [item for item in os.listdir(arch_rpm_dir) if re.search(param_list[0] + "-([0-9]+\.*)", item)] - if not target_rpm_file_list: - bb.warn("Couldn't find any version of target package %s. Please ensure it was built. " - "Related tests will probably fail." % param_list[0]) - return "" - if param_list[2] == "rpm": # binary should be deployed as rpm; (other, .deb, .ipk? ; in the near future) - for item in target_rpm_file_list: # copying all related rpm packages. "Intuition" reasons, someone may need other versions too. Deciding later on version - bb.plain("Copying target specific packaged file: %s" % item) - sh.copy(os.path.join(arch_rpm_dir, item), packaged_bin_dir) - return "copied" - else: # it is required to extract the binary - if param_list[1]: # the package is versioned - for item in target_rpm_file_list: - if re.match(".*-{}-.*\.rpm".format(param_list[1]), item): - destination = os.path.join(extracted_bin_dir,param_list[0], param_list[1]) - bb.utils.mkdirhier(destination) - extract_binary(os.path.join(arch_rpm_dir, item), destination) - break - else: - bb.warn("Couldn't find the desired version %s for target binary %s. Related test cases will probably fail." % (param_list[1], param_list[0])) - return "" - return "extracted" - else: # no version provided, just extract one binary - destination = os.path.join(extracted_bin_dir,param_list[0], - re.search(".*-([0-9]+\.[0-9]+)-.*rpm", target_rpm_file_list[0]).group(1)) - bb.utils.mkdirhier(destination) - extract_binary(os.path.join(arch_rpm_dir, target_rpm_file_list[0]), destination) - return "extracted" - else: # remote machine - binaries_path = os.getenv("bin_dir")# in order to know where the binaries are, bin_dir is set as env. variable - if param_list[3] == "native": #need to extract the native pkg here - native_rpm_dir = os.path.join(binaries_path, "native") - native_rpm_file_list = os.listdir(native_rpm_dir) - for item in native_rpm_file_list: - if param_list[1] and re.match("nativesdk-{}-{}-.*\.rpm".format(param_list[0], param_list[1]), item): # native package has version - extract_binary(os.path.join(native_rpm_dir, item)) - break - else:# just copy any related native binary - found_version = re.match("nativesdk-{}-([0-9]+\.[0-9]+)-".format(param_list[0]), item).group(1) - if found_version: - extract_binary(os.path.join(native_rpm_dir, item)) - else: - bb.warn("Couldn't find native package %s%s. Related test cases will be influenced." % - (param_list[0], " with version " + param_list[1] if param_list[1] else "")) - return - - else: # this is for target device - if param_list[2] == "rpm": - return "No need to extract, this is an .rpm file" - arch = get_dest_folder(d.getVar("TUNE_FEATURES"), os.listdir(binaries_path)) - extracted_bin_path = os.path.join(binaries_path, arch, "extracted_binaries") - extracted_bin_list = [item for item in os.listdir(extracted_bin_path)] - packaged_bin_path = os.path.join(binaries_path, arch, "packaged_binaries") - packaged_bin_file_list = os.listdir(packaged_bin_path) - # see if the package is already in the extracted ones; maybe it was deployed when exported the env. - if os.path.exists(os.path.join(extracted_bin_path, param_list[0], param_list[1] if param_list[1] else "")): - return "binary %s is already extracted" % param_list[0] - else: # we need to search for it in the packaged binaries directory. It may have been shipped after export - for item in packaged_bin_file_list: - if param_list[1]: - if re.match("%s-%s.*rpm" % (param_list[0], param_list[1]), item): # package with version - if not os.path.exists(os.path.join(extracted_bin_path, param_list[0],param_list[1])): - os.makedirs(os.path.join(extracted_bin_path, param_list[0], param_list[1])) - extract_binary(os.path.join(packaged_bin_path, item), os.path.join(extracted_bin_path, param_list[0],param_list[1])) - bb.plain("Using {} for {}".format(os.path.join(packaged_bin_path, item), param_list[0])) - break - else: - if re.match("%s-.*rpm" % param_list[0], item): - found_version = re.match(".*-([0-9]+\.[0-9]+)-", item).group(1) - if not os.path.exists(os.path.join(extracted_bin_path, param_list[0], found_version)): - os.makedirs(os.path.join(extracted_bin_path, param_list[0], found_version)) - bb.plain("Used ver. %s for %s" % (found_version, param_list[0])) - extract_binary(os.path.join(packaged_bin_path, item), os.path.join(extracted_bin_path, param_list[0], found_version)) - break - else: - bb.warn("Couldn't find target package %s%s. Please ensure it is available " - "in either of these directories: extracted_binaries or packaged_binaries. " - "Related tests will probably fail." % (param_list[0], " with version " + param_list[1] if param_list[1] else "")) - return - return "Binary %s extracted successfully." % param_list[0] - - -def files_to_copy(base_dir): - """ - Produces a list of files relative to the base dir path sent as param - :return: the list of relative path files - """ - files_list = [] - dir_list = [base_dir] - count = 1 - dir_count = 1 - while (dir_count == 1 or dir_count != count): - count = dir_count - for dir in dir_list: - for item in os.listdir(dir): - if os.path.isdir(os.path.join(dir, item)) and os.path.join(dir, item) not in dir_list: - dir_list.append(os.path.join(dir, item)) - dir_count = len(dir_list) - elif os.path.join(dir, item) not in files_list and os.path.isfile(os.path.join(dir, item)): - files_list.append(os.path.join(dir, item)) - return files_list - - -def send_bin_to_DUT(d,params): - from oeqa.oetest import oeRuntimeTest - param_list = params - cleanup_list = list() - bins_dir = os.path.join(d.getVar("TEST_EXPORT_DIR"), "binaries") if determine_if_poky_env() \ - else os.getenv("bin_dir") - arch = get_dest_folder(d.getVar("TUNE_FEATURES"), os.listdir(bins_dir)) - arch_rpms_dir = os.path.join(bins_dir, arch, "packaged_binaries") - extracted_bin_dir = os.path.join(bins_dir, arch, "extracted_binaries", param_list[0]) - - def send_extracted_binary(): - bin_local_dir = os.path.join(extracted_bin_dir, param_list[1] if param_list[1] else os.listdir(extracted_bin_dir)[0]) - for item in files_to_copy(bin_local_dir): - split_path = item.split(bin_local_dir)[1] - path_on_DUT = split_path if split_path[0] is "/" else "/" + split_path # create the path as on DUT; eg. /usr/bin/bin_file - (status, output) = oeRuntimeTest.tc.target.copy_to(item, path_on_DUT) - if status != 0: - bb.warn("Failed to copy %s binary file %s on the remote target: %s" % - (param_list[0], "ver. " + param_list[1] if param_list[1] else "", d.getVar("MACHINE"))) - return - if param_list[4] == "rm": - cleanup_list.append(path_on_DUT) - return cleanup_list - - def send_rpm(remote_path): # if it is not required to have an extracted binary, but to send an .rpm file - rpm_to_send = "" - for item in os.listdir(arch_rpms_dir): - if param_list[1] and re.match("%s-%s-.*rpm"%(param_list[0], param_list[1]), item): - rpm_to_send = item - break - elif re.match("%s-[0-9]+\.[0-9]+-.*rpm" % param_list[0], item): - rpm_to_send = item - break - else: - bb.warn("No rpm package found for %s %s in .rpm files dir %s. Skipping deployment." % - (param_list[0], "ver. " + param_list[1] if param_list[1] else "", rpms_file_dir) ) - return - (status, output) = oeRuntimeTest.tc.target.copy_to(os.path.join(arch_rpms_dir, rpm_to_send), remote_path) - if status != 0: - bb.warn("Failed to copy %s on the remote target: %s" %(param_list[0], d.getVar("MACHINE"))) - return - if param_list[4] == "rm": - cleanup_list.append(os.path.join(remote_path, rpm_to_send)) - return cleanup_list - - if param_list[2] == "rpm": # send an .rpm file - return send_rpm("/home/root") # rpms will be sent on home dir of remote machine - else: - return send_extracted_binary() - - -def rm_bin(removal_list): # need to know both if the binary is sent archived and the path where it is sent if archived - from oeqa.oetest import oeRuntimeTest - for item in removal_list: - (status,output) = oeRuntimeTest.tc.target.run("rm " + item) - if status != 0: - bb.warn("Failed to remove: %s. Please ensure connection with the target device is up and running and " - "you have the needed rights." % item) - From patchwork Sun Nov 15 08:48:20 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104208 Received: from mail-wr1-f47.google.com (mail-wr1-f47.google.com [209.85.221.47]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.4379.1794732558291589331 for ; Sun, 15 Nov 2026 00:49:18 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=hDl6cfsn; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.47, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f47.google.com with SMTP id ffacd0b85a97d-498f5fa5103so960284f8f.2 for ; Sun, 15 Nov 2026 00:49:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732556; x=1795337356; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=3oS7/UZLfkLqvDEUodlzuQQA4oMoTA9Wh9Y+MDqldu0=; b=hDl6cfsnbnNz0FdH4m3y7BBm8Y4zVtTUZa5idGHPLQFNwm4GUQ8JvLFBAs8/0Mdqu1 xzQzjQKqT0rMRkrLl11jIh7uvCpFadcrmYOh2L66nlnHkULzKTAIPxrrMREmKuqp/pka 5kROYAlJW82cPzx/pqVNXBMrBypvOKw8nivY8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732556; x=1795337356; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=3oS7/UZLfkLqvDEUodlzuQQA4oMoTA9Wh9Y+MDqldu0=; b=vZy2o8DZ5CRK4olXpskLbT0XkCFO989umrnhvKWXvFqf8m/4gXfpHlfBor5U8hQWK7 whKaU7YonleoAWZXZ4Go5LYoDzFcqrcv00VnMCEXQyK4zGOtlJi62Ip84HqPkJCZH6yX AW5ZbA6o56mKwHOluF8jGPe5BE8ayDJQD55jX88SnLchrSOfry1OYuZ34zcqKmnMRhyo 3hqv7+YnsKUPpH0zQ9ZbbElOakjiXhcnhn0lwIO4f+InuDwhwj6oEZJ3YjhDs+LYHfOf NR4nk75aj3ld4y60EDnOEpTMyfv8f1G8DdO2Mn/2yg6uL0S40JVGzdd1e3J6kVs1TCJu sObQ== X-Gm-Message-State: APuU4Z+KsMZMwmWiUaeU8QEpYbzyIwjawAPfMhy9HUS48hHjYZsOo+LU 6jsFbnXxeYdqkrRUFBkaQjdNtJpL1LqN7LUIBomYx1gsqpoSQGLe+uws6cGPyQ0XU9HhMB5AiVA 9p+L2/Co= X-Gm-Gg: AYBFou2+z+lS4WG856ugtsJ2gLwJgXa9nIvFup8DNWKIMa2lscNpVyXd/zqdL7Ibb+/ yI6xupbiBuK+LEcpgfy9Q1EQ0ke2qV6UBdyE3wTieduXJ6yqZssjnHVVfAEOsAld3V1iH415eGF MWxUurHcjRWzuqWODGKz3heK3I80GzeE8es0O+Uz431xyLcOavV2IM+eKTy0ForFZh8VF8OwBro +YCrjNa3SnltC6ChZ7ioRjTkdH7xqu0s6L8+OH+dqVe9JFo2yaAh+OH/onNYZHSMv3LGPK7xGxm 2klu82z9lQiStOS2f7DAP6W8f65dPtV1wVIxRkW9wtEUb7WTBM8dz31rgnqVcBn5WK5h25xCKm0 +kiglfg0qvwWTi5Hv+6ZnBFdTW1BxCZkhnlAkDjYt4Q4X7sBgJT5+8Dm4TpM3QFlbAROjChfxiV X0dfV1GHNr13Q+nhFCDGEbc6Y77qW/iYK2hkH//XVchhfIcZQp7atulA2fdAmBBCUnGbBwY0zY3 MQu1sASf1hWNrTI/qAMzZhQdFraH3l/fnXaoEgZFT/LcOg3tSVdOEtGSzRrbHFq+quiYbpRV7Mx anIC9AHiHHcT3vpN77h1MLoInIusJJt5j3zk2vHs76Yu7s3xHIIcZ40y1g== X-Received: by 2002:a05:6000:981:b0:48e:1f08:4f05 with SMTP id ffacd0b85a97d-49c72306696mr15489893f8f.33.1794732556376; Sun, 15 Nov 2026 00:49:16 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.13 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:15 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 17/41] oeqa/runexported.py: Remove file Date: Sun, 15 Nov 2026 08:48:20 +0000 Message-ID: <20261115084845.701136-17-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:22 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250248 testexport.bbclass uses scripts/oe-test to execute tests and this script hasn't been updated/used in years. Remove it as we don't need multiple ways to do things. Fix various comments to match. Signed-off-by: Richard Purdie --- meta/classes-recipe/testexport.bbclass | 2 +- meta/lib/oeqa/runexported.py | 153 ------------------- meta/lib/oeqa/selftest/cases/runtime_test.py | 4 +- 3 files changed, 2 insertions(+), 157 deletions(-) delete mode 100755 meta/lib/oeqa/runexported.py diff --git a/meta/classes-recipe/testexport.bbclass b/meta/classes-recipe/testexport.bbclass index adcc36c0622..b2b4a358c43 100644 --- a/meta/classes-recipe/testexport.bbclass +++ b/meta/classes-recipe/testexport.bbclass @@ -9,7 +9,7 @@ # - First build an image. i.e. core-image-sato # - Add IMAGE_CLASSES += "testexport" in local.conf # - Then bitbake core-image-sato -c testexport. That will generate the directory structure -# to execute the runtime tests using runexported.py. +# to execute the runtime tests using scripts/oe-test. # # For more information on TEST_SUITES check testimage class. diff --git a/meta/lib/oeqa/runexported.py b/meta/lib/oeqa/runexported.py deleted file mode 100755 index 982d8affa03..00000000000 --- a/meta/lib/oeqa/runexported.py +++ /dev/null @@ -1,153 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2013 Intel Corporation -# -# SPDX-License-Identifier: MIT -# - -# This script should be used outside of the build system to run image tests. -# It needs a json file as input as exported by the build. -# E.g for an already built image: -#- export the tests: -# TEST_EXPORT_ONLY = "1" -# TEST_TARGET = "simpleremote" -# TEST_TARGET_IP = "192.168.7.2" -# TEST_SERVER_IP = "192.168.7.1" -# bitbake core-image-sato -c testimage -# Setup your target, e.g for qemu: runqemu core-image-sato -# cd build/tmp/testimage/core-image-sato -# ./runexported.py testdata.json - -import sys -import os -import time -import argparse - -try: - import simplejson as json -except ImportError: - import json - -sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "oeqa"))) - -from oeqa.oetest import ExportTestContext -from oeqa.utils.commands import runCmd, updateEnv -from oeqa.utils.sshcontrol import SSHControl - -# this isn't pretty but we need a fake target object -# for running the tests externally as we don't care -# about deploy/start we only care about the connection methods (run, copy) -class FakeTarget: - def __init__(self, d): - self.connection = None - self.ip = None - self.server_ip = None - self.datetime = time.strftime('%Y%m%d%H%M%S',time.gmtime()) - self.testdir = d.getVar("TEST_LOG_DIR") - self.pn = d.getVar("PN") - - def exportStart(self): - self.sshlog = os.path.join(self.testdir, "ssh_target_log.%s" % self.datetime) - sshloglink = os.path.join(self.testdir, "ssh_target_log") - if os.path.lexists(sshloglink): - os.remove(sshloglink) - os.symlink(self.sshlog, sshloglink) - print("SSH log file: %s" % self.sshlog) - self.connection = SSHControl(self.ip, logfile=self.sshlog) - - def run(self, cmd, timeout=None): - return self.connection.run(cmd, timeout) - - def copy_to(self, localpath, remotepath): - return self.connection.copy_to(localpath, remotepath) - - def copy_from(self, remotepath, localpath): - return self.connection.copy_from(remotepath, localpath) - - -class MyDataDict(dict): - def getVar(self, key, unused = None): - return self.get(key, "") - -def main(): - - parser = argparse.ArgumentParser() - parser.add_argument("-t", "--target-ip", dest="ip", help="The IP address of the target machine. Use this to \ - overwrite the value determined from TEST_TARGET_IP at build time") - parser.add_argument("-s", "--server-ip", dest="server_ip", help="The IP address of this machine. Use this to \ - overwrite the value determined from TEST_SERVER_IP at build time.") - parser.add_argument("-d", "--deploy-dir", dest="deploy_dir", help="Full path to the package feeds, that this \ - the contents of what used to be DEPLOY_DIR on the build machine. If not specified it will use the value \ - specified in the json if that directory actually exists or it will error out.") - parser.add_argument("-l", "--log-dir", dest="log_dir", help="This sets the path for TEST_LOG_DIR. If not specified \ - the current dir is used. This is used for usually creating a ssh log file and a scp test file.") - parser.add_argument("-a", "--tag", dest="tag", help="Only run test with specified tag.") - parser.add_argument("json", help="The json file exported by the build system", default="testdata.json", nargs='?') - - args = parser.parse_args() - - with open(args.json, "r") as f: - loaded = json.load(f) - - if args.ip: - loaded["target"]["ip"] = args.ip - if args.server_ip: - loaded["target"]["server_ip"] = args.server_ip - - d = MyDataDict() - for key in loaded["d"].keys(): - d[key] = loaded["d"][key] - - if args.log_dir: - d["TEST_LOG_DIR"] = args.log_dir - else: - d["TEST_LOG_DIR"] = os.path.abspath(os.path.dirname(__file__)) - if args.deploy_dir: - d["DEPLOY_DIR"] = args.deploy_dir - else: - if not os.path.isdir(d["DEPLOY_DIR"]): - print("WARNING: The path to DEPLOY_DIR does not exist: %s" % d["DEPLOY_DIR"]) - - parsedArgs = {} - parsedArgs["tag"] = args.tag - - extract_sdk(d) - - target = FakeTarget(d) - for key in loaded["target"].keys(): - setattr(target, key, loaded["target"][key]) - - target.exportStart() - tc = ExportTestContext(d, target, True, parsedArgs) - tc.loadTests() - tc.runTests() - - return 0 - -def extract_sdk(d): - """ - Extract SDK if needed - """ - - export_dir = os.path.dirname(os.path.realpath(__file__)) - tools_dir = d.getVar("TEST_EXPORT_SDK_DIR") - tarball_name = "%s.sh" % d.getVar("TEST_EXPORT_SDK_NAME") - tarball_path = os.path.join(export_dir, tools_dir, tarball_name) - extract_path = os.path.join(export_dir, "sysroot") - if os.path.isfile(tarball_path): - print ("Found SDK tarball %s. Extracting..." % tarball_path) - result = runCmd("%s -y -d %s" % (tarball_path, extract_path)) - for f in os.listdir(extract_path): - if f.startswith("environment-setup"): - print("Setting up SDK environment...") - env_file = os.path.join(extract_path, f) - updateEnv(env_file) - -if __name__ == "__main__": - try: - ret = main() - except Exception: - ret = 1 - import traceback - traceback.print_exc() - sys.exit(ret) diff --git a/meta/lib/oeqa/selftest/cases/runtime_test.py b/meta/lib/oeqa/selftest/cases/runtime_test.py index 0e7ccf45856..f431f58c66e 100644 --- a/meta/lib/oeqa/selftest/cases/runtime_test.py +++ b/meta/lib/oeqa/selftest/cases/runtime_test.py @@ -20,8 +20,7 @@ class TestExport(OESelftestTestCase): """ Summary: Check basic testexport functionality with only ping test enabled. Expected: 1. testexport directory must be created. - 2. runexported.py must run without any error/exception. - 3. ping test must succeed. + 2. ping test must succeed. Product: oe-core Author: Mariano Lopez """ @@ -44,7 +43,6 @@ class TestExport(OESelftestTestCase): self.assertEqual(True, isdir, 'Failed to create testexport dir: %s' % testexport_dir) with runqemu('core-image-minimal') as qemu: - # Attempt to run runexported.py to perform ping test test_path = os.path.join(testexport_dir, "oe-test") data_file = os.path.join(testexport_dir, 'data', 'testdata.json') manifest = os.path.join(testexport_dir, 'data', 'manifest') From patchwork Sun Nov 15 08:48:21 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104209 Received: from mail-wm1-f42.google.com (mail-wm1-f42.google.com [209.85.128.42]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4329.1794732559692513403 for ; Sun, 15 Nov 2026 00:49:20 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=PAv5x6YH; spf=pass (domain: linuxfoundation.org, ip: 209.85.128.42, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wm1-f42.google.com with SMTP id 5b1f17b1804b1-4a214c5c4c0so26086535e9.3 for ; Sun, 15 Nov 2026 00:49:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732558; x=1795337358; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=My5iT8N5pR02Td9ANQ722itb/YNzTLUcGN2RvfV4XnM=; b=PAv5x6YHA/jTDttRSoz3uySbcKW8Nph6wR/SWG5W50SuuycnE5cHKRoGEFDx/bqMLH VEUZFTHw2Z5M75Yc/AGAn2tMI/fgWfFaOVDTs1guv0F2tYkZXthdPY8Ii0UqTtZID88s zVlWEMaeM2Dr8GchitnXMKftxe4fgJ+YcAb70= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732558; x=1795337358; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=My5iT8N5pR02Td9ANQ722itb/YNzTLUcGN2RvfV4XnM=; b=kOTpJwbvnu8kcDPvMXcyfB+UjBc+xYM3l2P9wt1LPFcBRo1v44qRqQcAuD98ytJTTl 6jF3PT435zW1DQiq8CJ0SbBmMi+omQ2tYniqoi4Pi4+gAS9DCDy9Q5R5oqGF45nxYh5e Kbxw2uaMISQscSo7vbz2yLSrAsmEHYwvhQigifWrCY2Ho+N+2Y0S6WcJbbW58btxUIor sz+z9e/93MArHx5aBC+yRkrudbAjWQTziNlWIGjxKC8NGVtpG7D35wImyqD4Wuc2tYvW 1MsyD+W3SZY2ysS9rHAL+G4s/Y1B17hAjFTbmStMsNyp+pcLOWBEL245e2mv9d56K6cW c0Rg== X-Gm-Message-State: APuU4Z/LM2s+19DT+GiLf3IQqLtp6UIw1M9KCLbWvsT9UUKD+m4PHr6K cOYaAOam3UUpFQdWVkGuzph+vtJVLq4G23QiFllDxO5zfB05GSDzGOxe5K8Xf/qOsM4RJUznp/8 KJTW+EV8= X-Gm-Gg: AYBFou0IGysEDhNNdtuQT3H310dnVvR9k+LeMuH+m9eGhJoTgMUMho1AePVNUMYDH5u g0slMzqZSFrie5TQh6qboqj62BAAZH3DSl9DtEPCu9YT08Bo6DOixrIOoIkZzXVmAQ7xc54gV+n THYlYjOfgDbENtIQmwVxTsmj403Lbw1Qjc4L9T7aInhorD0m2YoHgvURt9UMDYN7WjE0Y1VIUt3 lB75glknwgogDnv7LSlNyj+wbaMqa2E9a+gzMgOn+k6oUUPS027B6wKCWhEgglo27KFEMczv7mW Upn4OtC6kFwC9A25cThqdDVnro1Pxlcv3Kgzxd0mkxXQ13r+jd5XOicOnIGLGySsSfrXLpd347e ky/yfhkMR0iI0DeLQzXdJTekB6183NTg5TovfVlDV49NFsmzhc0OoAkMTOUi+y+2xcJ4RDfv0Aj z5fEhAnRQBnU3Le8GxZ5aAXZGUS2n7Yy7e2ml+ir1Led1bqGiN6lm/av0TAd/wFGRh1QAMpmzBa +5NcxdkzrJaPYjrRQ6qqPhfl3XLY/5cNcOOnSy149YGym2lH+dNmaFnN3iTZXAL47BHSyEyB2tk FgfTGfTp5uW9UFIPctvCXNdwKRlo99OwgkGUoACGoUqOL4/NbEDQVHbkpg== X-Received: by 2002:a05:600c:4e8c:b0:4bb:60ba:49e0 with SMTP id 5b1f17b1804b1-4bb60ba4a70mr83060365e9.26.1794732557604; Sun, 15 Nov 2026 00:49:17 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.16 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:16 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 18/41] oeqa/oetest.py: Remove Date: Sun, 15 Nov 2026 08:48:21 +0000 Message-ID: <20261115084845.701136-18-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:23 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250249 Nothing uses this any more, it is dead code. Drop it. Signed-off-by: Richard Purdie --- meta/lib/oeqa/oetest.py | 598 ---------------------------------------- 1 file changed, 598 deletions(-) delete mode 100644 meta/lib/oeqa/oetest.py diff --git a/meta/lib/oeqa/oetest.py b/meta/lib/oeqa/oetest.py deleted file mode 100644 index f5703ea9cd3..00000000000 --- a/meta/lib/oeqa/oetest.py +++ /dev/null @@ -1,598 +0,0 @@ -# -# Copyright (C) 2013 Intel Corporation -# -# SPDX-License-Identifier: MIT -# - -# Main unittest module used by testimage.bbclass -# This provides the oeRuntimeTest base class which is inherited by all tests in meta/lib/oeqa/runtime. - -# It also has some helper functions and it's responsible for actually starting the tests - -import os, re, sys -import unittest -import inspect -import subprocess -import signal -import shutil -import functools -try: - import bb -except ImportError: - pass -import logging - -import oeqa.runtime -# Exported test doesn't require sdkext -try: - import oeqa.sdkext -except ImportError: - pass -from oeqa.utils.decorators import LogResults, gettag - -logger = logging.getLogger("BitBake") - -def getVar(obj): - #extend form dict, if a variable didn't exists, need find it in testcase - class VarDict(dict): - def __getitem__(self, key): - return gettag(obj, key) - return VarDict() - -def checkTags(tc, tagexp): - return eval(tagexp, None, getVar(tc)) - -def filterByTagExp(testsuite, tagexp): - if not tagexp: - return testsuite - caseList = [] - for each in testsuite: - if not isinstance(each, unittest.BaseTestSuite): - if checkTags(each, tagexp): - caseList.append(each) - else: - caseList.append(filterByTagExp(each, tagexp)) - return testsuite.__class__(caseList) - -@LogResults -class oeTest(unittest.TestCase): - - longMessage = True - - @classmethod - def hasPackage(self, pkg): - """ - True if the full package name exists in the manifest, False otherwise. - """ - return pkg in oeTest.tc.pkgmanifest - - @classmethod - def hasPackageMatch(self, match): - """ - True if match exists in the manifest as a regular expression substring, - False otherwise. - """ - for s in oeTest.tc.pkgmanifest: - if re.match(match, s): - return True - return False - - @classmethod - def hasFeature(self,feature): - if feature in oeTest.tc.imagefeatures or \ - feature in oeTest.tc.distrofeatures: - return True - else: - return False - -class oeRuntimeTest(oeTest): - def __init__(self, methodName='runTest'): - self.target = oeRuntimeTest.tc.target - super().__init__(methodName) - - def setUp(self): - # Install packages in the DUT - self.tc.install_uninstall_packages(self.id()) - - # Check if test needs to run - if self.tc.sigterm: - self.fail("Got SIGTERM") - elif (type(self.target).__name__ == "QemuTarget"): - self.assertTrue(self.target.check(), msg = "Qemu not running?") - - self.setUpLocal() - - # a setup method before tests but after the class instantiation - def setUpLocal(self): - pass - - def tearDown(self): - # Uninstall packages in the DUT - self.tc.install_uninstall_packages(self.id(), False) - self.tearDownLocal() - - # Method to be run after tearDown and implemented by child classes - def tearDownLocal(self): - pass - -def getmodule(pos=2): - # stack returns a list of tuples containg frame information - # First element of the list the is current frame, caller is 1 - frameinfo = inspect.stack()[pos] - modname = inspect.getmodulename(frameinfo[1]) - #modname = inspect.getmodule(frameinfo[0]).__name__ - return modname - -def skipModule(reason, pos=2): - modname = getmodule(pos) - if modname not in oeTest.tc.testsrequired: - raise unittest.SkipTest("%s: %s" % (modname, reason)) - else: - raise Exception("\nTest %s wants to be skipped.\nReason is: %s" \ - "\nTest was required in TEST_SUITES, so either the condition for skipping is wrong" \ - "\nor the image really doesn't have the required feature/package when it should." % (modname, reason)) - -def skipModuleIf(cond, reason): - - if cond: - skipModule(reason, 3) - -def skipModuleUnless(cond, reason): - - if not cond: - skipModule(reason, 3) - -_buffer_logger = "" -def custom_verbose(msg, *args, **kwargs): - global _buffer_logger - if msg[-1] != "\n": - _buffer_logger += msg - else: - _buffer_logger += msg - try: - bb.plain(_buffer_logger.rstrip("\n"), *args, **kwargs) - except NameError: - logger.info(_buffer_logger.rstrip("\n"), *args, **kwargs) - _buffer_logger = "" - -class TestContext: - def __init__(self, d, exported=False): - self.d = d - - self.testsuites = self._get_test_suites() - - if exported: - path = [os.path.dirname(os.path.abspath(__file__))] - extrapath = "" - else: - path = d.getVar("BBPATH").split(':') - extrapath = "lib/oeqa" - - self.testslist = self._get_tests_list(path, extrapath) - self.testsrequired = self._get_test_suites_required() - - self.filesdir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "runtime/files") - self.corefilesdir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "files") - self.imagefeatures = d.getVar("IMAGE_FEATURES").split() - self.distrofeatures = d.getVar("DISTRO_FEATURES").split() - - # get testcase list from specified file - # if path is a relative path, then relative to build/conf/ - def _read_testlist(self, fpath, builddir): - if not os.path.isabs(fpath): - fpath = os.path.join(builddir, "conf", fpath) - if not os.path.exists(fpath): - bb.fatal("No such manifest file: ", fpath) - tcs = [] - for line in open(fpath).readlines(): - line = line.strip() - if line and not line.startswith("#"): - tcs.append(line) - return " ".join(tcs) - - # return test list by type also filter if TEST_SUITES is specified - def _get_tests_list(self, bbpath, extrapath): - testslist = [] - - type = self._get_test_namespace() - - # This relies on lib/ under each directory in BBPATH being added to sys.path - # (as done by default in base.bbclass) - for testname in self.testsuites: - if testname != "auto": - if testname.startswith("oeqa."): - testslist.append(testname) - continue - found = False - for p in bbpath: - if os.path.exists(os.path.join(p, extrapath, type, testname + ".py")): - testslist.append("oeqa." + type + "." + testname) - found = True - break - elif os.path.exists(os.path.join(p, extrapath, type, testname.split(".")[0] + ".py")): - testslist.append("oeqa." + type + "." + testname) - found = True - break - if not found: - bb.fatal('Test %s specified in TEST_SUITES could not be found in lib/oeqa/runtime under BBPATH' % testname) - - if "auto" in self.testsuites: - def add_auto_list(path): - files = sorted([f for f in os.listdir(path) if f.endswith('.py') and not f.startswith('_')]) - for f in files: - module = 'oeqa.' + type + '.' + f[:-3] - if module not in testslist: - testslist.append(module) - - for p in bbpath: - testpath = os.path.join(p, 'lib', 'oeqa', type) - bb.debug(2, 'Searching for tests in %s' % testpath) - if os.path.exists(testpath): - add_auto_list(testpath) - - return testslist - - def getTestModules(self): - """ - Returns all the test modules in the testlist. - """ - - import pkgutil - - modules = [] - for test in self.testslist: - if re.search(r"\w+\.\w+\.test_\S+", test): - test = '.'.join(t.split('.')[:3]) - module = pkgutil.get_loader(test) - modules.append(module) - - return modules - - def getModulefromID(self, test_id): - """ - Returns the test module based on a test id. - """ - - module_name = ".".join(test_id.split(".")[:3]) - modules = self.getTestModules() - for module in modules: - if module.name == module_name: - return module - - return None - - def getTests(self, test): - '''Return all individual tests executed when running the suite.''' - # Unfortunately unittest does not have an API for this, so we have - # to rely on implementation details. This only needs to work - # for TestSuite containing TestCase. - method = getattr(test, '_testMethodName', None) - if method: - # leaf case: a TestCase - yield test - else: - # Look into TestSuite. - tests = getattr(test, '_tests', []) - for t1 in tests: - for t2 in self.getTests(t1): - yield t2 - - def loadTests(self): - setattr(oeTest, "tc", self) - - testloader = unittest.TestLoader() - testloader.sortTestMethodsUsing = None - suites = [testloader.loadTestsFromName(name) for name in self.testslist] - suites = filterByTagExp(suites, getattr(self, "tagexp", None)) - - # Determine dependencies between suites by looking for @skipUnlessPassed - # method annotations. Suite A depends on suite B if any method in A - # depends on a method on B. - for suite in suites: - suite.dependencies = [] - suite.depth = 0 - for test in self.getTests(suite): - methodname = getattr(test, '_testMethodName', None) - if methodname: - method = getattr(test, methodname) - depends_on = getattr(method, '_depends_on', None) - if depends_on: - for dep_suite in suites: - if depends_on in [getattr(t, '_testMethodName', None) for t in self.getTests(dep_suite)]: - if dep_suite not in suite.dependencies and \ - dep_suite is not suite: - suite.dependencies.append(dep_suite) - break - else: - logger.warning("Test %s was declared as @skipUnlessPassed('%s') but that test is either not defined or not active. Will run the test anyway." % - (test, depends_on)) - - # Use brute-force topological sort to determine ordering. Sort by - # depth (higher depth = must run later), with original ordering to - # break ties. - def set_suite_depth(suite): - for dep in suite.dependencies: - new_depth = set_suite_depth(dep) + 1 - if new_depth > suite.depth: - suite.depth = new_depth - return suite.depth - - for index, suite in enumerate(suites): - set_suite_depth(suite) - suite.index = index - - def cmp(a, b): - return (a > b) - (a < b) - - def cmpfunc(a, b): - return cmp((a.depth, a.index), (b.depth, b.index)) - - suites.sort(key=functools.cmp_to_key(cmpfunc)) - - self.suite = testloader.suiteClass(suites) - - return self.suite - - def runTests(self): - logger.info("Test modules %s" % self.testslist) - if hasattr(self, "tagexp") and self.tagexp: - logger.info("Filter test cases by tags: %s" % self.tagexp) - logger.info("Found %s tests" % self.suite.countTestCases()) - runner = unittest.TextTestRunner(verbosity=2) - if 'bb' in sys.modules: - runner.stream.write = custom_verbose - - return runner.run(self.suite) - -class RuntimeTestContext(TestContext): - def __init__(self, d, target, exported=False): - super().__init__(d, exported) - - self.target = target - - self.pkgmanifest = {} - manifest = os.path.join(d.getVar("DEPLOY_DIR_IMAGE"), - d.getVar("IMAGE_LINK_NAME") + ".manifest") - nomanifest = d.getVar("IMAGE_NO_MANIFEST") - if nomanifest is None or nomanifest != "1": - try: - with open(manifest) as f: - for line in f: - (pkg, arch, version) = line.strip().split() - self.pkgmanifest[pkg] = (version, arch) - except OSError as e: - bb.fatal("No package manifest file found. Did you build the image?\n%s" % e) - - def _get_test_namespace(self): - return "runtime" - - def _get_test_suites(self): - testsuites = [] - - manifests = (self.d.getVar("TEST_SUITES_MANIFEST") or '').split() - if manifests: - for manifest in manifests: - testsuites.extend(self._read_testlist(manifest, - self.d.getVar("TOPDIR")).split()) - - else: - testsuites = self.d.getVar("TEST_SUITES").split() - - return testsuites - - def _get_test_suites_required(self): - return [t for t in self.d.getVar("TEST_SUITES").split() if t != "auto"] - - def extract_packages(self): - """ - Find packages that will be needed during runtime. - """ - - modules = self.getTestModules() - bbpaths = self.d.getVar("BBPATH").split(":") - - shutil.rmtree(self.d.getVar("TEST_EXTRACTED_DIR")) - shutil.rmtree(self.d.getVar("TEST_PACKAGED_DIR")) - for module in modules: - json_file = self._getJsonFile(module) - if json_file: - needed_packages = self._getNeededPackages(json_file) - self._perform_package_extraction(needed_packages) - - def _perform_package_extraction(self, needed_packages): - """ - Extract packages that will be needed during runtime. - """ - - import oe.path - - extracted_path = self.d.getVar("TEST_EXTRACTED_DIR") - packaged_path = self.d.getVar("TEST_PACKAGED_DIR") - - for key,value in needed_packages.items(): - packages = () - if isinstance(value, dict): - packages = (value, ) - elif isinstance(value, list): - packages = value - else: - bb.fatal("Failed to process needed packages for %s; " - "Value must be a dict or list" % key) - - for package in packages: - pkg = package["pkg"] - rm = package.get("rm", False) - extract = package.get("extract", True) - if extract: - dst_dir = os.path.join(extracted_path, pkg) - else: - dst_dir = os.path.join(packaged_path) - - # Extract package and copy it to TEST_EXTRACTED_DIR - pkg_dir = self._extract_in_tmpdir(pkg) - if extract: - - # Same package used for more than one test, - # don't need to extract again. - if os.path.exists(dst_dir): - continue - oe.path.copytree(pkg_dir, dst_dir) - shutil.rmtree(pkg_dir) - - # Copy package to TEST_PACKAGED_DIR - else: - self._copy_package(pkg) - - def _getJsonFile(self, module): - """ - Returns the path of the JSON file for a module, empty if doesn't exitst. - """ - - module_file = module.path - json_file = "%s.json" % module_file.rsplit(".", 1)[0] - if os.path.isfile(module_file) and os.path.isfile(json_file): - return json_file - else: - return "" - - def _getNeededPackages(self, json_file, test=None): - """ - Returns a dict with needed packages based on a JSON file. - - - If a test is specified it will return the dict just for that test. - """ - - import json - - needed_packages = {} - - with open(json_file) as f: - test_packages = json.load(f) - for key,value in test_packages.items(): - needed_packages[key] = value - - if test: - if test in needed_packages: - needed_packages = needed_packages[test] - else: - needed_packages = {} - - return needed_packages - - def _extract_in_tmpdir(self, pkg): - """" - Returns path to a temp directory where the package was - extracted without dependencies. - """ - - from oeqa.utils.package_manager import get_package_manager - - pkg_path = os.path.join(self.d.getVar("TEST_INSTALL_TMP_DIR"), pkg) - pm = get_package_manager(self.d, pkg_path) - extract_dir = pm.extract(pkg) - shutil.rmtree(pkg_path) - - return extract_dir - - def _copy_package(self, pkg): - """ - Copy the RPM, DEB or IPK package to dst_dir - """ - - from oeqa.utils.package_manager import get_package_manager - - pkg_path = os.path.join(self.d.getVar("TEST_INSTALL_TMP_DIR"), pkg) - dst_dir = self.d.getVar("TEST_PACKAGED_DIR") - pm = get_package_manager(self.d, pkg_path) - pkg_info = pm.package_info(pkg) - file_path = pkg_info[pkg]["filepath"] - shutil.copy2(file_path, dst_dir) - shutil.rmtree(pkg_path) - - def install_uninstall_packages(self, test_id, pkg_dir, install): - """ - Check if the test requires a package and Install/Uninstall it in the DUT - """ - - test = test_id.split(".")[4] - module = self.getModulefromID(test_id) - json = self._getJsonFile(module) - if json: - needed_packages = self._getNeededPackages(json, test) - if needed_packages: - self._install_uninstall_packages(needed_packages, pkg_dir, install) - - def _install_uninstall_packages(self, needed_packages, pkg_dir, install=True): - """ - Install/Uninstall packages in the DUT without using a package manager - """ - - if isinstance(needed_packages, dict): - packages = [needed_packages] - elif isinstance(needed_packages, list): - packages = needed_packages - - for package in packages: - pkg = package["pkg"] - rm = package.get("rm", False) - extract = package.get("extract", True) - src_dir = os.path.join(pkg_dir, pkg) - - # Install package - if install and extract: - self.target.connection.copy_dir_to(src_dir, "/") - - # Uninstall package - elif not install and rm: - self.target.connection.delete_dir_structure(src_dir, "/") - -class ImageTestContext(RuntimeTestContext): - def __init__(self, d, target, host_dumper): - super().__init__(d, target) - - self.tagexp = d.getVar("TEST_SUITES_TAGS") - - self.host_dumper = host_dumper - - self.sigterm = False - self.origsigtermhandler = signal.getsignal(signal.SIGTERM) - signal.signal(signal.SIGTERM, self._sigterm_exception) - - def _sigterm_exception(self, signum, stackframe): - bb.warn("TestImage received SIGTERM, shutting down...") - self.sigterm = True - self.target.stop() - - def install_uninstall_packages(self, test_id, install=True): - """ - Check if the test requires a package and Install/Uninstall it in the DUT - """ - - pkg_dir = self.d.getVar("TEST_EXTRACTED_DIR") - super().install_uninstall_packages(test_id, pkg_dir, install) - -class ExportTestContext(RuntimeTestContext): - def __init__(self, d, target, exported=False, parsedArgs={}): - """ - This class is used when exporting tests and when are executed outside OE environment. - - parsedArgs can contain the following: - - tag: Filter test by tag. - """ - super().__init__(d, target, exported) - - tag = parsedArgs.get("tag", None) - self.tagexp = tag if tag is not None else d.getVar("TEST_SUITES_TAGS") - - self.sigterm = None - - def install_uninstall_packages(self, test_id, install=True): - """ - Check if the test requires a package and Install/Uninstall it in the DUT - """ - - export_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) - extracted_dir = self.d.getVar("TEST_EXPORT_EXTRACTED_DIR") - pkg_dir = os.path.join(export_dir, extracted_dir) - super().install_uninstall_packages(test_id, pkg_dir, install) From patchwork Sun Nov 15 08:48:22 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104204 Received: from mail-wr1-f49.google.com (mail-wr1-f49.google.com [209.85.221.49]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.4380.1794732560518580472 for ; Sun, 15 Nov 2026 00:49:20 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=RmON/p++; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.49, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f49.google.com with SMTP id ffacd0b85a97d-48e10a70540so1244482f8f.1 for ; Sun, 15 Nov 2026 00:49:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732559; x=1795337359; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=8O+zb38zKK5Dl+6wiJKC9xhYM9FHgAoprI0Ji5lTTYo=; b=RmON/p++EgDfZBl10cJKTx7ACCAYXVBYcXQqbnzgapdsorE3V/WKSyDh9tTcsT8CRN 9Eh3s7QbOgW3nA3BWmSdKWqkMuKwWvulDtsyPcJPQmNwh8Ux4CgQ+9RSLZY9iPU6MoNh ytKLOYAG/yT1SZmzjTXx5bsBlmlJ1iiO0ewB4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732559; x=1795337359; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=8O+zb38zKK5Dl+6wiJKC9xhYM9FHgAoprI0Ji5lTTYo=; b=MOUoFilaiw58k9221/TZk9w/++gF+Q5j1d+jEw6UtysLUcxwgRkM9QGHcbxO38FHgq Ct6Ps8E6kLYCvuXGBFQEIfDgq5BgMlaiYhZ4YrtSTYYX0bGcyl+StIMspmAi0xI9C4Z4 JzVm3AUJ6lC6XFsLTdPXpXD3+ZB6xkd6lH184PbLkeORTmUoBy6q2pQUKAn2spJ5WU6Z lTklPsn9I/1bov9EY38+/nfC86Rbg4T+swd0pmu3GijgETHSuVxL5/tnIDg0W7UGCFSn NSS+OYVHt16vUzA6vIdHvfxHWjSoH3WdWyAWNj0NmvNr7i3LD8MkHu8r8zHvwiMiHGy5 C/xg== X-Gm-Message-State: APuU4Z9BedJlWJDXMOeij0ru0kh3wo0pvb8MPDC9V9PN3XOVKYPjMLlk TrJlHIE2cY1wLcf7pikanv+er1e3qNpV9P2DBrXi2bD/5l9VFhwLBaBEHhaHkp1lK+1jX9fHvl3 v9Se/0kk= X-Gm-Gg: AYBFou16yoTEdxPr7jI62I01NqCy7MIcfkPBq2d+qaUQvNoe9POfA8XWONVzviSkTx/ P7sCxF4+CNxNxXkqu4gL7/e6ebsQO8/cMOaqyHIOSDetAxxvfG+FfLWsFklfDiXyivEt/AMIKTk mZWjTztN098ES6AEfL5znr0Izu5KD2XOqmD/FI3XNNThPROE+wFMFDtCKbWw3SGBLkfTiNW7hq9 4szk2IUnMMAIA1BSaYAkmwRVe7x9/9HPc29E05C91TCpAhK+MHuR2tWHvKK7oSVoJMlxUs3a9DC HRDztWuAu19fS+3cQZ25FuSB7zpRXqj0GYc4a2c0LWEPC8Hl75cIxOajvTztS4uEatLg9tt43cs nNUBnXzcCjC6HLh2i8HOxLuznigz4qvPKoj2OqPSpzj/JRAw4LvCuUpxy/5injC3CH1++Ab8lfF OslfT5kwq5GBpd4wYyz/zbVLNePY+uLdPSoem6WLARO1nnhliaCZeyoFzwyCCpaxvLVdLfJ0bKZ ITCw4bbt7fVbcvkcEhzzrx3Ze3pAz6WyvCqK3ze75EAqq0Svyo8csTOmwcxNAcYlTQUE08TUEb8 CJa5lAkuYw9CRRlQUJEE3KHx/uzfbt0awaAH/DmWXLacMkYzPiEI9vvn1Q== X-Received: by 2002:a05:6000:22c2:b0:48d:ecba:3cf8 with SMTP id ffacd0b85a97d-49c741b1331mr17282800f8f.43.1794732558679; Sun, 15 Nov 2026 00:49:18 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.17 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:18 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 19/41] oeqa/lib/utils/decorators.py: Remove Date: Sun, 15 Nov 2026 08:48:22 +0000 Message-ID: <20261115084845.701136-19-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:22 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250250 This was only used by oetest.py which has been removed. Drop it. It was replaced by core/decorator/. Signed-off-by: Richard Purdie --- meta/lib/oeqa/utils/decorators.py | 212 ------------------------------ 1 file changed, 212 deletions(-) delete mode 100644 meta/lib/oeqa/utils/decorators.py diff --git a/meta/lib/oeqa/utils/decorators.py b/meta/lib/oeqa/utils/decorators.py deleted file mode 100644 index c45d5f4512c..00000000000 --- a/meta/lib/oeqa/utils/decorators.py +++ /dev/null @@ -1,212 +0,0 @@ -# -# Copyright (C) 2013 Intel Corporation -# -# SPDX-License-Identifier: MIT -# - -# Some custom decorators that can be used by unittests -# Most useful is skipUnlessPassed which can be used for -# creating dependecies between two test methods. - -import os -import logging -import sys -import unittest -import threading -import signal -from functools import wraps - -class testcase: - def __init__(self, test_case): - self.test_case = test_case - - def __call__(self, func): - @wraps(func) - def wrapped_f(*args, **kwargs): - return func(*args, **kwargs) - wrapped_f.test_case = self.test_case - wrapped_f.__name__ = func.__name__ - return wrapped_f - -class NoParsingFilter(logging.Filter): - def filter(self, record): - return record.levelno == 100 - -import inspect - -def LogResults(original_class): - orig_method = original_class.run - - from time import strftime, gmtime - caller = os.path.basename(sys.argv[0]) - timestamp = strftime('%Y%m%d%H%M%S',gmtime()) - logfile = os.path.join(os.getcwd(),'results-'+caller+'.'+timestamp+'.log') - linkfile = os.path.join(os.getcwd(),'results-'+caller+'.log') - - def get_class_that_defined_method(meth): - if inspect.ismethod(meth): - for cls in inspect.getmro(meth.__self__.__class__): - if cls.__dict__.get(meth.__name__) is meth: - return cls - meth = meth.__func__ # fallback to __qualname__ parsing - if inspect.isfunction(meth): - cls = getattr(inspect.getmodule(meth), - meth.__qualname__.split('.', 1)[0].rsplit('.', 1)[0]) - if isinstance(cls, type): - return cls - return None - - #rewrite the run method of unittest.TestCase to add testcase logging - def run(self, result, *args, **kws): - orig_method(self, result, *args, **kws) - passed = True - testMethod = getattr(self, self._testMethodName) - #if test case is decorated then use it's number, else use it's name - try: - test_case = testMethod.test_case - except AttributeError: - test_case = self._testMethodName - - class_name = str(get_class_that_defined_method(testMethod)).split("'")[1] - - #create custom logging level for filtering. - custom_log_level = 100 - logging.addLevelName(custom_log_level, 'RESULTS') - - def results(self, message, *args, **kws): - if self.isEnabledFor(custom_log_level): - self.log(custom_log_level, message, *args, **kws) - logging.Logger.results = results - - logging.basicConfig(filename=logfile, - filemode='w', - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', - datefmt='%H:%M:%S', - level=custom_log_level) - for handler in logging.root.handlers: - handler.addFilter(NoParsingFilter()) - local_log = logging.getLogger(caller) - - #check status of tests and record it - - tcid = self.id() - for (name, msg) in result.errors: - if tcid == name.id(): - local_log.results("Testcase "+str(test_case)+": ERROR") - local_log.results("Testcase "+str(test_case)+":\n"+msg) - passed = False - for (name, msg) in result.failures: - if tcid == name.id(): - local_log.results("Testcase "+str(test_case)+": FAILED") - local_log.results("Testcase "+str(test_case)+":\n"+msg) - passed = False - for (name, msg) in result.skipped: - if tcid == name.id(): - local_log.results("Testcase "+str(test_case)+": SKIPPED") - passed = False - if passed: - local_log.results("Testcase "+str(test_case)+": PASSED") - - # XXX: In order to avoid race condition when test if exists the linkfile - # use bb.utils.lock, the best solution is to create a unique name for the - # link file. - try: - import bb - has_bb = True - lockfilename = linkfile + '.lock' - except ImportError: - has_bb = False - - if has_bb: - lf = bb.utils.lockfile(lockfilename, block=True) - # Create symlink to the current log - if os.path.lexists(linkfile): - os.remove(linkfile) - os.symlink(logfile, linkfile) - if has_bb: - bb.utils.unlockfile(lf) - - original_class.run = run - - return original_class - -class TimeOut(BaseException): - pass - -def timeout(seconds): - def decorator(fn): - if hasattr(signal, 'alarm'): - @wraps(fn) - def wrapped_f(*args, **kw): - current_frame = sys._getframe() - def raiseTimeOut(signal, frame): - if frame is not current_frame: - raise TimeOut('%s seconds' % seconds) - prev_handler = signal.signal(signal.SIGALRM, raiseTimeOut) - try: - signal.alarm(seconds) - return fn(*args, **kw) - finally: - signal.alarm(0) - signal.signal(signal.SIGALRM, prev_handler) - return wrapped_f - else: - return fn - return decorator - -__tag_prefix = "tag__" -def tag(*args, **kwargs): - """Decorator that adds attributes to classes or functions - for use with the Attribute (-a) plugin. - """ - def wrap_ob(ob): - for name in args: - setattr(ob, __tag_prefix + name, True) - for name, value in kwargs.items(): - setattr(ob, __tag_prefix + name, value) - return ob - return wrap_ob - -def gettag(obj, key, default=None): - key = __tag_prefix + key - if not isinstance(obj, unittest.TestCase): - return getattr(obj, key, default) - tc_method = getattr(obj, obj._testMethodName) - ret = getattr(tc_method, key, getattr(obj, key, default)) - return ret - -def getAllTags(obj): - def __gettags(o): - r = {k[len(__tag_prefix):]:getattr(o,k) for k in dir(o) if k.startswith(__tag_prefix)} - return r - if not isinstance(obj, unittest.TestCase): - return __gettags(obj) - tc_method = getattr(obj, obj._testMethodName) - ret = __gettags(obj) - ret.update(__gettags(tc_method)) - return ret - -def timeout_handler(seconds): - def decorator(fn): - if hasattr(signal, 'alarm'): - @wraps(fn) - def wrapped_f(self, *args, **kw): - current_frame = sys._getframe() - def raiseTimeOut(signal, frame): - if frame is not current_frame: - try: - self.target.restart() - raise TimeOut('%s seconds' % seconds) - except: - raise TimeOut('%s seconds' % seconds) - prev_handler = signal.signal(signal.SIGALRM, raiseTimeOut) - try: - signal.alarm(seconds) - return fn(self, *args, **kw) - finally: - signal.alarm(0) - signal.signal(signal.SIGALRM, prev_handler) - return wrapped_f - else: - return fn - return decorator From patchwork Sun Nov 15 08:48:23 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104205 Received: from mail-wr1-f46.google.com (mail-wr1-f46.google.com [209.85.221.46]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.4381.1794732561580860825 for ; Sun, 15 Nov 2026 00:49:21 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=LXfCO2WQ; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.46, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f46.google.com with SMTP id ffacd0b85a97d-491f34b4e0fso935923f8f.2 for ; Sun, 15 Nov 2026 00:49:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732560; x=1795337360; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=hnTf5gsiNkhySTDX7hzhuZoxS9jhuH1OtoOVVJgWxeI=; b=LXfCO2WQMTq/P2S2thMaytCac0vAkRFVXdzDIwTY+mznyv0rUmg0mzli2PhwNb9y0/ FV5boMeggsWv8PzIAQoe39xA94p53fXS1y77Q8AQplC2YcPJlaQDEcRtTksvoGa2EPUu MdnhyvGulhsI8hhAJMhWFNuW5dbtwCbxZAYkI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732560; x=1795337360; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=hnTf5gsiNkhySTDX7hzhuZoxS9jhuH1OtoOVVJgWxeI=; b=p89XsMKBVMtAICk1A8DTyv9FHZy+xPmrQ1p1Q9jbr8FFOssu9oB0VgulDxxMHG7uvO RFcvURHJBNXmoVz8G6dwbmocuUE/ybZ1hyGhuGmjSqQ0HDvmSLtlnZvqCFfEwbWUMNWl Qm3QY/fT0Tme4ED6Zb4eTtiWVBvR/3PFHoRPG7JO11vIWZv9+GHI1WEomDC3shBBTri2 r3+4rVjhn88lgdu9EYMbk2dS1eLSuDxuX5GgeFd9cYB0X9BTxQvqO8ilmhLy+Vq3fCle zMu0imjrtOE34m/sGR6wh5OqbqioJFPXdn/NdS/013ivnfHfijxvFbJpcqOjDI2dkIzp 8t7Q== X-Gm-Message-State: APuU4Z9hcGhPoC7jkKOVhYmX5S1BTdd6gkkokFu8MtSB/7m0ILdNai+s 0gzlBFNPy8hGaEgppHq6KAIW/NPWNq0HxI/6xXl+MG/GqR55aYCzGP5bAbmsZff0cpwNlrxwd5d j4bBfiJ8= X-Gm-Gg: AYBFou2sTYCjCFE8tBM4Y5DuGef/CM3aZdP2VH+MZVBBXAprIEcennOwstYRvY0zdGN xxGxR/q1YYzVt1Z0Y14CvthbKrZhSm1+mzPvuUjMHGlESXMC7ONCWAHgJfhVE5hsxg9qoWGpe58 5dlXJ+ofo9+oTSFWED7MAqHSYoVidq4JLBQ9o6MY7nXx2wYQo3CoQaC5Bv/3b2+AUMGhjj1xdyH pcEfoVZWHK8aJvmlk/WsDsaxpSfktfaMDHDUtBsl0eUL4i/7DAQVEi8hWUWvzmD+gT28dYz3WX0 tbH58Q/XeIYOp3kcxnkMZnRAl2eN34jXbbj4C4lu/yoModUQBZ7lCIClBxcorbnqEqWO3SlTpkp 8lhyafEoxrGSKKNtND6yOv1lrb49zGQyi8sqN5MnCs5yn601Of7WG8sAji/cXN/wYXDa5uvVWAI Jiu57JNTiSVa2W8CjLyYn18JmBCuLxe3RAzfmVsZxCC5vO7Z3Ahc+bvEGRahVAy/V6UAlQSpki0 9Ux8S9lAXMbudpiVZgYeyZkp4DzKib9l0EthQNKgLupk7WXZBSEJHNv+gk/9BhCyng0MOsR1eVY bVoKyS8JdOqBSFCeEBaZVGoMkvsaEmDtjFx004qyOH9TR0hzStfsp6AWsQ== X-Received: by 2002:a05:6000:2dc5:b0:48d:e5c9:39a4 with SMTP id ffacd0b85a97d-49c73ce4e17mr16379558f8f.33.1794732559784; Sun, 15 Nov 2026 00:49:19 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.18 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:19 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 20/41] oeqa/targetcontrol: Drop SimpleRemoteTarget Date: Sun, 15 Nov 2026 08:48:23 +0000 Message-ID: <20261115084845.701136-20-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:22 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250251 This code is unused. The "simpleremote" type connects directly over ssh and doesn't need this code so we can remove it as obsolete. Signed-off-by: Richard Purdie --- meta/lib/oeqa/targetcontrol.py | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/meta/lib/oeqa/targetcontrol.py b/meta/lib/oeqa/targetcontrol.py index 283290cd227..233c9c40c5a 100644 --- a/meta/lib/oeqa/targetcontrol.py +++ b/meta/lib/oeqa/targetcontrol.py @@ -223,35 +223,3 @@ class QemuTarget(BaseTarget): def run_serial(self, command, timeout=60): return self.runner.run_serial(command, timeout=timeout) - - -class SimpleRemoteTarget(BaseTarget): - - def __init__(self, d): - super().__init__(d) - addr = d.getVar("TEST_TARGET_IP") or bb.fatal('Please set TEST_TARGET_IP with the IP address of the machine you want to run the tests on.') - self.ip = addr.split(":")[0] - try: - self.port = addr.split(":")[1] - except IndexError: - self.port = None - self.logger.info("Target IP: %s" % self.ip) - self.server_ip = d.getVar("TEST_SERVER_IP") - if not self.server_ip: - try: - self.server_ip = subprocess.check_output(['ip', 'route', 'get', self.ip ]).split("\n")[0].split()[-1] - except Exception as e: - bb.fatal("Failed to determine the host IP address (alternatively you can set TEST_SERVER_IP with the IP address of this machine): %s" % e) - self.logger.info("Server IP: %s" % self.server_ip) - - def deploy(self): - super().deploy() - - def start(self, params=None, ssh=True, extra_bootparams=None): - if ssh: - self.connection = SSHControl(self.ip, logfile=self.sshlog, port=self.port) - - def stop(self): - self.connection = None - self.ip = None - self.server_ip = None From patchwork Sun Nov 15 08:48:24 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104210 Received: from mail-wr1-f47.google.com (mail-wr1-f47.google.com [209.85.221.47]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4330.1794732563917779030 for ; Sun, 15 Nov 2026 00:49:24 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=V2VKZLyV; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.47, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f47.google.com with SMTP id ffacd0b85a97d-48e09aa5264so1076594f8f.2 for ; Sun, 15 Nov 2026 00:49:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732562; x=1795337362; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=B/0tz25vN1/Ofwx0U7+mK/59nh+OfmPdP6QWpm3Z0gA=; b=V2VKZLyVWgXW2azz793PyNc8q/8D/vd0Fq1EIMGHC/P0CJJgJizcajjLKUlgdTZIAL 2s2hzqg8onBS8jQQABzpMzN5kBFxGkufbYILaaP17QZ+SU7joT5arUP1UdTAYgD38G2O 4WoIt84v7tMDdspa2TlZm7qZWnuSVp3zwpmkw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732562; x=1795337362; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=B/0tz25vN1/Ofwx0U7+mK/59nh+OfmPdP6QWpm3Z0gA=; b=K/cETeZfm89aV8psOnZzf2rBoPeti8yyEm1YQ86pF/QWD22rqdsP8RDOyOf7S7aEYi U4NLv62boaT1KUVtnp8QNtEd7uiZYxgYMuRDVEbleozg2yeuesdb7ot+k9x8rQdV07Y2 KqWvP3M3cR52kTX0Fz1yl1P6XUNc6FZsgl1Tj6bId9GtYb5mKLRRCfjoPCUkkjnMxNbt lPJOBTqX1WobGHcMxaQ6SI8YA0PDHzcR0o1Vteh32x8/HF8HbjDt8ODTAJeSh8+ZhTMA f3u+6v+S47ZDIr5KwoygvZwAyA7oGA5PeSsaYLPPFCUPEjGlDENVD/cbHee9EXEg5WyB b1hQ== X-Gm-Message-State: APuU4Z+M5HQpalO9nC7WL/ssxAEPgxJ1PudznHcBwosOuGRPZ3r7716j ys/S/uovvJNoqtQ+wpNYZixlpBJaEFZZ19UiL+bVC0w1fv12shgC6WfxQznizQITMNNNGAygAjW RF3y8Gu0= X-Gm-Gg: AYBFou0IwwArSu0rqSBzKnJCDyT8zF3Fu145WBgF1Uul80ApTKcfphgaMKdB1sn5B4Y rULhe61Jb47sAe0/Wuom57yIGuU4rnCVwWn19hAsrfikC8E0VJZIMCBIDvzcmQRkG4oOjU6EqRC 5T9XKwqcnKJyf6dvieZ7aFzKe6T/V2Sq8QF2sIgte9kc6YN6Tzk5Pvs9a+nE3h+ESrZBgLhgy/l A3sb3VqYGMqOJf3WmSHcmbc2X7lsM9xcU10hpgIgulnvStFGHetOTXiCq2OvX406e5yla9ruL6C AZ9ZhgJ2r0T6m26P5VMNuz6JlFCyL+IK0Gwu3uZYbI5GwfvxkEDdsZYVgoGbJzOPwok9E3W0VTb yOHbXnkD8ciUsIjSB4XgCDTJJhDdMw4Ok7rAR0gqKFdMaTZHOoILuTWII6/Iz4cp22DOQ2vFsdi FoTWog/Adv3MPdoZhwDUvyoIl4DyomYivWDdXFda8udLwxuA70x4l5ZX5EzShW0Mzz0Wb6Ok+xZ L8Lqd1gASwrs79kqW5NdCzvJFcuRDYKcsXFxaUXxymew5jf7GBATLLlEBpi1tzVV9t+BcuhWxIF tNANRNYAvahXX++BiVK9Lg31wKZ33Oo1LRLr1B8wbF/mFk3nRrdpdWfq+4Z3DFYTtbDr13OiCSO G3i4= X-Received: by 2002:adf:f14b:0:b0:492:dddc:64c3 with SMTP id ffacd0b85a97d-49c742a6580mr12403489f8f.41.1794732562188; Sun, 15 Nov 2026 00:49:22 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.19 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:20 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 21/41] oeqa/core/target/ssh: Fix TimeoutExpired reference Date: Sun, 15 Nov 2026 08:48:24 +0000 Message-ID: <20261115084845.701136-21-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:33 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250252 TimeoutExpired was never imported so if the ssh process failed to exit after 5 seconds, the cleanup code raised a NameError instead of killing the process. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/core/target/ssh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/lib/oeqa/core/target/ssh.py b/meta/lib/oeqa/core/target/ssh.py index e380fd84854..03e99e68234 100644 --- a/meta/lib/oeqa/core/target/ssh.py +++ b/meta/lib/oeqa/core/target/ssh.py @@ -296,7 +296,7 @@ def SSHCall(command, logger, timeout=None, raw=False, **opts): if process.returncode is None: try: process.wait(timeout=5) - except TimeoutExpired: + except subprocess.TimeoutExpired: try: process.kill() except OSError: From patchwork Sun Nov 15 08:48:25 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104212 Received: from mail-wr1-f51.google.com (mail-wr1-f51.google.com [209.85.221.51]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4332.1794732566160302263 for ; Sun, 15 Nov 2026 00:49:26 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=N11kLkQv; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.51, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f51.google.com with SMTP id ffacd0b85a97d-490f38e9688so1608419f8f.0 for ; Sun, 15 Nov 2026 00:49:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732564; x=1795337364; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=cBZfcS7+NArJMXMIy8g0RLfH9/yRbnVQNm+NJiDfKdY=; b=N11kLkQvxytPoUsPY5I/AOulkvslB6bWgck/8VMInsRsKVl73QTajH41QDcbQISXWQ bIrCsbKDfoLMArK+qmhcid2rcEwn94wnfqj2TXY5moqcvLnUi/l+iiZsOIZmiKb+zCrs ywDlQ18m24UKPVluut6ULU44X7cXrLi4ugPpI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732564; x=1795337364; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=cBZfcS7+NArJMXMIy8g0RLfH9/yRbnVQNm+NJiDfKdY=; b=rlYbKZJ5skb/GKIZsvw1dtj37j7WyZVV0MRuFHJjRdIwrYr74Bx6tl7a2u6Fv6AUar 8hh2eOK+IXRgwnBgCN46DKfCL14yiQGXLn65TeH/EGC3TjJ0EsZON+MUMqkO2AqgHfMt XH2/O28lkKf3JVWSkhsvXYDtcJ9Hk9pLIwcbXAW7hSzJMcfRhcsLEAI9p41weAJvtw9h xkn4O3RA+ZBBAVqB+5KWRjqNNfBzr3/p1grIHNMfqSHIShbj8gmJALQ3Ey9ph7WvGD5v /FodXlmD8MVjtygzDKJ3qHTY5bzdU/n7olBdKSPrVeqOl2Mst0yMAeaJbM0zorxn5ns7 URGQ== X-Gm-Message-State: APuU4Z/h8jsxwDANNIt/2D8HUvcTxWlps6Aeu/1OwX0r81FAGYDWLCol ergq/ptbnxekXwv+yJDBWbndKoJFB9R/E7GYfvs1UMfPjdaNDt3+RAKDJ8111Wz2DEakWMdc716 Hbqm+uNY= X-Gm-Gg: AYBFou2rqM9c9hxt3NO6vmZ0v91R5NGnuKI1pjalHIVKL85yQLFZaAL9e1CXBAuFipK hDQfFcTYKInyEGJ3qQ6JZIQ4hkBDxEKzhN+cHo3OkS5gDrYZt13R5OwBJWbXexn5BP6dk7ksOPH UHOXQt+LdVvLvylEC7gu/xAx/YN4Nl+SUY1yjP5xxehIJAVI1n4tmt9Io1r638awDK/afx32n/M t2q+GJBe3kKSxTzcWX1gfyTMFqU6T+3rrXLhZr7/bduU8+N4fDgek7+9MTUV2HkWaTpbia9Q5kM FKmGwrzQ+23ofPjnITbdGbyI+EX10tQegXbEwqGZ+vkeJsENiD3mVWZv69DK0mQR63VYNXC3IHk hJm/0IsBUL926ipAuGw8zC29LRWTnY2UVrB45Dvi2h5rgoSpdiARcav3SolxEfKWwPLfd3qve6b AOaT5E5jmhqHfJaJyeDhINtus98hLfjGU9h3whzFSJoKmrwXZroIn8ng4yNhkm8NLW2V0eO1Lft ef1SFQwTnHmdQariCdpgRVlHkMX2j4qm6qU8rK9o2cGCimrplrWytzo02fyDCsJPU5PRTN2t6+D k38MXzTwcBg1qog1XszU4g1Z/18+Z707Nn/jgSf3AkCc7SPlX0j3tMPaoQ== X-Received: by 2002:a05:6000:383:b0:48e:d40:a87c with SMTP id ffacd0b85a97d-49b023a7e61mr24815184f8f.16.1794732564315; Sun, 15 Nov 2026 00:49:24 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.22 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:22 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 22/41] oeqa/runtime/ltp: Share a single base class and fix tearDownClass failures Date: Sun, 15 Nov 2026 08:48:25 +0000 Message-ID: <20261115084845.701136-22-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:33 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250253 ltp.py, ltp_stress.py and ltp_compliance.py each carried a copy of the same setup/teardown base class, differing only in the log directory and result names. Move it to oeqa/runtime/utils/ltp.py and set the names as class attributes. The teardown called cls.fail() from a classmethod, which passes the message as self and raises "AttributeError: 'str' object has no attribute 'failureException'" instead of reporting the failed LTP groups. Raise cls.failureException directly. Also import os explicitly rather than relying on it being available as a builtin. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/runtime/cases/ltp.py | 47 ++------------- meta/lib/oeqa/runtime/cases/ltp_compliance.py | 49 ++------------- meta/lib/oeqa/runtime/cases/ltp_stress.py | 50 ++-------------- meta/lib/oeqa/runtime/utils/ltp.py | 59 +++++++++++++++++++ 4 files changed, 73 insertions(+), 132 deletions(-) create mode 100644 meta/lib/oeqa/runtime/utils/ltp.py diff --git a/meta/lib/oeqa/runtime/cases/ltp.py b/meta/lib/oeqa/runtime/cases/ltp.py index b855e76907f..4a7400cbc15 100644 --- a/meta/lib/oeqa/runtime/cases/ltp.py +++ b/meta/lib/oeqa/runtime/cases/ltp.py @@ -5,57 +5,18 @@ # SPDX-License-Identifier: GPL-2.0-only # +import os import time -import datetime import pprint -from oeqa.runtime.case import OERuntimeTestCase +from oeqa.runtime.utils.ltp import LtpTestBase from oeqa.core.decorator.depends import OETestDepends from oeqa.runtime.decorator.package import OEHasPackage from oeqa.utils.logparser import LtpParser -class LtpTestBase(OERuntimeTestCase): - - @classmethod - def setUpClass(cls): - cls.ltp_startup() - - @classmethod - def tearDownClass(cls): - cls.ltp_finishup() - - @classmethod - def ltp_startup(cls): - cls.sections = {} - cls.failmsg = "" - test_log_dir = os.path.join(cls.td.get('WORKDIR', ''), 'testimage') - timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S') - - cls.ltptest_log_dir_link = os.path.join(test_log_dir, 'ltp_log') - cls.ltptest_log_dir = '%s.%s' % (cls.ltptest_log_dir_link, timestamp) - os.makedirs(cls.ltptest_log_dir) - - cls.tc.target.run("mkdir -p /opt/ltp/results") - - if not hasattr(cls.tc, "extraresults"): - cls.tc.extraresults = {} - cls.extras = cls.tc.extraresults - cls.extras['ltpresult.rawlogs'] = {'log': ""} - - - @classmethod - def ltp_finishup(cls): - cls.extras['ltpresult.sections'] = cls.sections - - # update symlink to ltp_log - if os.path.exists(cls.ltptest_log_dir_link): - os.remove(cls.ltptest_log_dir_link) - os.symlink(os.path.basename(cls.ltptest_log_dir), cls.ltptest_log_dir_link) - - if cls.failmsg: - cls.fail(cls.failmsg) - class LtpTest(LtpTestBase): + ltp_log_name = 'ltp_log' + ltp_result_prefix = 'ltpresult' ltp_groups = ["math", "syscalls", "dio", "mm", "sched", "nptl", "containers", "controllers", "fcntl-locktests", "commands", "net.ipv6_lib", "input","fs_perms_simple", "cve", "crypto", "ima", "net.nfs", "net_stress.ipsec_icmp", "net.ipv6", "numa", "uevent", "ltp-aiodio.part1", "ltp-aiodio.part2", "ltp-aiodio.part3", "ltp-aiodio.part4"] diff --git a/meta/lib/oeqa/runtime/cases/ltp_compliance.py b/meta/lib/oeqa/runtime/cases/ltp_compliance.py index ba47c78fd46..f16750a791c 100644 --- a/meta/lib/oeqa/runtime/cases/ltp_compliance.py +++ b/meta/lib/oeqa/runtime/cases/ltp_compliance.py @@ -5,58 +5,19 @@ # SPDX-License-Identifier: GPL-2.0-only # +import os import time -import datetime import pprint -from oeqa.runtime.case import OERuntimeTestCase +from oeqa.runtime.utils.ltp import LtpTestBase from oeqa.core.decorator.depends import OETestDepends from oeqa.runtime.decorator.package import OEHasPackage from oeqa.utils.logparser import LtpComplianceParser -class LtpPosixBase(OERuntimeTestCase): +class LtpPosixTest(LtpTestBase): + ltp_log_name = 'ltpcomp_log' + ltp_result_prefix = 'ltpposixresult' - @classmethod - def setUpClass(cls): - cls.ltp_startup() - - @classmethod - def tearDownClass(cls): - cls.ltp_finishup() - - @classmethod - def ltp_startup(cls): - cls.sections = {} - cls.failmsg = "" - test_log_dir = os.path.join(cls.td.get('WORKDIR', ''), 'testimage') - timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S') - - cls.ltptest_log_dir_link = os.path.join(test_log_dir, 'ltpcomp_log') - cls.ltptest_log_dir = '%s.%s' % (cls.ltptest_log_dir_link, timestamp) - os.makedirs(cls.ltptest_log_dir) - - cls.tc.target.run("mkdir -p /opt/ltp/results") - - if not hasattr(cls.tc, "extraresults"): - cls.tc.extraresults = {} - cls.extras = cls.tc.extraresults - cls.extras['ltpposixresult.rawlogs'] = {'log': ""} - - - @classmethod - def ltp_finishup(cls): - cls.extras['ltpposixresult.sections'] = cls.sections - - # update symlink to ltp_log - if os.path.exists(cls.ltptest_log_dir_link): - os.remove(cls.ltptest_log_dir_link) - - os.symlink(os.path.basename(cls.ltptest_log_dir), cls.ltptest_log_dir_link) - - if cls.failmsg: - cls.fail(cls.failmsg) - -class LtpPosixTest(LtpPosixBase): posix_groups = ["AIO", "MEM", "MSG", "SEM", "SIG", "THR", "TMR", "TPS"] def runltp(self, posix_group): diff --git a/meta/lib/oeqa/runtime/cases/ltp_stress.py b/meta/lib/oeqa/runtime/cases/ltp_stress.py index c902486eabf..e52d64c662b 100644 --- a/meta/lib/oeqa/runtime/cases/ltp_stress.py +++ b/meta/lib/oeqa/runtime/cases/ltp_stress.py @@ -5,59 +5,19 @@ # SPDX-License-Identifier: MIT # +import os import time -import datetime import pprint -from oeqa.runtime.case import OERuntimeTestCase +from oeqa.runtime.utils.ltp import LtpTestBase from oeqa.core.decorator.depends import OETestDepends from oeqa.runtime.decorator.package import OEHasPackage from oeqa.core.decorator.data import skipIfQemu from oeqa.utils.logparser import LtpParser -class LtpStressBase(OERuntimeTestCase): - - @classmethod - def setUpClass(cls): - cls.ltp_startup() - - @classmethod - def tearDownClass(cls): - cls.ltp_finishup() - - @classmethod - def ltp_startup(cls): - cls.sections = {} - cls.failmsg = "" - test_log_dir = os.path.join(cls.td.get('WORKDIR', ''), 'testimage') - timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S') - - cls.ltptest_log_dir_link = os.path.join(test_log_dir, 'ltpstress_log') - cls.ltptest_log_dir = '%s.%s' % (cls.ltptest_log_dir_link, timestamp) - os.makedirs(cls.ltptest_log_dir) - - cls.tc.target.run("mkdir -p /opt/ltp/results") - - if not hasattr(cls.tc, "extraresults"): - cls.tc.extraresults = {} - cls.extras = cls.tc.extraresults - cls.extras['ltpstressresult.rawlogs'] = {'log': ""} - - - @classmethod - def ltp_finishup(cls): - cls.extras['ltpstressresult.sections'] = cls.sections - - # update symlink to ltp_log - if os.path.exists(cls.ltptest_log_dir_link): - os.remove(cls.ltptest_log_dir_link) - - os.symlink(os.path.basename(cls.ltptest_log_dir), cls.ltptest_log_dir_link) - - if cls.failmsg: - cls.fail(cls.failmsg) - -class LtpStressTest(LtpStressBase): +class LtpStressTest(LtpTestBase): + ltp_log_name = 'ltpstress_log' + ltp_result_prefix = 'ltpstressresult' def runltp(self, stress_group): cmd = 'kirk --run-suite %s --json-report /opt/ltp/results/%s.json -n -d /opt/ltp' % (stress_group, stress_group) diff --git a/meta/lib/oeqa/runtime/utils/ltp.py b/meta/lib/oeqa/runtime/utils/ltp.py new file mode 100644 index 00000000000..e3aea4ead2f --- /dev/null +++ b/meta/lib/oeqa/runtime/utils/ltp.py @@ -0,0 +1,59 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +import datetime +import os + +from oeqa.runtime.case import OERuntimeTestCase + +class LtpTestBase(OERuntimeTestCase): + """ + Common setup and teardown for the LTP based test cases. Subclasses set + ltp_log_name, the name of the log directory symlink in the test log + directory, and ltp_result_prefix, the prefix of their extra test result + entries. + """ + ltp_log_name = None + ltp_result_prefix = None + + @classmethod + def setUpClass(cls): + cls.ltp_startup() + + @classmethod + def tearDownClass(cls): + cls.ltp_finishup() + + @classmethod + def ltp_startup(cls): + cls.sections = {} + cls.failmsg = "" + test_log_dir = os.path.join(cls.td.get('WORKDIR', ''), 'testimage') + timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S') + + cls.ltptest_log_dir_link = os.path.join(test_log_dir, cls.ltp_log_name) + cls.ltptest_log_dir = '%s.%s' % (cls.ltptest_log_dir_link, timestamp) + os.makedirs(cls.ltptest_log_dir) + + cls.tc.target.run("mkdir -p /opt/ltp/results") + + if not hasattr(cls.tc, "extraresults"): + cls.tc.extraresults = {} + cls.extras = cls.tc.extraresults + cls.extras['%s.rawlogs' % cls.ltp_result_prefix] = {'log': ""} + + @classmethod + def ltp_finishup(cls): + cls.extras['%s.sections' % cls.ltp_result_prefix] = cls.sections + + # update symlink to the log directory + if os.path.exists(cls.ltptest_log_dir_link): + os.remove(cls.ltptest_log_dir_link) + os.symlink(os.path.basename(cls.ltptest_log_dir), cls.ltptest_log_dir_link) + + if cls.failmsg: + # fail() is an instance method so can't be used from a classmethod + raise cls.failureException(cls.failmsg) From patchwork Sun Nov 15 08:48:26 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104213 Received: from mail-wr1-f53.google.com (mail-wr1-f53.google.com [209.85.221.53]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.4383.1794732567458296412 for ; Sun, 15 Nov 2026 00:49:27 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=CbuNLnEb; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.53, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f53.google.com with SMTP id ffacd0b85a97d-490d59c3f0aso857610f8f.1 for ; Sun, 15 Nov 2026 00:49:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732566; x=1795337366; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=1fY9ot6KSxVNPoeXaV4C/9xVHe0Ou/9GKlo61/g2LsQ=; b=CbuNLnEb0TfvTgGL/bpTl+UnYDFyK++2VgJis3v1J9DSoJd0w1deu4rBq20RH5tvKU 7aeFaMuvO331qyzKwzSYvsRvFlcRlSL99dNaUBlI95g0p1ASOXLVD/sby6ak72T2wPsy MO9MO4haJZCZyTN7DqB2GsQzx+p5tzCcp1G3U= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732566; x=1795337366; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=1fY9ot6KSxVNPoeXaV4C/9xVHe0Ou/9GKlo61/g2LsQ=; b=f2v57VwThJ0cq/pAQdr61oRth5+xXk0RGasCrs5xslW85gU0AdAc2+EL7tYDs0oEox GVBeY96mWACoeIERLHSrS3mq1X5EU1cOuQ91BWFfzEN0iulmUNyCtpLOxSCp4RG7omhJ i3kYCo9UUKbifUP7Yi8lciKkr1Kr+ELHInIcHZuejEksR9HnSQGdMu+PjxhtdMQ1ygBI /pK4eiAPGpbad1JgsNMhO7wDo4Db8wXYoCs6cCbTpytosaLvGFBXEIRa7w8fAYZtGTGH bKxMJjvANtlerEAVQQDpIYFYUglvpasrR7fC2+V2dMsH2kea/HtR7+rIOuHSJQol4xgd 9Peg== X-Gm-Message-State: APuU4Z9zVIcpj/TA4KjIjAqmv2bLSQy9y4cyVG+T/vcpvQh1yjDFzQlq gLO0+Ydx9tIq/EdWMZOAqqInIi3tjPR32ebOIQC+otWPdZWAuzXJwNgTyhUAoXihyWGAAOibs2d 4mIGpFrk= X-Gm-Gg: AYBFou0HRi2xUldX5Xv20PFylYY2tljrKGs0176xLsGO81PGRTzB2HG8n4lP+sXJWcz vBQWbSlzPCXAyjDP7eAUAv70+LAJF+pb4ApXrSbgumZiWYBt50aLEWYy7a4StNqdMw8QU9utvVL OgEZueXnf8iEGwD1fDzFjs41OlvqVVzYyPPYOWqS1PjhcUzGz0oXS7RdmoEifGL8lRPh6xgFTze SP4dg6niNvLaiDf/Fkhf3dQlraMj3qqciH+mMCKBDSXHQGOi46JR95wBaeicV2LYHwK8+Quk8F6 kSgXlLCM/oFwrqeeAnruZHDfnqhOgHLqoAOl2ihEGaasiCpSNRP5QRu2wfDauORBbC0P0elfDru NvDARH8CKIEiu1HU3f5NwzUu2N3liKYDiFR3ZkSSudrYyxBsffl+vQ1aRqJTwAt4MeagVMcoXeA rH4Xw0ZxYxsEk0Z518zTCB2TAnzox1SX8cG6/IX6gloUaPxxZH50CsIaSjjCGhRPLodusMQ6pcf p84wARvRxrO8gCiZ94KCnAOiWatzEHz7iPec8cazakjd9oFBU/xtQBVWzYgkY01PgDX7xhbTVSR DE5naCdbFCn0cBvNlpobPvyUW9lgpxvDPKP6W8R5OsMSgDnOFhpEH0RB4g== X-Received: by 2002:a05:6000:1a8a:b0:48b:f93:3b87 with SMTP id ffacd0b85a97d-49c726da6e1mr17443711f8f.30.1794732565786; Sun, 15 Nov 2026 00:49:25 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.24 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:24 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 23/41] oeqa/selftest/oelib/buildhistory: Fix variable removal in commit_vars() Date: Sun, 15 Nov 2026 08:48:26 +0000 Message-ID: <20261115084845.701136-23-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:33 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250254 The loop over to_remove popped the undefined name 'x' rather than the loop variable so passing to_remove would raise a NameError. No current caller passes it but fix it so the helper works as intended. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/selftest/cases/oelib/buildhistory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/lib/oeqa/selftest/cases/oelib/buildhistory.py b/meta/lib/oeqa/selftest/cases/oelib/buildhistory.py index 042ccdd2b48..dbc8f9346fa 100644 --- a/meta/lib/oeqa/selftest/cases/oelib/buildhistory.py +++ b/meta/lib/oeqa/selftest/cases/oelib/buildhistory.py @@ -45,7 +45,7 @@ class TestBlobParsing(OESelftestTestCase): return for k in to_remove: - self.var_map.pop(x,None) + self.var_map.pop(k, None) for k in to_add: self.var_map[k] = to_add[k] From patchwork Sun Nov 15 08:48:27 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104214 Received: from mail-wm1-f54.google.com (mail-wm1-f54.google.com [209.85.128.54]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.4385.1794732568675162504 for ; Sun, 15 Nov 2026 00:49:29 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=IqFF5jer; spf=pass (domain: linuxfoundation.org, ip: 209.85.128.54, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wm1-f54.google.com with SMTP id 5b1f17b1804b1-4a1fbd52ab6so20172275e9.0 for ; Sun, 15 Nov 2026 00:49:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732567; x=1795337367; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=oZKjYFAXhpeS/hzha++WxE7oXiYUe/QL0AECFZrso9o=; b=IqFF5jerX98W4nWzU/q+ckItpvXtRaJUpccg09QgB+MA3R9qOyoF5V/NjZVA/6lvum jIOsjm19b8qeLdpxc2PAo08k+lMxCTKFaiBgHSFRelZcKRX66m8QWpkyWlceD0/SOVzX DsInrWb3XLB35zxqmis+37DRiNfNEEY/W/c7U= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732567; x=1795337367; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=oZKjYFAXhpeS/hzha++WxE7oXiYUe/QL0AECFZrso9o=; b=I+47t4xyHazY4/5cj6wglu/2K0CTBCCfRhk2ONyE0rIejg3wljFHvSoGPgK4ZAlNSe axe9Gu8b4OgumHT/OL9fosPeAmZsTcZrHMAeuGKUkG/YnAEGfIUlXcPvd6GqdkdgaUwX HO6pzv/BlOrJA0B8x2uXs+1SiQB1wH7R/NzAKe4RaLZzp0J0OBeCY8w7sn7qbJnQAalp /ymlhBXIeBeGFZNBbMSI1RF2Gp2BX+gXgwCEo68GKVG4Hnos6LmicLWg5e1g7VCpKxwD NEOvxkMzo4YU8cbdA4YqEkluQu4WlXHsFU5inLDp4IG3iQ3Yek9NGabSyY+wHDBglxcK AxoA== X-Gm-Message-State: APuU4Z83q5nfDW95R3id6UnISyogUHJ+8eWo9P023MBHZg2DVf7osld/ jRPfDpX6c8FFjqaghjhHP514phfCpcUUw60BbcSY9kDWrmaR4CvCK6xW5XVrEoj0IdlpP8Gw+Z0 ucKTGHQ8= X-Gm-Gg: AYBFou3KHTBRM8zexp6H7He90xKJulJys/8tCpBYhRzWfelTbgatCFrNY0Oq0ftWd+a Fd6P0VP85i2SNhm4ndsCg6EOzU1npj6vBUGsXF9/X6sWltikd9NoVt376n+XB1VV0w62ikUaA1u nSqJhP9yTmY8f/eavkeGGj6/UPz8KQb4S+xmwQncVC5ZG3t7pZop8bTGLmNG16YJHEbpsyeF8rG zZpILs019y2nti8oTMHLObH1OnzFYppuQSGZWpJAw/Xw2m/WsRLE5b/ve3LNkw28dxUWQLSOkg2 1Ice/Nv/y4CPFRoF/kqRMbjhdyD2JBrib2OM5zX+3u1zw24+TZbO2hMKY/Z42eA1QkHm/9J2VEt bdKZsHk2Lp983LHOJhUve0WnbGVWSO4W56mtcWaNDWAVIh7zXTsOqbqSh6vzeVYr7r/vPHpyKTK fKSEGnaigpgxORn5vQ2t3pPwCQDo67q20iY+uGZOfaCVJrolU0AL7tYWbp6lx4WJf+81wJGglBp oC2nbg0/JJYHYwyc1bMpbw0vSVqIEFdQ6M1lIwJj5AXt6AlSLSOhUyL2idLb1cKX3si/qryW+Ht dCU57kifxsLZ8nQnpvEqLnO6El8ERc87oQ6bBNNuHDbt7DLpk9V5YtmalQ== X-Received: by 2002:a05:600c:8b0a:b0:4a1:da58:1ee with SMTP id 5b1f17b1804b1-4bb55a95dbamr153277325e9.31.1794732566720; Sun, 15 Nov 2026 00:49:26 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.25 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:26 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 24/41] oeqa: Remove unused code Date: Sun, 15 Nov 2026 08:48:27 +0000 Message-ID: <20261115084845.701136-24-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:33 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250255 Drop code nothing uses: - utils/targetbuild.py, an older copy of the BuildProject classes which are now in utils/buildproject.py, runtime/utils and sdk/utils - str_to_fn() in buildperf, which also always raised ValueError as re.LOCALE can't be used with str patterns - the dummybuf class in concurrencytest - getCaseClass() in core/utils/test.py - the empty metadata_from_data_store() stub - an unused variable in sdk/context.py and an unused assignment in the OETestDataDepends check AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/buildperf/base.py | 5 - meta/lib/oeqa/core/decorator/data.py | 4 +- meta/lib/oeqa/core/utils/concurrencytest.py | 11 -- meta/lib/oeqa/core/utils/test.py | 6 - meta/lib/oeqa/sdk/context.py | 1 - meta/lib/oeqa/utils/metadata.py | 9 -- meta/lib/oeqa/utils/targetbuild.py | 144 -------------------- 7 files changed, 1 insertion(+), 179 deletions(-) delete mode 100644 meta/lib/oeqa/utils/targetbuild.py diff --git a/meta/lib/oeqa/buildperf/base.py b/meta/lib/oeqa/buildperf/base.py index 37696466f4e..dcdc053da85 100644 --- a/meta/lib/oeqa/buildperf/base.py +++ b/meta/lib/oeqa/buildperf/base.py @@ -65,11 +65,6 @@ class KernelDropCaches: runCmd2(cmd, data=input_data) -def str_to_fn(string): - """Convert string to a sanitized filename""" - return re.sub(r'(\W+)', '-', string, flags=re.LOCALE) - - class ResultsJsonEncoder(json.JSONEncoder): """Extended encoder for build perf test results""" unix_epoch = datetime.utcfromtimestamp(0) diff --git a/meta/lib/oeqa/core/decorator/data.py b/meta/lib/oeqa/core/decorator/data.py index 0daf46334f6..fddedfdb4bc 100644 --- a/meta/lib/oeqa/core/decorator/data.py +++ b/meta/lib/oeqa/core/decorator/data.py @@ -99,9 +99,7 @@ class OETestDataDepends(OETestDecorator): def setUpDecorator(self): for v in self.td_depends: - try: - value = self.case.td[v] - except KeyError: + if v not in self.case.td: raise OEQAMissingVariable("Test case need %s variable but"\ " isn't into td" % v) diff --git a/meta/lib/oeqa/core/utils/concurrencytest.py b/meta/lib/oeqa/core/utils/concurrencytest.py index ade0a83cb82..267dba7ba19 100644 --- a/meta/lib/oeqa/core/utils/concurrencytest.py +++ b/meta/lib/oeqa/core/utils/concurrencytest.py @@ -198,17 +198,6 @@ def outSideTestaddSkip(self, offset, line): subunit._OutSideTest.addSkip = outSideTestaddSkip -# -# A dummy structure to add to io.StringIO so that the .buffer object -# is available and accepts writes. This allows unittest with buffer=True -# to interact ok with subunit which wants to access sys.stdout.buffer. -# -class dummybuf: - def __init__(self, parent): - self.p = parent - def write(self, data): - self.p.write(data.decode("utf-8")) - # # Taken from testtools.ConncurrencyTestSuite but modified for OE use # diff --git a/meta/lib/oeqa/core/utils/test.py b/meta/lib/oeqa/core/utils/test.py index d38cab8a511..99b7b9e6a6c 100644 --- a/meta/lib/oeqa/core/utils/test.py +++ b/meta/lib/oeqa/core/utils/test.py @@ -64,12 +64,6 @@ def getCaseModule(test_case): """ return test_case.__module__ -def getCaseClass(test_case): - """ - Returns test case class name. - """ - return test_case.__class__.__name__ - def getCaseID(test_case): """ Returns test case complete id. diff --git a/meta/lib/oeqa/sdk/context.py b/meta/lib/oeqa/sdk/context.py index f00e40eb6c6..6024554cac4 100644 --- a/meta/lib/oeqa/sdk/context.py +++ b/meta/lib/oeqa/sdk/context.py @@ -113,7 +113,6 @@ class OESDKTestContextExecutor(OETestContextExecutor): def _get_sdk_environs(sdk_dir): sdk_env = {} - environ_pattern = sdk_dir + '/environment-setup-*' full_sdk_env = glob.glob(sdk_dir + '/environment-setup-*') for env in full_sdk_env: m = re.search('environment-setup-(.*)', env) diff --git a/meta/lib/oeqa/utils/metadata.py b/meta/lib/oeqa/utils/metadata.py index 941a66de03e..3716e997f26 100644 --- a/meta/lib/oeqa/utils/metadata.py +++ b/meta/lib/oeqa/utils/metadata.py @@ -50,15 +50,6 @@ def metadata_from_bb(): info_dict['config'][var] = data_dict[var] return info_dict -def metadata_from_data_store(d): - """ Returns test's metadata as OrderedDict. - - Data will be collected from the provided data store. - """ - # TODO: Getting metadata from the data store would - # be useful when running within bitbake. - pass - def git_rev_info(path): """Get git revision information as a dict""" info = OrderedDict() diff --git a/meta/lib/oeqa/utils/targetbuild.py b/meta/lib/oeqa/utils/targetbuild.py deleted file mode 100644 index 2365dda11bd..00000000000 --- a/meta/lib/oeqa/utils/targetbuild.py +++ /dev/null @@ -1,144 +0,0 @@ -# -# Copyright (C) 2013 Intel Corporation -# -# SPDX-License-Identifier: MIT -# - -# Provides a class for automating build tests for projects - -import os -import re -import bb.utils -import subprocess -import tempfile -from abc import ABCMeta, abstractmethod - -class BuildProject(metaclass=ABCMeta): - - def __init__(self, d, uri, foldername=None, tmpdir=None): - self.d = d - self.uri = uri - self.archive = os.path.basename(uri) - self.tempdirobj = None - if not tmpdir: - tmpdir = self.d.getVar('WORKDIR') - if not tmpdir: - self.tempdirobj = tempfile.TemporaryDirectory(prefix='buildproject-') - tmpdir = self.tempdirobj.name - self.localarchive = os.path.join(tmpdir, self.archive) - if foldername: - self.fname = foldername - else: - self.fname = re.sub(r'\.tar\.bz2$|\.tar\.gz$|\.tar\.xz$', '', self.archive) - - # Download self.archive to self.localarchive - def _download_archive(self): - dl_dir = self.d.getVar("DL_DIR") - if dl_dir and os.path.exists(os.path.join(dl_dir, self.archive)): - bb.utils.copyfile(os.path.join(dl_dir, self.archive), self.localarchive) - return - - exportvars = ['HTTP_PROXY', 'http_proxy', - 'HTTPS_PROXY', 'https_proxy', - 'FTP_PROXY', 'ftp_proxy', - 'FTPS_PROXY', 'ftps_proxy', - 'NO_PROXY', 'no_proxy', - 'ALL_PROXY', 'all_proxy', - 'SOCKS5_USER', 'SOCKS5_PASSWD'] - - env = os.environ.copy() - for var in exportvars: - val = self.d.getVar(var) - if val: - env[var] = val - - cmd = ['wget', '-O', self.localarchive, self.uri] - subprocess.check_output(cmd, env=env) - - # This method should provide a way to run a command in the desired environment. - @abstractmethod - def _run(self, cmd): - pass - - # The timeout parameter of target.run is set to 0 to make the ssh command - # run with no timeout. - def run_configure(self, configure_args='', extra_cmds=''): - return self._run('cd %s; %s ./configure %s' % (self.targetdir, extra_cmds, configure_args)) - - def run_make(self, make_args=''): - return self._run('cd %s; make %s' % (self.targetdir, make_args)) - - def run_install(self, install_args=''): - return self._run('cd %s; make install %s' % (self.targetdir, install_args)) - - def clean(self): - if self.tempdirobj: - self.tempdirobj.cleanup() - self._run('rm -rf %s' % self.targetdir) - subprocess.check_call(['rm', '-f', self.localarchive]) - -class TargetBuildProject(BuildProject): - - def __init__(self, target, d, uri, foldername=None): - self.target = target - self.targetdir = "~/" - BuildProject.__init__(self, d, uri, foldername) - - def download_archive(self): - - self._download_archive() - - (status, output) = self.target.copy_to(self.localarchive, self.targetdir) - if status != 0: - raise Exception("Failed to copy archive to target, output: %s" % output) - - (status, output) = self.target.run('tar xf %s%s -C %s' % (self.targetdir, self.archive, self.targetdir)) - if status != 0: - raise Exception("Failed to extract archive, output: %s" % output) - - #Change targetdir to project folder - self.targetdir = self.targetdir + self.fname - - # The timeout parameter of target.run is set to 0 to make the ssh command - # run with no timeout. - def _run(self, cmd): - return self.target.run(cmd, 0)[0] - - -class SDKBuildProject(BuildProject): - - def __init__(self, testpath, sdkenv, d, uri, foldername=None): - self.sdkenv = sdkenv - self.testdir = testpath - self.targetdir = testpath - bb.utils.mkdirhier(testpath) - self.datetime = d.getVar('DATETIME') - self.testlogdir = d.getVar("TEST_LOG_DIR") - bb.utils.mkdirhier(self.testlogdir) - self.logfile = os.path.join(self.testlogdir, "sdk_target_log.%s" % self.datetime) - BuildProject.__init__(self, d, uri, foldername, tmpdir=testpath) - - def download_archive(self): - - self._download_archive() - - cmd = ['tar', 'xf', self.targetdir + self.archive, '-C', self.targetdir] - subprocess.check_output(cmd) - - #Change targetdir to project folder - self.targetdir = os.path.join(self.targetdir, self.fname) - - def run_configure(self, configure_args='', extra_cmds=' gnu-configize; '): - return super().run_configure(configure_args=(configure_args or '$CONFIGURE_FLAGS'), extra_cmds=extra_cmds) - - def run_install(self, install_args=''): - return super().run_install(install_args=(install_args or "DESTDIR=%s/../install" % self.targetdir)) - - def log(self, msg): - if self.logfile: - with open(self.logfile, "a") as f: - f.write("%s\n" % msg) - - def _run(self, cmd): - self.log("Running . %s; " % self.sdkenv + cmd) - return subprocess.check_call(". %s; " % self.sdkenv + cmd, shell=True) From patchwork Sun Nov 15 08:48:28 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104215 Received: from mail-wr1-f51.google.com (mail-wr1-f51.google.com [209.85.221.51]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.4387.1794732570849724975 for ; Sun, 15 Nov 2026 00:49:31 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=Oi39OgAC; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.51, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f51.google.com with SMTP id ffacd0b85a97d-491971ac844so2254634f8f.2 for ; Sun, 15 Nov 2026 00:49:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732569; x=1795337369; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=bfPqxnnrPcmDHG7CZpqqwYdrk79EiIFko9RVMoc/CKc=; b=Oi39OgACfN3klcmNuXZu6ldLXQ/fvums9JYc6Ohz1KNxTwjmTPGMXxXSGGkUCYeAK2 pASl/xNQMKTN4etPkfSVo0pwcjJZwy+1R0FdlbR2qlqSzgXBUURkr2DYCUpDjmKD+9Bp sHV93oqlwFkbgoUmWgjwFBJANHLDT1UMuPRoI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732569; x=1795337369; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=bfPqxnnrPcmDHG7CZpqqwYdrk79EiIFko9RVMoc/CKc=; b=sNDTgT4ijje9xTll/JGh2yZYoLEK35Zpf+4Y6MABwYdr52QUNt4YF4hp1KuV9JkEZX jAvjJHi1JXo8TegFK5rlR82EoJ9SvLXqFsOVsfPH2cMNpkasHarKx5hlHb/+f6RdVSyR /rUOvRQ6+RMIyChYd96Vhyj3hsAGAUEzdnkyCuhEcxRmTrsvq5Lkt88kzi2kemxjSRw3 LXhPvrh7Sk2uTGx6xYNhqv5EOkCHPXi2Ju9PcVKaft3L8Qp1mnF+ONR2udJYjLaDoXpJ c2a5pcStIcXvYGWlQffpbwxLEPyY+PjtnDLoA7D4sja/DDYW0WDp7Bk9TC81LUTgI15R Wziw== X-Gm-Message-State: APuU4Z+hDd3J17BcTQev7x9OutiMxG1+6upRx+Zzh2szRFcPq5SOV+mO tFPGAuivnNKHhzlNMxhUYWXmfkwvHFOwYb2R1zngHWZ35Fgqsa2Kvc+WX1sScOdGLyRT5oMGyiX 3Oekozik= X-Gm-Gg: AYBFou2TrWxCWPVRF50RrTNyktpPAmWV0OK6WiD46qz8cNvKVGIEt0pGQcYYmo0Ue99 eeFq2wtqcAOemWb8uMo8kiwBFkPHKakM/qr8aJePsom1HRNhhXiziEFmwWNbqFTlLasbpIG59Qu 8DANNXB3ijW7ntdoyBhP6t0uOAsiUnamcl/GAqM0Iag4d14G/LmFsHVqA7b7R2jcrBd1A9pyWw8 Zsu1MbaUmTr5gWWEX132YD2KGqBH1gzCj96/uhe5KSBN9v6/Hg20FBANci9HX/oF/txKLiTmnd2 7CPvBmnyJbR63phPuOiAZHCYqesB9HExv5olHF3j71CPyoNDsF5gq+TjDr4HKSZR70Dnzhhroon yiSvF2hnqiPlg5C9FhajttZWP7fTtkC3vtgSffC5kAxvdmm0cP2THrOxt10arLDGCGw1aWU228j T/XVYAMaS4yn9kvuljCkhUQrW5GX4btGobMFcc/nsNzkMcbm/g/XXpIjXE1lxcwwNRHf4zNhwlo BPn8K++eOV5nv9lDltSOW2paJwH0V0JO6Ui0Di/g2bA8OSacZQaDCykYNqGAnTt2iez9ePZ/jqL X/TxCKtoTuBUv84KPDxEtMQPwjOThfTLE8/Phzzir/VkGBi5/dbVuNfWOg== X-Received: by 2002:a05:6000:46c2:b0:48f:db47:6ebf with SMTP id ffacd0b85a97d-49c729bb31fmr10663382f8f.38.1794732569013; Sun, 15 Nov 2026 00:49:29 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.26 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:27 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 25/41] oeqa/core/loader: Simplify the _make_failed_test override Date: Sun, 15 Nov 2026 08:48:28 +0000 Message-ID: <20261115084845.701136-25-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:33 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250256 We now require python 3.9 or later so we can drop the python 3.4 era compatibility code. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/core/loader.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/meta/lib/oeqa/core/loader.py b/meta/lib/oeqa/core/loader.py index 5e96988b7a9..719e2a8a4c3 100644 --- a/meta/lib/oeqa/core/loader.py +++ b/meta/lib/oeqa/core/loader.py @@ -8,7 +8,6 @@ import os import re import sys import unittest -import inspect from oeqa.core.utils.path import findFile from oeqa.core.utils.test import getSuiteModules, getCaseID @@ -23,12 +22,8 @@ from oeqa.core.decorator import decoratorClasses, OETestDecorator, \ # # For our purposes, it is better to raise the exceptions in the loading # step rather than waiting to run the test suite. -# -# Generate the function definition because this differ across python versions -# Python >= 3.4.4 uses tree parameters instead four but for example Python 3.5.3 -# ueses four parameters so isn't incremental. -_failed_test_args = inspect.getfullargspec(unittest.loader._make_failed_test).args -exec("""def _make_failed_test(%s): raise exception""" % ', '.join(_failed_test_args)) +def _make_failed_test(methodname, exception, *args, **kwargs): + raise exception unittest.loader._make_failed_test = _make_failed_test def _find_duplicated_modules(suite, directory): From patchwork Sun Nov 15 08:48:29 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104211 Received: from mail-wm1-f50.google.com (mail-wm1-f50.google.com [209.85.128.50]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4333.1794732572394574999 for ; Sun, 15 Nov 2026 00:49:32 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=DFaaI0vC; spf=pass (domain: linuxfoundation.org, ip: 209.85.128.50, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wm1-f50.google.com with SMTP id 5b1f17b1804b1-4bb64c99d2fso10229385e9.3 for ; Sun, 15 Nov 2026 00:49:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732571; x=1795337371; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=f7iXH4nEv2ubLA4XSH/w3O/vGDyit425+b7EzLSXgWE=; b=DFaaI0vCV1x4bwApTVHNESdXI9AotNsUQXTX2+cJB4Sz7JYYPYpS91+beqEyeYSL4o NC1tMoD2xw41gTCscMlTLma1mzzET02/IiyXqkWTQ6r6LafI3hgukdP/Q8yG+Y2ulHpl 7a48vp1G21ICUz2iY1ZQayVT1BjbV+kGjgrr0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732571; x=1795337371; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=f7iXH4nEv2ubLA4XSH/w3O/vGDyit425+b7EzLSXgWE=; b=1Kb3GuwNKQN/FBt+MEVOH3jKai32P+ETOqE0xzofiuOqbH+xf3dr9MkiPPakYAjdUF IrU+oSWjobyzVu+PB3uMExzx2Q3amsg+9KzHIIQxyd8xJWE0Y38pWGDwM8AtfBWU2nab XzOcUfo259cA4D/qywtcPeKQmJzuhdfU4au0/xetLLxhvg6XotcT6prW7jkGBScqW24F RS/+meBODIjpaC6+72/kb8WLerdSYJ+nwFjINc7H1uL6s3cm4KvMhsuU3amBWviq7DsM brraf4zVOgyOpnCJPg9rt04yRFvkz/s8EK+NpmY0Wy6tX83avwYOXkWRkHqONIn3wTmo sOzQ== X-Gm-Message-State: APuU4Z/zvyQd+Kj5TF6INYGXfYHLRLPqn0nd7BV9GuWAi7czPwQt4uN8 bXGWuLFFGMGtfy0v4bimoIHXfIyj7pa4uZJp4tFxubgd9EPLtnHLxbZo9EB6R/6do7k7q66RvUq GX50RrqU= X-Gm-Gg: AYBFou21LGtaSGVlLfJ0KwV35NtTwwoFcACZvTLIDqCipZ23+dSijlM3v3ngdJkYOFR z5RCSIdRP/nrJOMW+P3C6/hjDyJLoKXellNuV5mHanKMLFFxoYCE1TpETsdAiPPh/xCmtce5e5s 3djwXI78zKw0I7q6weF1LvTpUmLCMqjc/+QmHYp+b8Taec1adjoD7WrxX3nmcSY8M8OvF8xVa9C atgYYIACPRCsY4clZnDek5gWLqQQUhLD+R5zTVu0GdAYjgzuGWQSPkcxUV93UhBEZNus6AY7JDV LtxZ/QsOONDxaz8C26067pK62/WI+UDiEEOSno2Fj6E7DaQ+jG1bZI94im2ECaWXPAhDLfCn2Vu 3TW4KnPBUmBky9Ek8TtAZ/+W/yjenf86aBqKzzjuox2JZm/ZJf01VdfyEQ5DWJD8fD8NizD21ag BR/nujDh8D0P3EcFNYf30xY86N1glqOtkLF9iQ3toQrH9gDXObAH5NJR5b0zalQXCX6tOL/H5ku Tunjg36D+KUi/ZYRmPWa2CQ3+ztLDX76r48sMh9CBlPE/dctD/NA033glSB5/xvSmiUShJ1fi5Y DHHWO5Y1aNcQG8KszKgjwXhfbVTqM4h61nUE56Zm0MewqjnqmFACZ23DRBmOoIuL1nl2ei3aq6F cmDs= X-Received: by 2002:a05:600c:4f0e:b0:4bb:5f43:23bb with SMTP id 5b1f17b1804b1-4bb5f43261fmr109061995e9.33.1794732570501; Sun, 15 Nov 2026 00:49:30 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.29 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:29 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 26/41] oeqa: Remove unused imports Date: Sun, 15 Nov 2026 08:48:29 +0000 Message-ID: <20261115084845.701136-26-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:33 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250257 Drop imports which nothing in the module uses. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/buildperf/base.py | 1 - meta/lib/oeqa/core/loader.py | 1 - meta/lib/oeqa/core/target/qemu.py | 4 ---- meta/lib/oeqa/core/target/ssh.py | 1 - meta/lib/oeqa/core/utils/concurrencytest.py | 1 - meta/lib/oeqa/core/utils/path.py | 1 - meta/lib/oeqa/core/utils/test.py | 1 - meta/lib/oeqa/sdk/testsdk.py | 2 -- meta/lib/oeqa/sdkext/testsdk.py | 2 +- meta/lib/oeqa/selftest/cases/usergrouptests.py | 1 - meta/lib/oeqa/selftest/context.py | 3 --- meta/lib/oeqa/utils/commands.py | 1 - meta/lib/oeqa/utils/ftools.py | 2 -- meta/lib/oeqa/utils/httpserver.py | 2 +- meta/lib/oeqa/utils/nfs.py | 2 -- meta/lib/oeqa/utils/postactions.py | 2 -- meta/lib/oeqa/utils/qemurunner.py | 1 - 17 files changed, 2 insertions(+), 26 deletions(-) diff --git a/meta/lib/oeqa/buildperf/base.py b/meta/lib/oeqa/buildperf/base.py index dcdc053da85..6735e14fc8b 100644 --- a/meta/lib/oeqa/buildperf/base.py +++ b/meta/lib/oeqa/buildperf/base.py @@ -22,7 +22,6 @@ from xml.dom import minidom import oe.path from oeqa.utils.commands import CommandError, runCmd, get_bb_vars -from oeqa.utils.git import GitError, GitRepo # Get logger for this module log = logging.getLogger('build-perf') diff --git a/meta/lib/oeqa/core/loader.py b/meta/lib/oeqa/core/loader.py index 719e2a8a4c3..90b9366754d 100644 --- a/meta/lib/oeqa/core/loader.py +++ b/meta/lib/oeqa/core/loader.py @@ -4,7 +4,6 @@ # SPDX-License-Identifier: MIT # -import os import re import sys import unittest diff --git a/meta/lib/oeqa/core/target/qemu.py b/meta/lib/oeqa/core/target/qemu.py index e3e5ec874d5..2d541532f29 100644 --- a/meta/lib/oeqa/core/target/qemu.py +++ b/meta/lib/oeqa/core/target/qemu.py @@ -4,10 +4,6 @@ # SPDX-License-Identifier: MIT # -import os -import sys -import signal -import time import glob import subprocess from collections import defaultdict diff --git a/meta/lib/oeqa/core/target/ssh.py b/meta/lib/oeqa/core/target/ssh.py index 03e99e68234..e860c478fe8 100644 --- a/meta/lib/oeqa/core/target/ssh.py +++ b/meta/lib/oeqa/core/target/ssh.py @@ -9,7 +9,6 @@ import time import select import logging import subprocess -import codecs from . import OETarget diff --git a/meta/lib/oeqa/core/utils/concurrencytest.py b/meta/lib/oeqa/core/utils/concurrencytest.py index 267dba7ba19..d495665e028 100644 --- a/meta/lib/oeqa/core/utils/concurrencytest.py +++ b/meta/lib/oeqa/core/utils/concurrencytest.py @@ -18,7 +18,6 @@ import os import sys import traceback import unittest -import subprocess import testtools import threading import time diff --git a/meta/lib/oeqa/core/utils/path.py b/meta/lib/oeqa/core/utils/path.py index c086dcb0b04..288d38635fb 100644 --- a/meta/lib/oeqa/core/utils/path.py +++ b/meta/lib/oeqa/core/utils/path.py @@ -5,7 +5,6 @@ # import os -import sys def findFile(file_name, directory): """ diff --git a/meta/lib/oeqa/core/utils/test.py b/meta/lib/oeqa/core/utils/test.py index 99b7b9e6a6c..b5062c59f90 100644 --- a/meta/lib/oeqa/core/utils/test.py +++ b/meta/lib/oeqa/core/utils/test.py @@ -4,7 +4,6 @@ # SPDX-License-Identifier: MIT # -import os import inspect import unittest diff --git a/meta/lib/oeqa/sdk/testsdk.py b/meta/lib/oeqa/sdk/testsdk.py index ee25d682b95..8a6e46cd862 100644 --- a/meta/lib/oeqa/sdk/testsdk.py +++ b/meta/lib/oeqa/sdk/testsdk.py @@ -9,7 +9,6 @@ from oeqa.sdk.context import OESDKTestContext, OESDKTestContextExecutor class TestSDKBase: @staticmethod def get_sdk_configuration(d, test_type): - import platform import oe.lsb from oeqa.utils.metadata import get_layers configuration = {'TEST_TYPE': test_type, @@ -80,7 +79,6 @@ class TestSDK(TestSDKBase): def run(self, d): import os - import subprocess import json import logging diff --git a/meta/lib/oeqa/sdkext/testsdk.py b/meta/lib/oeqa/sdkext/testsdk.py index 40560fb47a4..16781644a41 100644 --- a/meta/lib/oeqa/sdkext/testsdk.py +++ b/meta/lib/oeqa/sdkext/testsdk.py @@ -14,7 +14,7 @@ class TestSDKExt(TestSDKBase): import logging from bb.utils import export_proxies - from oeqa.utils import avoid_paths_in_environ, make_logger_bitbake_compatible, subprocesstweak + from oeqa.utils import make_logger_bitbake_compatible, subprocesstweak from oeqa.sdkext.context import OESDKExtTestContext, OESDKExtTestContextExecutor from oeqa.utils import get_json_result_dir diff --git a/meta/lib/oeqa/selftest/cases/usergrouptests.py b/meta/lib/oeqa/selftest/cases/usergrouptests.py index 40e6e246068..2454fe880fe 100644 --- a/meta/lib/oeqa/selftest/cases/usergrouptests.py +++ b/meta/lib/oeqa/selftest/cases/usergrouptests.py @@ -7,7 +7,6 @@ import os import shutil from oeqa.selftest.case import OESelftestTestCase -from oeqa.utils.commands import bitbake from oeqa.utils.commands import bitbake, get_bb_var, get_test_layer class UserGroupTests(OESelftestTestCase): diff --git a/meta/lib/oeqa/selftest/context.py b/meta/lib/oeqa/selftest/context.py index eb38012eae3..1802454a0c0 100644 --- a/meta/lib/oeqa/selftest/context.py +++ b/meta/lib/oeqa/selftest/context.py @@ -6,12 +6,10 @@ import os import time -import glob import sys import importlib import subprocess import unittest -from random import choice import oeqa import oe @@ -373,7 +371,6 @@ class OESelftestTestContextExecutor(OETestContextExecutor): return json_result_dir def get_configuration(self, args): - import platform from oeqa.utils.metadata import metadata_from_bb metadata = metadata_from_bb() oeselftest_metadata = get_oeselftest_metadata(args) diff --git a/meta/lib/oeqa/utils/commands.py b/meta/lib/oeqa/utils/commands.py index f8d6a793550..cf2b7aa9418 100644 --- a/meta/lib/oeqa/utils/commands.py +++ b/meta/lib/oeqa/utils/commands.py @@ -16,7 +16,6 @@ import time import logging from oeqa.utils import CommandError from oeqa.utils import ftools -import re import contextlib import errno # Export test doesn't require bb diff --git a/meta/lib/oeqa/utils/ftools.py b/meta/lib/oeqa/utils/ftools.py index 3a10ae79d45..7f44648cca4 100644 --- a/meta/lib/oeqa/utils/ftools.py +++ b/meta/lib/oeqa/utils/ftools.py @@ -4,8 +4,6 @@ # SPDX-License-Identifier: MIT # -import os -import re import errno def write_file(path, data): diff --git a/meta/lib/oeqa/utils/httpserver.py b/meta/lib/oeqa/utils/httpserver.py index 9e61cd89d5a..cb43c00a29f 100644 --- a/meta/lib/oeqa/utils/httpserver.py +++ b/meta/lib/oeqa/utils/httpserver.py @@ -72,7 +72,7 @@ class HTTPService: self.logger.info("Stopped HTTPService on %s:%s" % (self.host, self.port)) if __name__ == "__main__": - import sys, logging + import sys logger = logging.getLogger(__name__) logging.basicConfig(level=logging.DEBUG) diff --git a/meta/lib/oeqa/utils/nfs.py b/meta/lib/oeqa/utils/nfs.py index 903469bfeec..db95c6a06ee 100644 --- a/meta/lib/oeqa/utils/nfs.py +++ b/meta/lib/oeqa/utils/nfs.py @@ -4,10 +4,8 @@ # SPDX-License-Identifier: MIT # import os -import sys import tempfile import contextlib -import socket from oeqa.utils.commands import bitbake, get_bb_var, Command from oeqa.utils.network import get_free_port diff --git a/meta/lib/oeqa/utils/postactions.py b/meta/lib/oeqa/utils/postactions.py index 2792c16bccf..892e9919454 100644 --- a/meta/lib/oeqa/utils/postactions.py +++ b/meta/lib/oeqa/utils/postactions.py @@ -8,10 +8,8 @@ # dictionary as well as test context to any action to run. import datetime -import io import os import stat -import subprocess import tempfile from oeqa.utils import get_artefact_dir diff --git a/meta/lib/oeqa/utils/qemurunner.py b/meta/lib/oeqa/utils/qemurunner.py index 0e27a977335..a0c8ab3575d 100644 --- a/meta/lib/oeqa/utils/qemurunner.py +++ b/meta/lib/oeqa/utils/qemurunner.py @@ -18,7 +18,6 @@ import select import errno import string import threading -import codecs import tempfile from collections import defaultdict from contextlib import contextmanager From patchwork Sun Nov 15 08:48:30 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104217 Received: from mail-wr1-f53.google.com (mail-wr1-f53.google.com [209.85.221.53]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.4388.1794732574726380627 for ; Sun, 15 Nov 2026 00:49:35 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=csqsNLB6; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.53, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f53.google.com with SMTP id ffacd0b85a97d-490585eddfcso1787787f8f.0 for ; Sun, 15 Nov 2026 00:49:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732573; x=1795337373; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=PBBqLks8pXq6n8gaq7ssFyajeLLxCEBX2aibZgKxoFk=; b=csqsNLB6jtu1LB24DErfT3ckB8olYefALA5RiIlYOZVbJJm9MJI+YuSuEch02BmZSu V1M3EylNXHwi7ui5B6PCrebsMCAK2yvt7RbO7m6DdwyrAfegiQt52LjGovWvF6EQChse HNPcJxZTOrKRSayIrFlPSO2VXXhLCZRh2HkZ8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732573; x=1795337373; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=PBBqLks8pXq6n8gaq7ssFyajeLLxCEBX2aibZgKxoFk=; b=GOI7hLyW8Rm4+Sg0M9t4qHy6mnrdpP756fL/Xgm+3dVlxRlRwW0A8DvDP+lGxA8Ci+ Jot7Mgun0mDVR0YVipckCo11I/0DzpthH5ZXXpxdDQDTYdlXIsbeWJovIcPK0MiB9uQn P0Yg+4jaIy+CV1EuTUYzDFHHzgubNEs8m0jOl4QJqMAXDxnrTUA0iT9VzT4+TpXokm5y XF04Tjbt4RTIX8XWNiXrmPNQ9rItxbGRzfL+0h/yZnd/01aEgS9gDozx3jEOxcd1Rv0V gHqxYxU356fC1zNxB2DYps1+aSs1C5suybWrCe+P1TgTcQUc7H5IAyAqsAlRei2o09jZ RHBw== X-Gm-Message-State: APuU4Z+gcL9zNKytd5NnezqLF7ZsavNlaFpGume2FPVOcX85Z1sF2Dcs StQQYSh+Q3DrZ54ik0WVozr25KFY7PNsGHdoHC7DtUn2rDPPJgDwaEC3FXVucsrJpP4rVZA4yrR jzO/QuxM= X-Gm-Gg: AYBFou3JVuqyT0IwH/x2I3KZ6z0Q4L5uLkb7/U+xFmEHTJ899QTSUdHFg9967XzVibB nbHKvkmJhpdPBiN+DRzOwFKohJZZ2RiAoAv0AIn7Q8AQQbNko4WU8F6RFqMSZPt1PQ8JZA7Qd+4 JlgTUe7ROmP2N1wQBjyhxlL1tnsr8vMFNh0sxG3sm2Wv5o+dSK2yKgqrtUi0k42Rbn5KAEfGtlQ F5nqN7lKukaglferFW3Z/oil9ggUufn1oa8yTy8eRCv4XP2pfI9znG3Y1lDkoyHfRfkFRe+3tYI elc5invC5oR6/ZP3fvrs/Sh4J8AnbXCTk4BvNDqMH0OdVXeLCPwugajGWtYcMChehvWB6i3de// z+svonKwCBi4zZrNsxKswlG9H+FpEIitD2IVkHVBnsFHvP5v+NHQjTdYtBN2bFGhQUIYxZ0Fsv3 WsQ4FwoMxxDv5HbM2YTdG3LKW6Z1rK3FD9IU0U78DWabSLJqdxzgos1KRvhkjcsMIVzUUOUIKOO ADT9MSbs0xEicHlZ73tSg0cUBOMJkrUIEZeZ+cNh3h9RnobFOnPeQPiTzFUUz03yZ4RkOjWGgtU yeofBFIZAtS+BYsunnOtpdLchDwx5DMIj/huV2RZ+C7gq576XNBP9Y0bTQ== X-Received: by 2002:a05:6000:2dc9:b0:48d:f460:2c62 with SMTP id ffacd0b85a97d-49c71785323mr17130102f8f.33.1794732572890; Sun, 15 Nov 2026 00:49:32 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.30 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:31 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 27/41] oeqa/core/decorator/depends: Check resolved dependency ids when running Date: Sun, 15 Nov 2026 08:48:30 +0000 Message-ID: <20261115084845.701136-27-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:43 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250258 OETestDepends allows dependencies to be given relative to the test's module or class and bind() resolves these to full test ids for ordering. The runtime check compared the dependencies as written with the ids of the passed tests though, so a test with a relative dependency was always skipped, e.g. test_example_depends in the core example tests. Use the resolved ids from the registry to avoid that. Add a test which runs tests with relative dependencies. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/core/decorator/depends.py | 2 +- meta/lib/oeqa/core/tests/test_decorators.py | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/meta/lib/oeqa/core/decorator/depends.py b/meta/lib/oeqa/core/decorator/depends.py index 41a324e61fb..abfb72a6152 100644 --- a/meta/lib/oeqa/core/decorator/depends.py +++ b/meta/lib/oeqa/core/decorator/depends.py @@ -95,4 +95,4 @@ class OETestDepends(OETestDiscover): return [registry['cases'][case_id] for case_id in registry['cases']] def setUpDecorator(self): - _skipTestDependency(self.case, self.depends) + _skipTestDependency(self.case, self.case.tc._registry['depends'][self.case.id()]) diff --git a/meta/lib/oeqa/core/tests/test_decorators.py b/meta/lib/oeqa/core/tests/test_decorators.py index 5095f39948d..2c668a9871d 100755 --- a/meta/lib/oeqa/core/tests/test_decorators.py +++ b/meta/lib/oeqa/core/tests/test_decorators.py @@ -112,6 +112,20 @@ class TestDependsDecorator(TestBase): msg = 'Expected OEQADependency exception having a circular dependency' self.assertTrue(result, msg=msg) + def test_depends_run(self): + # Dependencies given relative to the class must be found when the + # tests run, otherwise the dependent tests are skipped + tests = ['depends.DependsTest.testDependsFirst', + 'depends.DependsTest.testDependsSecond', + 'depends.DependsTest.testDependsThird', + 'depends.DependsTest.testDependsFourth', + 'depends.DependsTest.testDependsFifth'] + tc = self._testLoader(modules=self.modules, tests=tests) + result = tc.runTests() + self.assertTrue(result.wasSuccessful()) + self.assertEqual(result.skipped, []) + self.assertEqual(len(result.successes), len(tests)) + class TestTimeoutDecorator(TestBase): modules = ['timeout'] From patchwork Sun Nov 15 08:48:31 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104218 Received: from mail-wr1-f50.google.com (mail-wr1-f50.google.com [209.85.221.50]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.4389.1794732576939660914 for ; Sun, 15 Nov 2026 00:49:37 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=eamqf2W8; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.50, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f50.google.com with SMTP id ffacd0b85a97d-49465892f7bso2045636f8f.1 for ; Sun, 15 Nov 2026 00:49:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732575; x=1795337375; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=bf4P3f9Gzu3gYu2q1dNwCaXpaQVZ0gbtr7u6c7HhnI4=; b=eamqf2W8XQrdwMbtT9mbM+e0uQmTw3j9t5pLzrOKGNlZUNQJOceL70gXq3VpHO2BMF 4us22BHHB1Lcr4s6Psw/2loI8IGoBYGEHMtcDNc5YoGqruGG90VxDjI4yT8IXsjUWPBw uLdDb1ozwmpzPJMsIwZuaNo50UT0Y+f1vKE7A= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732575; x=1795337375; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=bf4P3f9Gzu3gYu2q1dNwCaXpaQVZ0gbtr7u6c7HhnI4=; b=IbH8U4MaVzX0nn62YybKinF2O2tYCOekPqcqJwLMq6VUTCf2jevwvmHSy6Da+LbyHg q365fuzI3tVGP4Bl/Hent5a4hwvcl7rn8365BseZ3BRZ4Bbx+VHqDw8ZmuDIX42zorNM n0NUlvHIFhQZjFQg6TqAn32GmB7ZVQnK7cxX8d8A5bVn0Cj9yfs/ZRulDwk4ERqARdJq Mxij2fq7F2bGvNgcsS8tiD6NTc7JD+c7wYOaywV0Ei43IdlpIQ2hi24iOzEA636pmeU7 SVKY9h5Z2LDx7FLuib9s7WabUdlc9hMuPq6oO+bHK8qKwLcIqFNoZFH0CFH7a0KMCwdz DccA== X-Gm-Message-State: APuU4Z89iNTYv00TSamt5euEZX/mvUHJvEsR9VtucBe1QFE+i0vWRw7+ sQjH6ucEecmkbBHhCRhQbGnf/1ISgYQaN+ahhaEr/0bHdqDQjOH3fJKOmMb7uIV3vJB3bEQzFXY k/GAxVo4= X-Gm-Gg: AYBFou1WUEswE5JKGiaM27sKEgbTN8t8w2V+82QdHuw40USrRPa/IYxW1T41vVpNp54 3OCxylwYuiP9AIou6DqPKXHVBNRAPnBrkg/jQwDeaBM459yQ8h8zSjvpQ8r14yDhXGP+yFyXGnm a93cHgXVjaAsEvHnhCzsRLGYI6IUHSxumFoz8xelD2qYHreu0QlYJK5T4he8+G5+J5Gqe+g1QZE Socnmi2jWM0jfKb7h1xmI/KiItk8TThqsQTre9p4YpCsbKLyryfatK7V9902/1kL5Sx+pa+1hWY qDtcN7hdP0NJM3Cj1vLHwq49DaYAi0TU7+TPfsalKk4SfWJ9XNFIECL2mh7LU5RTN9AzgJega2d xHhByOkB1XikIAYz7D5q5Jlvz8rWgedrR+py9uv8zbdu1bayMUVIu19LoZFVWdcSYShXzqd43yn uEqpyhAlKrIQz+CM23+0uKdgdREJRodTyX+eGC7GtTZqW5ewhOKZjHOK88p+kCRXyUkl9VC02tX 4QDz5hjsC5qTyXUFWTRTprwUGBNSItFclx1wtQ8XV+WnQJSx/EN/IyZ47TDL4KT/eTyGLnSSZdo MWjiSLTNwHnWhOWF9VBdunIwPdcZBoydK6uDAcmbeGWa6KsvUhFWlOct6g== X-Received: by 2002:a05:6000:2888:b0:493:d5f0:4e68 with SMTP id ffacd0b85a97d-49c72307130mr16960560f8f.36.1794732575067; Sun, 15 Nov 2026 00:49:35 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.33 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:34 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 28/41] oeqa/core/case: Tear down decorators if setUp() fails Date: Sun, 15 Nov 2026 08:48:31 +0000 Message-ID: <20261115084845.701136-28-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:43 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250259 unittest doesn't call tearDown() when setUp() raises, so if a test's own setUp() failed after the decorators were set up, they were never torn down. For OETimeout this left the alarm running so it could fire during a later test. Tear the decorators down in that case too and add a test. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/core/case.py | 4 +++- meta/lib/oeqa/core/tests/cases/timeout.py | 9 +++++++++ meta/lib/oeqa/core/tests/test_decorators.py | 9 +++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/meta/lib/oeqa/core/case.py b/meta/lib/oeqa/core/case.py index ad5524a7142..e71cab5028c 100644 --- a/meta/lib/oeqa/core/case.py +++ b/meta/lib/oeqa/core/case.py @@ -44,14 +44,16 @@ class OETestCase(unittest.TestCase): clss.tearDownClassMethod() def _oeSetUp(self): + # unittest doesn't call tearDown() if setUp() fails so the decorators + # need tearing down here in that case too try: for d in self.decorators: d.setUpDecorator() + self.setUpMethod() except: for d in self.decorators: d.tearDownDecorator() raise - self.setUpMethod() def _oeTearDown(self): for d in self.decorators: diff --git a/meta/lib/oeqa/core/tests/cases/timeout.py b/meta/lib/oeqa/core/tests/cases/timeout.py index 69cf969a67b..2d7229c18fd 100644 --- a/meta/lib/oeqa/core/tests/cases/timeout.py +++ b/meta/lib/oeqa/core/tests/cases/timeout.py @@ -32,3 +32,12 @@ class TimeoutTest(OETestCase): def testTimeoutUnrelated(self): sleep(6) + +class TimeoutSetUpFailTest(OETestCase): + + def setUp(self): + raise Exception("setUp failed") + + @OETimeout(10) + def testTimeoutSetUpFail(self): + self.assertTrue(True, msg='How is this possible?') diff --git a/meta/lib/oeqa/core/tests/test_decorators.py b/meta/lib/oeqa/core/tests/test_decorators.py index 2c668a9871d..d3305b1e534 100755 --- a/meta/lib/oeqa/core/tests/test_decorators.py +++ b/meta/lib/oeqa/core/tests/test_decorators.py @@ -147,6 +147,15 @@ class TestTimeoutDecorator(TestBase): msg = "OETestTimeout didn't restore SIGALRM" self.assertIs(alarm_signal, signal.getsignal(signal.SIGALRM), msg=msg) + def test_timeout_setup_fail(self): + tests = ['timeout.TimeoutSetUpFailTest.testTimeoutSetUpFail'] + alarm_signal = signal.getsignal(signal.SIGALRM) + tc = self._testLoader(modules=self.modules, tests=tests) + self.assertFalse(tc.runTests().wasSuccessful()) + # signal.alarm() returns the time left on any previous alarm + self.assertEqual(signal.alarm(0), 0, msg="OETestTimeout alarm left running after setUp failed") + self.assertIs(alarm_signal, signal.getsignal(signal.SIGALRM), msg="OETestTimeout didn't restore SIGALRM") + def test_timeout_cancel(self): tests = ['timeout.TimeoutTest.testTimeoutSkip', 'timeout.TimeoutTest.testTimeoutDepends', 'timeout.TimeoutTest.testTimeoutUnrelated'] msg = 'Unrelated test failed to complete' From patchwork Sun Nov 15 08:48:32 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104219 Received: from mail-wm1-f47.google.com (mail-wm1-f47.google.com [209.85.128.47]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4334.1794732577967770849 for ; Sun, 15 Nov 2026 00:49:38 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=KMmDIFUg; spf=pass (domain: linuxfoundation.org, ip: 209.85.128.47, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wm1-f47.google.com with SMTP id 5b1f17b1804b1-4b467581b98so18535755e9.0 for ; Sun, 15 Nov 2026 00:49:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732576; x=1795337376; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=Em4LeCNW9oSi+h+npeEyWWkD20+DJgqJ6mntdYL+G5Q=; b=KMmDIFUgh9DX7/mn2djXlfvZj0twg/prPl5tn6ErHRV58Q3sExemfLs0XWW1aLnoRD j90BYyil+qUm/wJZXtq2lJjcBUS+fLupTxlvRTnw784h7FWbClO/leqek0TbxRDjibqV aEFliwcacl6p6o6muQ8enwTkD/gXNuR9y5dOs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732576; x=1795337376; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=Em4LeCNW9oSi+h+npeEyWWkD20+DJgqJ6mntdYL+G5Q=; b=ikfg9Qx742ZV2VjSk4fdQBf4+vHcSrJx9hOD/gzq0LN/EYFnY3ezmUxkMSH+YQ+KLY T+HNfbgCtgLwDPRka4bgsak3zeO+SpfJxo/LvkHfqvO4nKRP7Zfv33QjFUpll4qxBoZh 5BmKl76XiJ9YVb49vKj6TvfuYrD9La9jOb9LOl+FJSr4rlI+M0jacXTL1etvnrXCu55E czz+VZIYoYUigU8woXMPMXh8ZXSvq5dIQ2+AGD15looz/quGkc3kCIboOC+fBo2dOhW+ Ic1R1gNeIE+i1mI39yIxQfrQT2PUWqK2MbZaPqq/byofHQ//PcLEfkGyBty0UBy5yu7K JhfA== X-Gm-Message-State: APuU4Z+eetOrjZ6jFeqev0YLNHGrUYtoBKnKqCM8Rug3J8MtDVj37d1L GeP+0LV/+TwLJ86HUGsZ30tjwdK3E301zJOGI2PgmaOqrOP3TdXnvsIJSK5+Vy38NfTaFIExHxh 9iq/RN88= X-Gm-Gg: AYBFou1hf8PYRvqVuQ9urZn4DdwGvcLiOfrVnCtDW/Ne/SZT6Gq+Aj1Vm/vP9GeH+Ho vgEP5cYOcxSuYnYduZK4Z1nCPUWha/2DzlNnxa2tX/tWUXOFW0j6GXOI8nRsDwhajEii3mxROSa BnHdzUGgM4nCiuAO0QP/1Y8xE0SprFQUPW0ps14KictsaHQ2lhBac04SjD4IIknK0B9Y7R0Xt2Q MVb3AkdL1EhpnbqbOERk8/mrH1GmAiiEZcytdhmIOPUK4nYpatfmPqzdYAz+XxWqJFRX8pfQSNH f7WvEy7g8vGFCLtcCuJeC21rwByBwAIGX8CIpi5u+8i9BYTpNfeON9vmE/Aqu16tWBHqf5TcR7q 4pSfexGFzLb0JpgR9fiPg/vcb7O4WQSSYazyUAgZC1Iy/eT4olEGUxGM4UW71GL8rOnifSCGEBG wkr7l8HWDArhnH1a5fuTUiRiTip34EmRtzh1pzeMuuDkCOFm/VY7UlYXohXlhfbbzdexY05U8b+ U7DWPI2+IvaqZ+lMOvug75Sk/GMdN2wHBIpEa8q08B1xp3iCtyabV6OkmnTxNmXEpABEoKtXxAZ Vai+30q2raZbQzlNAgPhQvIE0vJIT3o2kBpFzm3GIcSzcVZL4Zv6eSDfWA== X-Received: by 2002:a05:600c:3e10:b0:4bb:6651:9eda with SMTP id 5b1f17b1804b1-4bb6651a042mr60844295e9.14.1794732576100; Sun, 15 Nov 2026 00:49:36 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.35 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:35 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 29/41] oeqa/core/loader: Bind a copy of each decorator per test case Date: Sun, 15 Nov 2026 08:48:32 +0000 Message-ID: <20261115084845.701136-29-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:44 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250260 A decorator instance belongs to the decorated function, so when a test method is inherited by more than one test class the same instance was bound to each test case in turn and ended up referring to whichever case was bound last. Its setUpDecorator() then ran against the wrong case. Bind a copy for each test case instead and add a test. Also fix the unregistered decorator error, which used obj.__name__ on a decorator instance and so raised AttributeError instead. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/core/loader.py | 7 +++++-- meta/lib/oeqa/core/tests/cases/inherit.py | 20 ++++++++++++++++++++ meta/lib/oeqa/core/tests/test_decorators.py | 14 ++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 meta/lib/oeqa/core/tests/cases/inherit.py diff --git a/meta/lib/oeqa/core/loader.py b/meta/lib/oeqa/core/loader.py index 90b9366754d..28b4fd20166 100644 --- a/meta/lib/oeqa/core/loader.py +++ b/meta/lib/oeqa/core/loader.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: MIT # +import copy import re import sys import unittest @@ -106,8 +107,10 @@ class OETestLoader(unittest.TestLoader): if isinstance(obj, OETestDecorator): if not obj.__class__ in decoratorClasses: raise Exception("Decorator %s isn't registered" \ - " in decoratorClasses." % obj.__name__) - obj.bind(self.tc._registry, case) + " in decoratorClasses." % obj.__class__.__name__) + # The decorator instance is shared by every class that has + # the method so bind a copy for this test case + copy.copy(obj).bind(self.tc._registry, case) def _walk_closure(obj): if hasattr(obj, '__closure__') and obj.__closure__: diff --git a/meta/lib/oeqa/core/tests/cases/inherit.py b/meta/lib/oeqa/core/tests/cases/inherit.py new file mode 100644 index 00000000000..8600c8005b5 --- /dev/null +++ b/meta/lib/oeqa/core/tests/cases/inherit.py @@ -0,0 +1,20 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +from oeqa.core.case import OETestCase +from oeqa.core.decorator.depends import OETestDepends + +class InheritBaseTest(OETestCase): + + def testInheritFirst(self): + self.assertTrue(True, msg='How is this possible?') + + @OETestDepends(['testInheritFirst']) + def testInheritSecond(self): + self.assertTrue(True, msg='How is this possible?') + +class InheritSubTest(InheritBaseTest): + pass diff --git a/meta/lib/oeqa/core/tests/test_decorators.py b/meta/lib/oeqa/core/tests/test_decorators.py index d3305b1e534..74ac4632372 100755 --- a/meta/lib/oeqa/core/tests/test_decorators.py +++ b/meta/lib/oeqa/core/tests/test_decorators.py @@ -126,6 +126,20 @@ class TestDependsDecorator(TestBase): self.assertEqual(result.skipped, []) self.assertEqual(len(result.successes), len(tests)) +class TestInheritedDecorators(TestBase): + modules = ['inherit'] + + def test_inherited_decorators(self): + # Each test case needs its own decorator instances, even when the + # test method is inherited by another test class + tc = self._testLoader(modules=self.modules) + cases = tc._registry['cases'] + self.assertEqual(len(cases), 4) + for case in cases.values(): + for d in case.decorators: + self.assertIs(d.case, case) + self.assertTrue(tc.runTests().wasSuccessful()) + class TestTimeoutDecorator(TestBase): modules = ['timeout'] From patchwork Sun Nov 15 08:48:33 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104220 Received: from mail-wm1-f53.google.com (mail-wm1-f53.google.com [209.85.128.53]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4335.1794732579154568516 for ; Sun, 15 Nov 2026 00:49:39 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=BPhV2K1f; spf=pass (domain: linuxfoundation.org, ip: 209.85.128.53, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wm1-f53.google.com with SMTP id 5b1f17b1804b1-4bb5b8ef642so12444515e9.1 for ; Sun, 15 Nov 2026 00:49:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732577; x=1795337377; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=IYnurFPZO8lOfyrEZx6HUhkzrAkGA8RwTsGNgeoaDds=; b=BPhV2K1f+bSfiFIhPYfQDr5ytYYLGYNZqSl9HPRHMM0f4eqWAZmA7QRtWTj6D8GJ3y MHI7cLncMJxB0Sqfh2kDt8MeebAik7LFEem6aNCKxGtxq6eTlmc1vFYrka8nQw0AwrWr mnfv96PjfOhkKbEqkV2lRU0PgEgG9GHYoYRv0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732577; x=1795337377; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=IYnurFPZO8lOfyrEZx6HUhkzrAkGA8RwTsGNgeoaDds=; b=zI++h/69KVcglik0MQXNtDj6l3Mjl4yuby4KvLat5IJ+FEqnkxy7rRfi+XER6uw7Nb K2v5D1Z7uuDtj6QRMymfNutHUiomVY9KnoN/iv3JjOKIh4qofG6n7khBeB5vgdRwSkTQ XpUx+gtHHzn7qtqP4+TG/VZjpG7dfvuEpHdYiSZRmtnnUhYc6kiM9jdzcVyoXQTF6Ksj VI8YHQVnflZO19lubPIkjEZEDjwDklRemTvlLgP7Id4QQ9jjEXs4NdFIReCaR9x2pp+D jyhNg/gpB6ABTkHo50kDW7UsaPEo7yQBvgKI0F4lUXzNQht9Qk2+mbrnbGq19vDLT1c2 mrLA== X-Gm-Message-State: APuU4Z95p1HvBiYLgW5JtN5Alnw8ljjZspkefP5FxRo4THNjJTCVuMcI 0sVDxfQXbtUHDrTzvrWyg/pa4FTDW7eifki02M+JejQ0Qt/85Jv6i58D3fdP47/NJJuyFNy4o+Z uH/MwDkU= X-Gm-Gg: AYBFou1vaTg5bFdPgRdRnVkF4N/XYp1eRvXzefZkHZDuzZn80p/5BonGCuotFu2E9p2 8MFEmhNBepL+JmArGydd5hC+LOjOGoEf59UJ5TF02Vx97V4Xpznq0sDJGNpSk2MBVp2qjhev523 lL3TazY7Vz9nbaT6+x7KOxmZi6569bVBCwvLPvJway6LW7XaNrqVQC3zXyPLeumMtLjgZ81i7+g sewikYNxu6jspPuParCGpmyDIEX2fLWQvnzhSEmDvp8nvGEUiZwsRMHN374mHXG+wjFC2bbtLMV b7/eliME4EukBO9KSDZQi4QRQWqN9eZ3aQ2j7xAwl7Z0mhxZ5aH7nz/pdC0FbDePU8npPMjuHw7 Dk0lHnLh/wO3UHdY7ZxiCVSQl2WrlPuanRiCxYAzBNAl72eGoA5VToSjTGCdcfmFNNdfF/9StFg LFX5LYuC0GmqLOCyboCMTOSYMUdD3nXGSA9gWoB9/xqwLbnR1yn7KV+d73n5e0CSysYwBXXJzRt sAtm4OXGi2f8NOUx+RTMwXb6sIBMjHwehj7ao/iR1EIP2IK+cbmopQKn0YKRvZn5E4oMQ5CpqSG HA1oqm/L+EVkFXbvFJbO1TzvtBN3K03/H+6CwV1PNXJlTSqxf8llbmo+Ew== X-Received: by 2002:a05:600c:548e:b0:4bb:5c92:ce12 with SMTP id 5b1f17b1804b1-4bb5c92cedemr118169905e9.17.1794732577251; Sun, 15 Nov 2026 00:49:37 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.36 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:36 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 30/41] oeqa/core/runner: Report the status of tests with failing subtests Date: Sun, 15 Nov 2026 08:48:33 +0000 Message-ID: <20261115084845.701136-30-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:44 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250261 unittest records subtest failures against a subtest object rather than the test case, so the result lookups never matched them. Tests with failing subtests were reported as UNKNOWN in the results and their failure messages weren't shown as the test finished. Match subtests to their test case and add a test. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/core/runner.py | 9 +++++++-- meta/lib/oeqa/core/tests/cases/subtest.py | 19 +++++++++++++++++++ meta/lib/oeqa/core/tests/test_runner.py | 13 +++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 meta/lib/oeqa/core/tests/cases/subtest.py diff --git a/meta/lib/oeqa/core/runner.py b/meta/lib/oeqa/core/runner.py index 9164ee6bcca..a9b416f7cd7 100644 --- a/meta/lib/oeqa/core/runner.py +++ b/meta/lib/oeqa/core/runner.py @@ -15,6 +15,11 @@ import sys from unittest import TextTestResult as _TestResult from unittest import TextTestRunner as _TestRunner +def _case_id(case): + # Failures in subtests are recorded against a subtest object, use the + # id of the test case it belongs to + return getattr(case, 'test_case', case).id() + class OEStreamLogger: def __init__(self, logger): self.logger = logger @@ -73,7 +78,7 @@ class OETestResult(_TestResult): # to wait until selftest finishes to see them. for t in ['failures', 'errors', 'skipped', 'expectedFailures']: for (scase, msg) in getattr(self, t): - if test.id() == scase.id(): + if test.id() == _case_id(scase): self.tc.logger.info(str(msg)) self.shownmsg.append(test.id()) break @@ -109,7 +114,7 @@ class OETestResult(_TestResult): scase, msg = resultclass else: scase, msg = resultclass, None - if case.id() == scase.id(): + if case.id() == _case_id(scase): found = True break scase_str = str(scase.id()) diff --git a/meta/lib/oeqa/core/tests/cases/subtest.py b/meta/lib/oeqa/core/tests/cases/subtest.py new file mode 100644 index 00000000000..d24135f7c98 --- /dev/null +++ b/meta/lib/oeqa/core/tests/cases/subtest.py @@ -0,0 +1,19 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +from oeqa.core.case import OETestCase + +class SubTestTest(OETestCase): + + def testSubTestFail(self): + for i in range(2): + with self.subTest(i=i): + self.assertEqual(i, 0) + + def testSubTestPass(self): + for i in range(2): + with self.subTest(i=i): + self.assertTrue(True, msg='How is this possible?') diff --git a/meta/lib/oeqa/core/tests/test_runner.py b/meta/lib/oeqa/core/tests/test_runner.py index 205464cfae9..ce7be7b14e3 100755 --- a/meta/lib/oeqa/core/tests/test_runner.py +++ b/meta/lib/oeqa/core/tests/test_runner.py @@ -36,5 +36,18 @@ class TestRunner(TestBase): fp.close() +class TestResultStatus(TestBase): + def _statuses(self, modules): + tc = self._testLoader(modules=modules) + result = tc.runTests() + return {case_id: result._getTestResultDetails(case)[0] + for case_id, case in tc._registry['cases'].items()} + + def test_subtest_status(self): + self.assertEqual(self._statuses(['subtest']), { + 'subtest.SubTestTest.testSubTestFail': 'FAILED', + 'subtest.SubTestTest.testSubTestPass': 'PASSED', + }) + if __name__ == '__main__': unittest.main() From patchwork Sun Nov 15 08:48:34 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104221 Received: from mail-wr1-f50.google.com (mail-wr1-f50.google.com [209.85.221.50]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.4391.1794732581136279304 for ; Sun, 15 Nov 2026 00:49:41 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=EcnYYkZV; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.50, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f50.google.com with SMTP id ffacd0b85a97d-48e47347279so932772f8f.1 for ; Sun, 15 Nov 2026 00:49:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732579; x=1795337379; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=WEc00Cdh0QhWCDTYSFtHY98d7wGTGyajtlwtkeNudSI=; b=EcnYYkZVoAf0Um2LhWum8wTb4ctqzCCUuilRqZm6VI05FmM7Fd5ugN6k9sexp8uY+0 qTApufaDVAHrYEEzIKhUWeKLlfuiwrv+vPgV+0wgD3X6ePcXY4j9X6cL/TtBSnO0LiAn DHHqgj+HenlhqHMV6vPyWMD0MUJOXwtKT61Cc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732579; x=1795337379; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=WEc00Cdh0QhWCDTYSFtHY98d7wGTGyajtlwtkeNudSI=; b=law2YYBtwPWqrVQv4Jo4oIBDu65wWYfDvIQT06hDQDTC8hf/BRrwMut+3Mui+OMybH b7duAEZqsgNpG3Z50bKfCUnWwZoGMlY+7VchRG946arL6mm82qXnhdUbv3Mhu/3Bv2Oo uyt3xvXBVl1dSG/OsLDTysFzK9JWsDR5tThIdCFYRv7Ov/3T4AUTIWVNsbH0mijHC8cO KkCyFU/2QvU4IrA1ZwaGJSjfLKxvC9Y9qG8pk7zo4mBRNiQrBjuVzaSC9ZGAf+QCW4nE Wf2gRvJ6rMuSY9kLQkrkRcXrBK+BL/Hg3EbDLQG8FxQgtewhSIEkDa+ZcVqemZid4zRV gt1Q== X-Gm-Message-State: APuU4Z/7xyAmQVC7sdGwyGBbSKmmAUvpmFBIbvvasK/Wf7GG039rOmKH 75XzO14Dk6iGGbiDPpDkMDh7kuoOQKyHAszE2Ujhb2oh3tnqYf4dLOcqA8Jr8nPSx9p2IpGAyM2 qyDUurYU= X-Gm-Gg: AYBFou3Cex76UXhZhR1jAVdeedCAu58ScjJiu7KzgPdZMhh0dfursKpgf7Xz2Ya+ji+ W5WoAXhLvUYpBT+s+UNyZip7E5VvRsuq5dxpO1fSGzctnQgYaub1AnwT8w5rR5zW7l21eVrU2tb +ipeBChT3SrFbmDA7XkM4AT2UX4OQ/xXlwXfK4O/mBq0Z2AXJyrfKDQkMyIbWSZOXcO7syjKLsy qYZ/idWsPLlB+/FFTQglwR/0WXWpx3DxmQbJoirWxfpdxp7vO2VXLIX8WHY8aU5TT53QCSawtfF A1Trjmi2Anjao3a/8N6CZifD+GONrWZ1cnDGi6PQKGlTfEw4uMcP8aByN0MbZ4doDA48517tKUi 1xrS06+MR/S3YR8qjq7Zcd7jy6h2aWo43nI9WN3n2qD5RU+gPnMx11aLUgF/k9xnUQ9osm/FASq A75Hmxq59EkhUDbI6YMf4qUADoG8OTqtb1tzvWyfC5JEQoW6xeY5fgRYmQjNf8PQgdA1tzn0+nU 7EMLfAsXQaGpGErVICl/XKKlK/hWBGyiYnagaobwU+EINdLC5gzRDfMCvmY9+b1XS82LWE41GNg 4WmffQuZ8XOKekZDwmX3LtobL1RLnSAgbesTTU0Nrz58pCu3q3+EQ50Zng== X-Received: by 2002:a05:6000:2007:b0:491:7ab7:81a1 with SMTP id ffacd0b85a97d-49c72c9be63mr14642656f8f.46.1794732579363; Sun, 15 Nov 2026 00:49:39 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.37 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:38 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 31/41] oeqa/buildperf: Drop sortTestMethodsUsing from the test runner Date: Sun, 15 Nov 2026 08:48:34 +0000 Message-ID: <20261115084845.701136-31-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:44 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250262 Only test loaders use sortTestMethodsUsing so setting it on the runner has no effect; BuildPerfTestLoader already sets it. Also fix the runner's docstring. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/buildperf/base.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/meta/lib/oeqa/buildperf/base.py b/meta/lib/oeqa/buildperf/base.py index 6735e14fc8b..ce39bead31a 100644 --- a/meta/lib/oeqa/buildperf/base.py +++ b/meta/lib/oeqa/buildperf/base.py @@ -486,8 +486,7 @@ class BuildPerfTestLoader(unittest.TestLoader): class BuildPerfTestRunner(unittest.TextTestRunner): - """Test loader for build performance tests""" - sortTestMethodsUsing = None + """Test runner for build performance tests""" def __init__(self, out_dir, *args, **kwargs): super().__init__(*args, **kwargs) From patchwork Sun Nov 15 08:48:35 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104216 Received: from mail-wr1-f43.google.com (mail-wr1-f43.google.com [209.85.221.43]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.4392.1794732582541667277 for ; Sun, 15 Nov 2026 00:49:42 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=PK2Yige1; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.43, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f43.google.com with SMTP id ffacd0b85a97d-497614c95f0so1030116f8f.1 for ; Sun, 15 Nov 2026 00:49:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732581; x=1795337381; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=G+ds/RwkFf771kp7kv26RHNc3l0PJgggB/S5yCP9tDs=; b=PK2Yige1R0K5f7bVxmkg2rVoI+L95Yyo278J36AHy/se40Qo3AnMRR69TE3VTfN9nz nKY962Q9AJGwEyIqgpgNoFqzmXvbt1cGfmDLDCasj6c4ncnMMIl+wSn0tZX1SEaRhI5I JMq3n5XsiqFvRVZsHZ44yOiTt3B+cLkuvrB+4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732581; x=1795337381; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=G+ds/RwkFf771kp7kv26RHNc3l0PJgggB/S5yCP9tDs=; b=Qv4bLcZqgFea7jTbdOYC/sf2SlQbtKV7bGoUo87M669Z3AqTjq62/8EGnJz14FGf/R m5N/irxabguEu75rUWy3cGw6H0j2V1djPyt4URhWoKRxAGuK9S+QpBlcmsTpAqDX7mxA sEpm7YePC1RfNJznPavZ9EDNoyILiUakBiVEfh2gQkqwySwggdsNDmY4WDpwM+NyNEdL 3v0HP11C7p2SDuLChQjqFtxpHF6rC9KqJBLd8hy27YvcgF4ONgI6qg7NuqbW/TI3WCcA 2rwp4IQSJkBkYoKGNQyiW+K3bC7U7kz8u1Y1lymeSokroDp0oHX8HbmcIz5ADLHl+J08 bG7A== X-Gm-Message-State: APuU4Z8hge34CugjS4jVwuu8HUt41VRnHluiEy/Uplfd7ulBdGFFvHLP Fc9ypItOSbemj07P++UTiNLj3PSEADphHN3ERzTWU60/b6FxSxZXs9eqicZL9PwflpztDS1rPEy SBEM5S2w= X-Gm-Gg: AYBFou0ZM3asDWF7fI3JRvXhw3M5KmSS8TIfzoIEChit1h2QQg9lGe9R7Tp5RRm8DFd K5f4cy8t8rCZaWwfweZmNsx9aUOuC9fPiSz/4Vod5vtXVpo8nJ3c0EWgt7yaDoWmsOC98amjKTD ihOfAUnfKawc2xoNy6l82NWvuAUv+DVnQrtGHfD61MCdlBTY17wyqe/rI18YlpogN5q17/B7r0d +xp0bH1aIjURJMPHKiet4cClviCnWsuLrs6aWvKzXUGuuG5LWSfzEMijNBQtD37hS7PnPsfeIbn o9wEDbnfMK40tobeCxgzZH+UMo+Co+FPGVetFjuR68eyc9rcwHmEbyt04CLgRWgo1Hc2DJZZNhM lSLNKv3ERSrjnHhTAnngSYiVNfbenzGQDmuBZ8pVmfaqquvRkmlHWoirKzrRVxOo6mwZUgNL4VU wgfJJmYsAmvCiRwRKRgK7nZxsg4YO4UtRsNQ/D1x2k/UH59COoWVMQBlHjw6UxoNVODAwDhZzB5 waxk6ByTkHtl1St3S7i0bu0WtHWbD6xT8m0/HkI0RgWNRNuSr4DtVM6Uq9wGWHz38BBM5jghDb4 hAOz78OU6yNAjNFLz88hMpUGK+dN/9D0J1TbNTvlhT5o2UMdFKzNReOTkxbqwadKVDb9LbGg8Zd OSpY= X-Received: by 2002:a05:6000:161d:b0:48d:b940:af7a with SMTP id ffacd0b85a97d-49c74d2daa2mr11192729f8f.55.1794732580733; Sun, 15 Nov 2026 00:49:40 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.39 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:39 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 32/41] oeqa/core/tests: Add tests for the reported test result status Date: Sun, 15 Nov 2026 08:48:35 +0000 Message-ID: <20261115084845.701136-32-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:43 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250263 Check the status OETestResult reports for each kind of test outcome, including setUpClass and setUpModule errors and skips, ahead of reworking how results are tracked. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/core/tests/cases/results.py | 49 +++++++++++++++++++ .../oeqa/core/tests/cases/resultsmodule.py | 15 ++++++ meta/lib/oeqa/core/tests/test_runner.py | 13 +++++ 3 files changed, 77 insertions(+) create mode 100644 meta/lib/oeqa/core/tests/cases/results.py create mode 100644 meta/lib/oeqa/core/tests/cases/resultsmodule.py diff --git a/meta/lib/oeqa/core/tests/cases/results.py b/meta/lib/oeqa/core/tests/cases/results.py new file mode 100644 index 00000000000..363f3cd85fb --- /dev/null +++ b/meta/lib/oeqa/core/tests/cases/results.py @@ -0,0 +1,49 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +import unittest + +from oeqa.core.case import OETestCase + +class ResultsTest(OETestCase): + + def testPass(self): + pass + + def testFail(self): + self.fail("Failed on purpose") + + def testError(self): + raise Exception("Error on purpose") + + def testSkip(self): + self.skipTest("Skipped on purpose") + + @unittest.expectedFailure + def testExpectedFailure(self): + self.fail("Failed on purpose") + + @unittest.expectedFailure + def testUnexpectedSuccess(self): + pass + +class ResultsClassErrorTest(OETestCase): + + @classmethod + def setUpClass(cls): + raise Exception("Error on purpose") + + def testClassError(self): + pass + +class ResultsClassSkipTest(OETestCase): + + @classmethod + def setUpClass(cls): + raise unittest.SkipTest("Skipped on purpose") + + def testClassSkip(self): + pass diff --git a/meta/lib/oeqa/core/tests/cases/resultsmodule.py b/meta/lib/oeqa/core/tests/cases/resultsmodule.py new file mode 100644 index 00000000000..7579e86b934 --- /dev/null +++ b/meta/lib/oeqa/core/tests/cases/resultsmodule.py @@ -0,0 +1,15 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +from oeqa.core.case import OETestCase + +def setUpModule(): + raise Exception("Error on purpose") + +class ResultsModuleTest(OETestCase): + + def testModuleError(self): + pass diff --git a/meta/lib/oeqa/core/tests/test_runner.py b/meta/lib/oeqa/core/tests/test_runner.py index ce7be7b14e3..a9aac5ddf66 100755 --- a/meta/lib/oeqa/core/tests/test_runner.py +++ b/meta/lib/oeqa/core/tests/test_runner.py @@ -43,6 +43,19 @@ class TestResultStatus(TestBase): return {case_id: result._getTestResultDetails(case)[0] for case_id, case in tc._registry['cases'].items()} + def test_result_status(self): + self.assertEqual(self._statuses(['results', 'resultsmodule']), { + 'results.ResultsTest.testPass': 'PASSED', + 'results.ResultsTest.testFail': 'FAILED', + 'results.ResultsTest.testError': 'ERROR', + 'results.ResultsTest.testSkip': 'SKIPPED', + 'results.ResultsTest.testExpectedFailure': 'EXPECTEDFAIL', + 'results.ResultsTest.testUnexpectedSuccess': 'PASSED', + 'results.ResultsClassErrorTest.testClassError': 'ERROR', + 'results.ResultsClassSkipTest.testClassSkip': 'SKIPPED', + 'resultsmodule.ResultsModuleTest.testModuleError': 'ERROR', + }) + def test_subtest_status(self): self.assertEqual(self._statuses(['subtest']), { 'subtest.SubTestTest.testSubTestFail': 'FAILED', From patchwork Sun Nov 15 08:48:36 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104223 Received: from mail-wr1-f47.google.com (mail-wr1-f47.google.com [209.85.221.47]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.4393.1794732584331875744 for ; Sun, 15 Nov 2026 00:49:44 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=PdCyS7aJ; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.47, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f47.google.com with SMTP id ffacd0b85a97d-498f5fa5103so960331f8f.2 for ; Sun, 15 Nov 2026 00:49:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732582; x=1795337382; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=0pNW/+qDSc+Pmwe0vGJ5r/khKdDAaMqjvLKP8uQlJJE=; b=PdCyS7aJpL4cxIBw7ibDa1TqIvTg5CM6VpA1Qq2apBUx/xzW1DMAVOHrTTrc2pQBhX keHetAo8HjKlodDh1Errjfyggjq8vs/OoPJVrXCeFvFV+b5MDQ1fZF25nTXuMG2H1ZvL wvbuw0qjL6zVBE4PXlp6eomOH+ODi/7tNJ0+o= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732582; x=1795337382; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=0pNW/+qDSc+Pmwe0vGJ5r/khKdDAaMqjvLKP8uQlJJE=; b=Wmxcz2N4ew9oibXT5dxwdcbR1m2RBmjrT0TBnf/s0umPa2V/7oM5vzXzJPUcg78WFU 5c1wIwwPqwzadrErIrQcM4BEtL1rc5bzcFKK2oWUYAkdSs0u7yZnVxvdMNX5IyQSREa+ g+hpvnxGxmyx0q0Di4AdL49O3nmgoU605yh1kc4pgjd5d5DyZJKznJKkjGfj3+POO9Uw oAroKI+NtZ0rarlefOg+DXhEGtMnuFDJZWsC7yEq+ECNgoJKwGQGCyH6tqHYGEyI8UUM xHMHiunUHmuzkNuFWJNCEoBn8mP0JwUYUNQfI6vheSiZ0Av5BgkZic8cK5QVwrQD4vAt 8dJg== X-Gm-Message-State: APuU4Z9peK/7tkyz4DKD85eYMxLXjw0cvtrlUnOtuL2TADiqw65lr6q7 X8qfg6AL2MkutZwRzS6i6HNFnc3ECRfvrS712wuAOtptRInPfE7cbAzXra9eb12kyxY15CrYRhN 7vGUIQiQ= X-Gm-Gg: AYBFou3QrfzY24MU0JgQtct3+ylUXVwjvDbmHWM5p2Sl4ebdakreMZ7+S0TIDAfs+57 aU2Kj7X4/ST7LcGKZSFUFP8uKtK5y+3xoNJAFNpHOW2zahoJXpWU9yNbUnsWggllQmS5y6V0vTt X3VT1R/254xJNuH9zD+kbb6IR5AzOdwPRiVMm/fkcHrWjcMfHFbehqgdHl2lAqKxBVT6HfPczTF wfXGdVva443wFCPLvw04WleI0xoNDwq09YeSIZXAgAucsEACgMTEDJD5NoN+b4zxqYO38QnazFX SQ/+PmD4FTYpg2R/AVYW9+ehkfc6R/8xHjc1ymCrYleKYIVXDXPfi3ud8lJLAFh8fxqzbOR0NCT HG+UMsqMU+0rHmz9nBinRe5wwD2eusOjc7xmPt3riJXtcLMrPVr3gr975zTZzZ0bs1+sTUwVjmu /1MXWQnB4S87MIHx/kbkql2jc2HkCjnDB1qtGsRI17bOqdpEnW/d/xql7ImbZWO/qBTdora+3Z6 lyGHl14jSfwfZYAURwOIrigZPT6vkrwgb+UpO1MIDUbuQujGRP15U5s4vE7oEZ+a/ipBCdvdc6E KEA5w+5FtwqEVZYnTUuKV07VYNBXuYSNQ1Z1GIVmLosakCRAYK4/bv2OLA== X-Received: by 2002:a05:6000:4803:b0:49c:192f:cf20 with SMTP id ffacd0b85a97d-49c6dbffed9mr14525022f8f.6.1794732582434; Sun, 15 Nov 2026 00:49:42 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.40 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:41 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 33/41] oeqa/core/runner: Track test results as they are added Date: Sun, 15 Nov 2026 08:48:36 +0000 Message-ID: <20261115084845.701136-33-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:54 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250264 The status of each test was worked out by searching every unittest result list, matching setUpClass/setUpModule failures with regular expressions, once per test when writing the results. After every test, stopTest() also searched all the failure, error and skip lists to show its messages. Both grow with the square of the number of tests which adds up for large selftest runs. Record each result against its test, or against the class or module for setup failures, when it is added, and use that for both. If a test has more than one result, e.g. from subtests, the same precedence as before is used. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/core/runner.py | 107 +++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 50 deletions(-) diff --git a/meta/lib/oeqa/core/runner.py b/meta/lib/oeqa/core/runner.py index a9b416f7cd7..f68203baa3b 100644 --- a/meta/lib/oeqa/core/runner.py +++ b/meta/lib/oeqa/core/runner.py @@ -20,6 +20,10 @@ def _case_id(case): # id of the test case it belongs to return getattr(case, 'test_case', case).id() +# setUpClass/setUpModule failures are reported against a placeholder whose id +# names the class or module +_setup_failure_re = re.compile(r"^(?:setUpModule|setUpClass) \((?P.*)\)") + class OEStreamLogger: def __init__(self, logger): self.logger = logger @@ -41,6 +45,10 @@ class OEStreamLogger: handler.flush() class OETestResult(_TestResult): + # If a test has several results, e.g. from subtests, the status reported + # is the first of these which it has + status_priority = ('FAILED', 'ERROR', 'SKIPPED', 'EXPECTEDFAIL', 'PASSED') + def __init__(self, tc, *args, **kwargs): super().__init__(*args, **kwargs) @@ -49,7 +57,12 @@ class OETestResult(_TestResult): self.endtime = {} self.progressinfo = {} self.extraresults = {} - self.shownmsg = [] + self.shownmsg = set() + + # (status, message) results for each test id, and for setUpClass and + # setUpModule failures by class or module name + self.test_results = {} + self.setup_results = {} # Inject into tc so that TestDepends decorator can see results tc.results = self @@ -76,12 +89,10 @@ class OETestResult(_TestResult): # Print the errors/failures early to aid/speed debugging, its a pain # to wait until selftest finishes to see them. - for t in ['failures', 'errors', 'skipped', 'expectedFailures']: - for (scase, msg) in getattr(self, t): - if test.id() == _case_id(scase): - self.tc.logger.info(str(msg)) - self.shownmsg.append(test.id()) - break + for status, msg in self.test_results.get(test.id(), []): + if status != 'PASSED' and msg: + self.tc.logger.info(str(msg)) + self.shownmsg.add(test.id()) # Python 3.12 added this, stub it out for now def addDuration(self, test, elapsed): @@ -101,45 +112,23 @@ class OETestResult(_TestResult): msg += " (successes=%d, skipped=%d, failures=%d, errors=%d)" % (len(self.successes), len(self.skipped), len(self.failures), len(self.errors)) self.tc.logger.info(msg) + def _addResult(self, test, status, msg=None): + m = _setup_failure_re.match(str(test.id())) + if m: + self.setup_results.setdefault(m.group('name'), []).append((status, msg)) + else: + self.test_results.setdefault(_case_id(test), []).append((status, msg)) + def _getTestResultDetails(self, case): - result_types = {'failures': 'FAILED', 'errors': 'ERROR', 'skipped': 'SKIPPED', - 'expectedFailures': 'EXPECTEDFAIL', 'successes': 'PASSED', - 'unexpectedSuccesses' : 'PASSED'} - - for rtype in result_types: - found = False - for resultclass in getattr(self, rtype): - # unexpectedSuccesses are just lists, not lists of tuples - if isinstance(resultclass, tuple): - scase, msg = resultclass - else: - scase, msg = resultclass, None - if case.id() == _case_id(scase): - found = True - break - scase_str = str(scase.id()) - - # When fails at module or class level the class name is passed as string - # so figure out to see if match - m = re.search(r"^setUpModule \((?P.*)\).*$", scase_str) - if m: - if case.__class__.__module__ == m.group('module_name'): - found = True - break - - m = re.search(r"^setUpClass \((?P.*)\).*$", scase_str) - if m: - class_name = "%s.%s" % (case.__class__.__module__, - case.__class__.__name__) - - if class_name == m.group('class_name'): - found = True - break - - if found: - return result_types[rtype], msg - - return 'UNKNOWN', None + results = self.test_results.get(case.id()) + if not results: + # The test didn't run, look for a class or module setup failure + cls = case.__class__ + results = self.setup_results.get("%s.%s" % (cls.__module__, cls.__name__)) or \ + self.setup_results.get(cls.__module__) + if not results: + return 'UNKNOWN', None + return min(results, key=lambda r: self.status_priority.index(r[0])) def extractExtraResults(self, test, details = None): extraresults = None @@ -158,25 +147,43 @@ class OETestResult(_TestResult): def addError(self, test, *args, details = None): self.extractExtraResults(test, details = details) - return super().addError(test, *args) + super().addError(test, *args) + self._addResult(test, 'ERROR', self.errors[-1][1]) def addFailure(self, test, *args, details = None): self.extractExtraResults(test, details = details) - return super().addFailure(test, *args) + super().addFailure(test, *args) + self._addResult(test, 'FAILED', self.failures[-1][1]) + + def addSubTest(self, test, subtest, err): + super().addSubTest(test, subtest, err) + if err is not None: + if issubclass(err[0], test.failureException): + self._addResult(test, 'FAILED', self.failures[-1][1]) + else: + self._addResult(test, 'ERROR', self.errors[-1][1]) + + # No details argument, so testtools passes the reason + def addSkip(self, test, reason): + super().addSkip(test, reason) + self._addResult(test, 'SKIPPED', reason) def addSuccess(self, test, details = None): #Added so we can keep track of successes too self.successes.append((test, None)) self.extractExtraResults(test, details = details) - return super().addSuccess(test) + super().addSuccess(test) + self._addResult(test, 'PASSED') def addExpectedFailure(self, test, *args, details = None): self.extractExtraResults(test, details = details) - return super().addExpectedFailure(test, *args) + super().addExpectedFailure(test, *args) + self._addResult(test, 'EXPECTEDFAIL', self.expectedFailures[-1][1]) def addUnexpectedSuccess(self, test, details = None): self.extractExtraResults(test, details = details) - return super().addUnexpectedSuccess(test) + super().addUnexpectedSuccess(test) + self._addResult(test, 'PASSED') def logDetails(self, json_file_dir=None, configuration=None, result_id=None, dump_streams=False): From patchwork Sun Nov 15 08:48:37 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104224 Received: from mail-wm1-f46.google.com (mail-wm1-f46.google.com [209.85.128.46]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.4394.1794732585727613805 for ; Sun, 15 Nov 2026 00:49:46 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=AGKOgSHh; spf=pass (domain: linuxfoundation.org, ip: 209.85.128.46, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wm1-f46.google.com with SMTP id 5b1f17b1804b1-4a4d7ae1ae9so17942915e9.1 for ; Sun, 15 Nov 2026 00:49:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732584; x=1795337384; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=5qFFVAfX+YGZ0x6GNk4C3sSkdNWvacVUulR0jwfm5IE=; b=AGKOgSHhR5LgqUcQUg0+ra/f0jvq4JplvWUI84Jomkl0uKvrJPAPCYu8kl5/HFk+jL B6+3QCGTFCl5AzoksMo4DdPpB5H5HWg3/ASBCn1cIBZ74MW2CRgJq6cnR6SIvweU8v2D RaYwgMOnUZx5JknQ91DMCB6bYT6PZB8E+yjmQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732584; x=1795337384; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=5qFFVAfX+YGZ0x6GNk4C3sSkdNWvacVUulR0jwfm5IE=; b=ZMa6kyxRz0se1ZzNWtDjCoH8uF56Sh/HM7S68d3OgA/5+JL/EaCjH0/1IqY5VxEVgr 9C6voVLeANzfIqhz3oJ+I0f0YiiLorrfyChyMqymFFsKVwm0QyJEYOQQYFuFFufIWqrA sSFDCZxlOaKS64mdztw7BVh9Ua0ao5khnIXkWO0diCL5l0wNl77epuyPDE8YhnCByYKP 5G8PexYtR6FWaVJX8e6h8fytQb/iltCDC02btXblRrjVdv8Jewl9kvo3TSfhuBIR27da hJOGQv0TWeeTmdPrGaF9ZCV2d0UKhiWrBrBSKdeMWY8bOnPXuwqi818fAt9e583l11O+ k6zA== X-Gm-Message-State: APuU4Z9azUCYycEzk8CQCDo1oRgPgc6dPsEXqehOmqg6kbNar8nLG4JY 3XFAEOB4TP77ZAoYNu894QqZ86DBqD6Daa+8YWTUR8zprhuXVftpM2+C8nSlYtBTX5dhRMLaxcu /XjsGsdE= X-Gm-Gg: AYBFou0bVwUwSxDy1u13LWFXSjjGOyAAr31Eh+w9ge3XmVgJI762yJozZygioXbcHtH YX13mXhKD3dOyeRCRfO9Agfn1sD8sQGoo2YlY+WEGa4PTA8UwHdUwhXcSFcl4CvtxNPetfbof25 tPyXrNbZ/F4J92lh2iZ1OFvhMmBbzGaR5MeilDfTviQWjPWFQyfHRBC0sT163uaqw9xTm06lLEb YUXyLZLpytG9Zfo8ZS+roecwZxnUFkHmWjiX1jcpS3GwNGwJpmOY4WP0Fm2CP/RAlocyFBdwqXO kFMsGYb3kqG4vwRxWz95q4JeRuaS/coDlVjFl9rdmB5zPmQUjUcPXCZ/HvjvJXL4bEr5S9aBX8g 3/9AciAJZnxtsxffKUtVfBAhSsk+i5gReiJBwrJszINyLOuvp/PJnS5BefcjFl5UwSzqy4b0jLG 6IKdQgt8b1SEFn9VV6dBybghKzGdY27EfTlqo1a9s3zv9SPXxDQvQxoUTYVNIFF+rwgsmS/BbEv /Pz0ZoAbT94O3J7hM/wyIjy7IdFToGh88w3jv1/kHPX9nLxfHKdTO8WoFoOPMe98++PWjMoFumy lSlLFKujMMDtcLZ2jkZk0/sglTxVliZ5SDnDe0H8xDI0QuYN1OTNsRZSUw== X-Received: by 2002:a05:600c:8b82:b0:4bb:6814:738c with SMTP id 5b1f17b1804b1-4bb6814762dmr67481465e9.22.1794732583952; Sun, 15 Nov 2026 00:49:43 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.42 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:42 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 34/41] oeqa/core/runner: Use getSuiteCases() to list tests Date: Sun, 15 Nov 2026 08:48:37 +0000 Message-ID: <20261115084845.701136-34-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:54 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250265 The test listing code had its own recursive walk over the suite, and a counter stored on the runner, to do what getSuiteCases() already does. Use getSuiteCases() instead. The output is unchanged. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/core/runner.py | 79 +++++++++++++----------------------- 1 file changed, 28 insertions(+), 51 deletions(-) diff --git a/meta/lib/oeqa/core/runner.py b/meta/lib/oeqa/core/runner.py index f68203baa3b..6de9d865f4c 100644 --- a/meta/lib/oeqa/core/runner.py +++ b/meta/lib/oeqa/core/runner.py @@ -6,7 +6,6 @@ import os import time -import unittest import logging import re import json @@ -15,6 +14,8 @@ import sys from unittest import TextTestResult as _TestResult from unittest import TextTestRunner as _TestRunner +from oeqa.core.utils.test import getSuiteCases + def _case_id(case): # Failures in subtests are recorded against a subtest object, use the # id of the test case it belongs to @@ -272,68 +273,44 @@ class OETestRunner(_TestRunner): return self.resultclass(self.tc, self.stream, self.descriptions, self.verbosity) - def _walk_suite(self, suite, func): - for obj in suite: - if isinstance(obj, unittest.suite.TestSuite): - if len(obj._tests): - self._walk_suite(obj, func) - elif isinstance(obj, unittest.case.TestCase): - func(self.tc.logger, obj) - self._walked_cases = self._walked_cases + 1 - def _list_tests_name(self, suite): - self._walked_cases = 0 - - def _list_cases(logger, case): - oetags = [] - if hasattr(case, '__oeqa_testtags'): - oetags = getattr(case, '__oeqa_testtags') - if oetags: - logger.info("%s (%s)" % (case.id(), ",".join(oetags))) - else: - logger.info("%s" % (case.id())) + cases = getSuiteCases(suite) self.tc.logger.info("Listing all available tests:") - self._walked_cases = 0 self.tc.logger.info("test (tags)") self.tc.logger.info("-" * 80) - self._walk_suite(suite, _list_cases) + for case in cases: + oetags = getattr(case, '__oeqa_testtags', None) + if oetags: + self.tc.logger.info("%s (%s)" % (case.id(), ",".join(oetags))) + else: + self.tc.logger.info("%s" % (case.id())) self.tc.logger.info("-" * 80) - self.tc.logger.info("Total found:\t%s" % self._walked_cases) + self.tc.logger.info("Total found:\t%s" % len(cases)) def _list_tests_class(self, suite): - self._walked_cases = 0 - - curr = {} - def _list_classes(logger, case): - if not 'module' in curr or curr['module'] != case.__module__: - curr['module'] = case.__module__ - logger.info(curr['module']) - - if not 'class' in curr or curr['class'] != \ - case.__class__.__name__: - curr['class'] = case.__class__.__name__ - logger.info(" -- %s" % curr['class']) - - logger.info(" -- -- %s" % case._testMethodName) - self.tc.logger.info("Listing all available test classes:") - self._walk_suite(suite, _list_classes) + module = cls = None + for case in getSuiteCases(suite): + if case.__module__ != module: + module = case.__module__ + self.tc.logger.info(module) + if case.__class__.__name__ != cls: + cls = case.__class__.__name__ + self.tc.logger.info(" -- %s" % cls) + self.tc.logger.info(" -- -- %s" % case._testMethodName) def _list_tests_module(self, suite): - self._walked_cases = 0 - - listed = [] - def _list_modules(logger, case): - if not case.__module__ in listed: - if case.__module__.startswith('_'): - logger.info("%s (hidden)" % case.__module__) - else: - logger.info(case.__module__) - listed.append(case.__module__) - self.tc.logger.info("Listing all available test modules:") - self._walk_suite(suite, _list_modules) + listed = set() + for case in getSuiteCases(suite): + module = case.__module__ + if module not in listed: + if module.startswith('_'): + self.tc.logger.info("%s (hidden)" % module) + else: + self.tc.logger.info(module) + listed.add(module) def list_tests(self, suite, display_type): if display_type == 'name': From patchwork Sun Nov 15 08:48:38 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104225 Received: from mail-wm1-f48.google.com (mail-wm1-f48.google.com [209.85.128.48]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4336.1794732586747354083 for ; Sun, 15 Nov 2026 00:49:47 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=D838kozy; spf=pass (domain: linuxfoundation.org, ip: 209.85.128.48, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wm1-f48.google.com with SMTP id 5b1f17b1804b1-4bb6886d30aso4423305e9.3 for ; Sun, 15 Nov 2026 00:49:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732585; x=1795337385; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=WHNmUCXfoovc28pQN+AdXsrZdjWqMte+sUiDKFRfbOU=; b=D838kozynsyneyBbHGcJixMhoyYelbRKVtYKCMgb6YgtoRjM2kPUxB/nmwLOu5ddfV CnC7yVMxesmX6iEkNh0OwclkNUCLLWaM1SvRdbmU+1qWdqOz+v40TC1HH0pG/MmTGB8t 97C9jI9JeR7MDPLRbhgUqc09Wr2uUMpiJogwQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732585; x=1795337385; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=WHNmUCXfoovc28pQN+AdXsrZdjWqMte+sUiDKFRfbOU=; b=sJ51t+uZB7jMRxRZ1zRDjyKNAtca/8WOIhUEI4l92Qm1r8Kv9X8jMljb3TmTjBqvww 9qq6GyJsTQjpS+7hFEZECntgXvaGZKUIVtvR0wejnVVTIB47gX+EBojQ6IRHOLOSRNvX z5m/jIKAqngJfWL5BxxGsNDtvIQzqRvV8/6UHAl2ZAoPLIScIgtSpZDyUcjY5i5iAtg6 ZuG64keRQgxcLhTcOJo3NXgH+hKLnABQYnLnXwryx3vUJQQ9UqDSdQ0s/fjbrG6y7DrX uttx9fPnVQlEm0U17dTOyA1RB/VvJTp3yK+jqqejyN+o5nQZlR61Py5BmiOSkkj4zuSZ k9ug== X-Gm-Message-State: APuU4Z92KODITYzNp01qyurb1bmi3VO49UForVxOWyK8ho52NJrizPRs Aq0oo3+0bKnZ7UWO4PohCr4sBr4I857TpYJhnXiSzfRj/2iN55mIIdeAqNN6/LNrwEBgv9AxhXz 53DBS38Y= X-Gm-Gg: AYBFou0PYumNf4/VQlvPu02Z6GIeqMyHJ8cvi05K+KIHIlodtNvJwIMpSJ43Bf4X49W 6ZHtRVALhEcCoeb/qxvDW2qATlVqQNT04HQO+FKzQhVWc2q1WPr5XSvLgkeMhtFhJEiLSu1XT1k xAqjz4mE/iekHAJGQrxY3oiHr+p+TYLOIg+N3z2+4icOfHw4YPsQfpDw5M2yeRm90kbVulOTThe 7FUjDaeBtpVmM09ue07GvQQOdccllWB4WDhLMSKvJHqKWSOwLYrER0exhlde5bqY/wPVwd6KYxs ykOdPQe0ZFtqUVUjMBELte7x6FJfQbDMFafuuUVvGjWH1YhAq6kNRQAO3AtqyvBiQtn8SreieZZ XBIFtCmDOsFa4iHITeqktD/Pg6Bm4t6KnArjfca7j7dxIDdtibK1I5pNAP7FtqtlbdXKwhubGKT Bd9KyA1M2AE2N9MvB2+ISPsiGvHl2bgl8YVxDl2/l8sHOm8DO6ptaAJl9JdNpkZdzM7D9kZZfOz qUnuVcEPEtDOsVYG/bv3v3Y2lOtPHBxzrcxrPNcC6VK2s8RA+92f1ncjfLjCstGVdu6AV3V+W5A 0swoJ36R/1SOfrI2Ghx9TUAuQSUEpaifM7pKZ9V6yXXkn3F5ZjaAjQJIJUU= X-Received: by 2002:a05:600c:608e:b0:4ac:da92:2bd4 with SMTP id 5b1f17b1804b1-4bb55a238bemr140035435e9.1.1794732584927; Sun, 15 Nov 2026 00:49:44 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.44 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:44 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 35/41] oeqa/core/decorator: Record decorators on the test function Date: Sun, 15 Nov 2026 08:48:38 +0000 Message-ID: <20261115084845.701136-35-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:54 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250266 OETestDecorator wrapped each test method in a function which only called it, with a dummy assignment to self so the decorator would be captured in the wrapper's closure. OETestLoader then walked the closures to find the decorators. Instead, record the decorators in an attribute on the test function and return it unchanged. The order they are set up in is the same as before, innermost first, and a test now checks this. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/core/decorator/__init__.py | 10 ++++---- meta/lib/oeqa/core/loader.py | 26 +++++++-------------- meta/lib/oeqa/core/tests/test_decorators.py | 8 +++++++ 3 files changed, 20 insertions(+), 24 deletions(-) diff --git a/meta/lib/oeqa/core/decorator/__init__.py b/meta/lib/oeqa/core/decorator/__init__.py index 93efd30e1db..e3e1326873c 100644 --- a/meta/lib/oeqa/core/decorator/__init__.py +++ b/meta/lib/oeqa/core/decorator/__init__.py @@ -4,7 +4,6 @@ # SPDX-License-Identifier: MIT # -from functools import wraps from abc import ABCMeta decoratorClasses = set() @@ -29,11 +28,10 @@ class OETestDecorator(object, metaclass=ABCMeta): setattr(self, attr, value) def __call__(self, func): - @wraps(func) - def wrapped_f(*args, **kwargs): - self.attrs = self.attrs # XXX: Enables OETestLoader discover - return func(*args, **kwargs) - return wrapped_f + # Record the decorator on the test function for OETestLoader to find. + # They are set up in the order they are applied, innermost first. + func._oeqa_decorators = getattr(func, '_oeqa_decorators', []) + [self] + return func # OETestLoader call it when is loading test cases. # XXX: Most methods would change the registry for later diff --git a/meta/lib/oeqa/core/loader.py b/meta/lib/oeqa/core/loader.py index 28b4fd20166..94ade54506d 100644 --- a/meta/lib/oeqa/core/loader.py +++ b/meta/lib/oeqa/core/loader.py @@ -14,8 +14,7 @@ from oeqa.core.utils.test import getSuiteModules, getCaseID from oeqa.core.exception import OEQATestNotFound from oeqa.core.case import OETestCase -from oeqa.core.decorator import decoratorClasses, OETestDecorator, \ - OETestDiscover +from oeqa.core.decorator import decoratorClasses, OETestDiscover # When loading tests, the unittest framework stores any exceptions and # displays them only when the run method is called. @@ -103,23 +102,14 @@ class OETestLoader(unittest.TestLoader): self.tc._registry['cases'][case_id] = case def _handleTestCaseDecorators(self, case): - def _handle(obj): - if isinstance(obj, OETestDecorator): - if not obj.__class__ in decoratorClasses: - raise Exception("Decorator %s isn't registered" \ - " in decoratorClasses." % obj.__class__.__name__) - # The decorator instance is shared by every class that has - # the method so bind a copy for this test case - copy.copy(obj).bind(self.tc._registry, case) - - def _walk_closure(obj): - if hasattr(obj, '__closure__') and obj.__closure__: - for f in obj.__closure__: - obj = f.cell_contents - _handle(obj) - _walk_closure(obj) method = getattr(case, case._testMethodName, None) - _walk_closure(method) + for obj in getattr(method, '_oeqa_decorators', []): + if not obj.__class__ in decoratorClasses: + raise Exception("Decorator %s isn't registered" \ + " in decoratorClasses." % obj.__class__.__name__) + # The decorator instance is shared by every class that has + # the method so bind a copy for this test case + copy.copy(obj).bind(self.tc._registry, case) def _filterTest(self, case): """ diff --git a/meta/lib/oeqa/core/tests/test_decorators.py b/meta/lib/oeqa/core/tests/test_decorators.py index 74ac4632372..90ab1d3ff67 100755 --- a/meta/lib/oeqa/core/tests/test_decorators.py +++ b/meta/lib/oeqa/core/tests/test_decorators.py @@ -126,6 +126,14 @@ class TestDependsDecorator(TestBase): self.assertEqual(result.skipped, []) self.assertEqual(len(result.successes), len(tests)) +class TestDecoratorOrder(TestBase): + def test_decorator_order(self): + # Decorators are set up in the order they are applied, innermost first + tc = self._testLoader(modules=['timeout']) + case = tc._registry['cases']['timeout.TimeoutTest.testTimeoutDepends'] + self.assertEqual([d.__class__.__name__ for d in case.decorators], + ['OETimeout', 'OETestDepends']) + class TestInheritedDecorators(TestBase): modules = ['inherit'] From patchwork Sun Nov 15 08:48:39 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104226 Received: from mail-wr1-f41.google.com (mail-wr1-f41.google.com [209.85.221.41]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.4395.1794732590604514838 for ; Sun, 15 Nov 2026 00:49:50 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=iEiNUP2P; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.41, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f41.google.com with SMTP id ffacd0b85a97d-4919a880834so1131410f8f.0 for ; Sun, 15 Nov 2026 00:49:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732589; x=1795337389; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=wmLcBVUkMm6vSNtCN4x8U7mNWh31QOkztROT2aMVp/k=; b=iEiNUP2PHdwhqe9JqQFaBEg/GYaB8rIXZU1JArGJSNQyRLCOY1/xEWYbGlA27K+F1T vglUfNUca+kPXr5bcx7PWuGmTrbzCxtzFpHR/ayyUZ92Z5esluzqC7ezF+Q/uTqMeIhH KuRxNrSVXOATGZGMEZNIF3T4zA+1haTJuDUQE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732589; x=1795337389; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=wmLcBVUkMm6vSNtCN4x8U7mNWh31QOkztROT2aMVp/k=; b=SzOADL7s1aBkg5KOeNLwmMKbJlWktJORd3qw9l90i4M8RlV2e7cCxOebRCjyaTz+Vx s75p/TIE8W4V/0dQ/It3JGKE7Of+vKqAMacQDxS0gJE+rsk1nryZSWfx++WD0549oyfR uP5/xI5SMebCa8a1nV2uTkXotpUbrBjirLHQVElhDC5tPWgC5tb4uOjP0VaR/EeLMXOl OMjvPDTIpE2fvdf+04uuA9IoWY/4BL73RELIwP3foGhwF7B7o6o/kZCG5EVgSzbd1Tw7 AGp53+jiod9bK5Jfhkjkf32AUlqQ1DOXD660nAKB3Ihtloidg0b/aaIGV+Sh3ES7jvQZ hwsQ== X-Gm-Message-State: APuU4Z9rnOHoFTwP0r089EETc5DkvdeEy4kkAeHNt73Uk3o9lcFgjbCs j11Z5eQMApbLUMfqnlysvovtsOFtUOrhEozTDDYP00VKJr//XaBXvr2wHBPnqoMeI+ciHUPOZUw uKgzZ1ok= X-Gm-Gg: AYBFou3WLTmqdBDb0c0x1O+wwwS1PSKKEomzICmLjR1CbfEvWvf9q/DICstF37krF9i YFQYFaBh8zFRzpB5aDbo3V6VTE+R8UXBSUUSVKHUMPLHw+5ks/V9a0Ony499pMpH4Y82yj+57DE n4L64S0cwW4ccQt079d/Qp6rYYspymEkHncBN7A7xlyq5wr2BjkKAWul6iAPyUklR2WJOBB8CAQ 4PXGEEAhFqPoXAsQWOcZwH3x69rZQWG6nJVBlBJbitjiy5Zht4wwiMnWCK7RDpRTNvM/e178PMJ AbSACHaz1wTaKTgc5UEoVCRHfxkNoHQ0OnkpkziDg9G1uFbW4l000zJnMXzWafYOxnaloZ3TJ3v RjM/UQ/idtRhYjgaaE1ARTh/Vntv4BN9R52vp+kt4QrdPFx3/iHiZamJFIgVJRDJOvUSMpIjLux 0eQc8nd1AooKnYwvpzBZfi3EYUzEhM+TjISJhZkStp+jjPc5AM4NUcjcQV9zM2NQudJcXymbbcz ACsFKFI5mI0e+x2e11o4KSq72P+1FpQLpQnxoQVh6yh9lODLD0JSdjs5QXERixMs9RHTTCQCRAZ 1OXXYDWOem8z3eQINjtbSzfX9D6LTbwSAyee9Y+kDV+sjJdrMqN+1ZEcew== X-Received: by 2002:a05:6000:200a:b0:48f:bf71:2ad9 with SMTP id ffacd0b85a97d-49c727d1f2dmr17248226f8f.41.1794732588784; Sun, 15 Nov 2026 00:49:48 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.45 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:46 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 36/41] oeqa/core/tests: Add tests for skipping tests and td_vars checks Date: Sun, 15 Nov 2026 08:48:39 +0000 Message-ID: <20261115084845.701136-36-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:54 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250267 Check that tests and whole classes can be skipped by id and that a skipped class doesn't run its setUpClass(), and that a missing td_vars variable is reported, ahead of reworking how test setup is hooked. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/core/tests/cases/skips.py | 24 ++++++++++++++++++++++++ meta/lib/oeqa/core/tests/cases/tdvars.py | 13 +++++++++++++ meta/lib/oeqa/core/tests/test_runner.py | 21 +++++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 meta/lib/oeqa/core/tests/cases/skips.py create mode 100644 meta/lib/oeqa/core/tests/cases/tdvars.py diff --git a/meta/lib/oeqa/core/tests/cases/skips.py b/meta/lib/oeqa/core/tests/cases/skips.py new file mode 100644 index 00000000000..a24ee8d1c04 --- /dev/null +++ b/meta/lib/oeqa/core/tests/cases/skips.py @@ -0,0 +1,24 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +from oeqa.core.case import OETestCase + +class SkipsClassTest(OETestCase): + + @classmethod + def setUpClass(cls): + raise Exception("setUpClass of a skipped class shouldn't run") + + def testSkipsClass(self): + pass + +class SkipsTest(OETestCase): + + def testSkipsSkipped(self): + self.fail("Skipped test shouldn't run") + + def testSkipsRun(self): + pass diff --git a/meta/lib/oeqa/core/tests/cases/tdvars.py b/meta/lib/oeqa/core/tests/cases/tdvars.py new file mode 100644 index 00000000000..60313600754 --- /dev/null +++ b/meta/lib/oeqa/core/tests/cases/tdvars.py @@ -0,0 +1,13 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +from oeqa.core.case import OETestCase + +class TdVarsMissingTest(OETestCase): + td_vars = ['NOT_IN_TD'] + + def testTdVarsMissing(self): + pass diff --git a/meta/lib/oeqa/core/tests/test_runner.py b/meta/lib/oeqa/core/tests/test_runner.py index a9aac5ddf66..70107d1e25d 100755 --- a/meta/lib/oeqa/core/tests/test_runner.py +++ b/meta/lib/oeqa/core/tests/test_runner.py @@ -56,6 +56,27 @@ class TestResultStatus(TestBase): 'resultsmodule.ResultsModuleTest.testModuleError': 'ERROR', }) + def test_skip_tests(self): + # Tests and classes can be skipped by id prefix; a skipped class must + # not run its setUpClass() + tc = self._testLoader(modules=['skips']) + result = tc.runTests(skips=['skips.SkipsClassTest', 'skips.SkipsTest.testSkipsSkipped']) + statuses = {case_id: result._getTestResultDetails(case)[0] + for case_id, case in tc._registry['cases'].items()} + self.assertEqual(statuses, { + 'skips.SkipsClassTest.testSkipsClass': 'SKIPPED', + 'skips.SkipsTest.testSkipsSkipped': 'SKIPPED', + 'skips.SkipsTest.testSkipsRun': 'PASSED', + }) + + def test_td_vars(self): + tc = self._testLoader(modules=['tdvars']) + result = tc.runTests() + statuses = {case_id: result._getTestResultDetails(case)[0] + for case_id, case in tc._registry['cases'].items()} + self.assertEqual(statuses, {'tdvars.TdVarsMissingTest.testTdVarsMissing': 'ERROR'}) + self.assertIn("OEQAMissingVariable", result.errors[0][1]) + def test_subtest_status(self): self.assertEqual(self._statuses(['subtest']), { 'subtest.SubTestTest.testSubTestFail': 'FAILED', From patchwork Sun Nov 15 08:48:40 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104227 Received: from mail-wr1-f41.google.com (mail-wr1-f41.google.com [209.85.221.41]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.4396.1794732591685414621 for ; Sun, 15 Nov 2026 00:49:52 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=W4/7EK9K; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.41, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f41.google.com with SMTP id ffacd0b85a97d-490a0e72588so1022852f8f.3 for ; Sun, 15 Nov 2026 00:49:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732590; x=1795337390; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=0upI0JkeOtdlV3/K9FWBma6qnIg4K4SSiqU5bydGtmo=; b=W4/7EK9KNV7pi5rd5iChDZDbFvTqVoMpAmUQ7Wa4ivsRbvesL0M68VYLenXrxPCL0a VV+1ZL8RmcuqzjO6U2fWR09H1txuY8HsrvRQKzrSJdmiCqfRL+qM4ust542/cUWXPGIh CV3+OiukoEhHWoOYAnOIV84e8TAHrQDSHDJeM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732590; x=1795337390; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=0upI0JkeOtdlV3/K9FWBma6qnIg4K4SSiqU5bydGtmo=; b=kVyIDBl8JOrmX7tL8LbjTTGgz30CXXHI8wLo9rVVzXlfq1zrSLH5e1nUfJf5PMxkdu bp3KLeVjq5I2zPIE2ecqEQGYeGD6n3TM+CFwQcgrto7sG1IN7zIj5YKIOePWG6rEh860 vd6xn3/8u9F1dfhr1L+SGQUwFzCaSqMT35p+pGfMnvi9wCuI5Jkz5vX7LknjdRaB6Y/v 4YPI1BkYl/rmSg/YKjj38CbO9sbAeHD1lnI3ULd4GRAYbrQ+ZzRZJi+VL2Nfg9lvr0mX 6f1dPCYJJmQT6ICEcPGnIgc6Rv0UHnPy/gzrVzU81ltm1ehp/jgzj93pBvV7iyufQgs9 ePWQ== X-Gm-Message-State: APuU4Z+SmEMCTY2Ah85Suh8OkcTdl9VRnN3Zrg2NR6cEqHY70LO5ZYWB 5BCsyDjUJtTLgbLOjzYDsZk9HjOQQA47opG/p36SV/1AlNvOFqy6KagU3zDPl00C+9pDKJJlp8f xP5+TP0U= X-Gm-Gg: AYBFou1Xa1jJMyFowcab7Hm1sd0W2xmoR902EaL4RrCtPu+usJsZWHDAjI2lxRBqQTq 2+raaYA4b0c2thH5zXcyc3ZSvbp95v3Z6/WpymTElxpBpUm7gbM32r0+IhMrVPQn4+5wB9pAdIH AMzsdguE+cvsEPv2D2MSIKwnSyLw9bKhjzrNplbz5GjTOG4Q1gv2hTfV+esMhtFJJDSTmY/Besk UQip590XdbU1T9A5rSqw2Hkq46v83zlwAi2qW6kLdLn8+7v+g5CF1oolCnSkQ4axPGMBXn1uMAQ esIY5qZB2j7nMfKa7EiEUh0NJR0nyPBiBHtbKyfNWfHPm1pzEdWjys6bsgzdrXEORqElvvvSnwk 5+gPtm5bl/1aoQMwFoE4qKhUVCLbkONi9dwkgzQwYyIvi3U46zA+EFMzPTScWgBxhY0sek5jiNq tZbZx/3tPMTFkSbbX8ZQAV9JYcNJm53/aVLPRcuo0SQwDHvie1UK407xjrHXdmUa99yIGTm+jiF 5U2qsOxc2y24NHKc1ORmY3XIHJuRFV0YkTXR/a08pbwV3wrDVWuUBYZJldNBr/Hza8++XGnFIuK oK3oCCefBPAJ054w0rwt75M8qqdeL4bgM9/zf2MaL38mEtlWf8qqzhTtRg== X-Received: by 2002:a5d:584c:0:b0:48a:f0cd:8712 with SMTP id ffacd0b85a97d-49c7325b837mr17556216f8f.50.1794732589864; Sun, 15 Nov 2026 00:49:49 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.48 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:49 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 37/41] oeqa/core: Use unittest's setup hook instead of patching test classes Date: Sun, 15 Nov 2026 08:48:40 +0000 Message-ID: <20261115084845.701136-37-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:54 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250268 To run the decorators and the td_vars check, OETestLoader renamed the setUp()/tearDown()/setUpClass()/tearDownClass() methods of every test class it loaded and replaced them with OETestCase wrappers, marking the class as patched. Since the marker was inherited, a subclass which overrode setUp() and was loaded after its parent class was left unpatched and silently lost its decorators. Override TestCase._callSetUp(), which unittest uses to run setUp(), to check td_vars and set up the decorators, and register the decorator teardowns as cleanups so they run after tearDown() and when setUp() fails. The td_vars check now runs per test rather than in setUpClass(), none of the classes using td_vars need the variables in setUpClass(). The class level hook was otherwise only used to skip classes given on the command line, so use unittest.skip() for those and for skipped tests. Tests in a skipped class are now each reported as skipped rather than as a single class level skip. This does mean we use python internal API but we can adapt if python changes that. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/core/case.py | 37 +++++++++++------------------------ meta/lib/oeqa/core/context.py | 25 +++++++++-------------- meta/lib/oeqa/core/loader.py | 30 +--------------------------- 3 files changed, 21 insertions(+), 71 deletions(-) diff --git a/meta/lib/oeqa/core/case.py b/meta/lib/oeqa/core/case.py index e71cab5028c..86944cddde0 100644 --- a/meta/lib/oeqa/core/case.py +++ b/meta/lib/oeqa/core/case.py @@ -32,33 +32,18 @@ class OETestCase(unittest.TestCase): # OEQAMissingVariable exception is raised td_vars = None - @classmethod - def _oeSetUpClass(clss): - _validate_td_vars(clss.td, clss.td_vars, "class") - if hasattr(clss, 'setUpHooker') and callable(getattr(clss, 'setUpHooker')): - clss.setUpHooker() - clss.setUpClassMethod() - - @classmethod - def _oeTearDownClass(clss): - clss.tearDownClassMethod() - - def _oeSetUp(self): - # unittest doesn't call tearDown() if setUp() fails so the decorators - # need tearing down here in that case too - try: - for d in self.decorators: - d.setUpDecorator() - self.setUpMethod() - except: - for d in self.decorators: - d.tearDownDecorator() - raise - - def _oeTearDown(self): + # Decorators bound to this test case by OETestLoader + decorators = () + + def _callSetUp(self): + # unittest.TestCase.run() calls this to run setUp(). Check the test + # data and set up the decorators first. Decorators are torn down as + # cleanups, which run after tearDown() and also if setUp() fails. + _validate_td_vars(self.td, self.td_vars, "class") for d in self.decorators: - d.tearDownDecorator() - self.tearDownMethod() + d.setUpDecorator() + self.addCleanup(d.tearDownDecorator) + super()._callSetUp() def assertFileExists(self, filename, msg=None): """ diff --git a/meta/lib/oeqa/core/context.py b/meta/lib/oeqa/core/context.py index 3bd65ba35f6..601a8014d9b 100644 --- a/meta/lib/oeqa/core/context.py +++ b/meta/lib/oeqa/core/context.py @@ -47,24 +47,17 @@ class OETestContext: return modules def skipTests(self, skips): - if not skips: - return - def skipfuncgen(skipmsg): - def func(): - raise unittest.SkipTest(skipmsg) - return func - class_ids = {} + # Use unittest's skip support so that skipped tests, and the class + # setup of skipped classes, don't run for test in self.suites: - if test.__class__ not in class_ids: - class_ids[test.__class__] = '.'.join(test.id().split('.')[:-1]) + class_id = test.id().rsplit('.', 1)[0] for skip in skips: - if (test.id()+'.').startswith(skip+'.'): - setattr(test, 'setUp', skipfuncgen('Skip by the command line argument "%s"' % skip)) - for tclass in class_ids: - cid = class_ids[tclass] - for skip in skips: - if (cid + '.').startswith(skip + '.'): - setattr(tclass, 'setUpHooker', skipfuncgen('Skip by the command line argument "%s"' % skip)) + msg = 'Skip by the command line argument "%s"' % skip + if (class_id + '.').startswith(skip + '.'): + unittest.skip(msg)(test.__class__) + elif (test.id() + '.').startswith(skip + '.'): + method = getattr(test, test._testMethodName) + setattr(test, test._testMethodName, unittest.skip(msg)(method)) def loadTests(self, module_paths, modules=[], tests=[], modules_manifest="", modules_required=[], **kwargs): diff --git a/meta/lib/oeqa/core/loader.py b/meta/lib/oeqa/core/loader.py index 94ade54506d..d4f330dafc3 100644 --- a/meta/lib/oeqa/core/loader.py +++ b/meta/lib/oeqa/core/loader.py @@ -171,37 +171,9 @@ class OETestLoader(unittest.TestLoader): return False def _getTestCase(self, testCaseClass, tcName): - if not hasattr(testCaseClass, '__oeqa_loader') and \ - issubclass(testCaseClass, OETestCase): - # In order to support data_vars validation - # monkey patch the default setUp/tearDown{Class} to use - # the ones provided by OETestCase - setattr(testCaseClass, 'setUpClassMethod', - getattr(testCaseClass, 'setUpClass')) - setattr(testCaseClass, 'tearDownClassMethod', - getattr(testCaseClass, 'tearDownClass')) - setattr(testCaseClass, 'setUpClass', - testCaseClass._oeSetUpClass) - setattr(testCaseClass, 'tearDownClass', - testCaseClass._oeTearDownClass) - - # In order to support decorators initialization - # monkey patch the default setUp/tearDown to use - # a setUpDecorators/tearDownDecorators that methods - # will call setUp/tearDown original methods. - setattr(testCaseClass, 'setUpMethod', - getattr(testCaseClass, 'setUp')) - setattr(testCaseClass, 'tearDownMethod', - getattr(testCaseClass, 'tearDown')) - setattr(testCaseClass, 'setUp', testCaseClass._oeSetUp) - setattr(testCaseClass, 'tearDown', testCaseClass._oeTearDown) - - setattr(testCaseClass, '__oeqa_loader', True) - case = testCaseClass(tcName) if isinstance(case, OETestCase): - setattr(case, 'decorators', []) - + case.decorators = [] return case def loadTestsFromTestCase(self, testCaseClass): From patchwork Sun Nov 15 08:48:41 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104222 Received: from mail-wm1-f43.google.com (mail-wm1-f43.google.com [209.85.128.43]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4337.1794732592688410454 for ; Sun, 15 Nov 2026 00:49:53 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=UDrnfiiU; spf=pass (domain: linuxfoundation.org, ip: 209.85.128.43, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wm1-f43.google.com with SMTP id 5b1f17b1804b1-4a4d7ae1ae9so17943385e9.1 for ; Sun, 15 Nov 2026 00:49:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732591; x=1795337391; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=Jn79lalBbqwt28qSle040LD3UaScOJl7zKBnXJOGcBs=; b=UDrnfiiU3t7B06q4jOMf+it2Zz64Fyt0ItuKZFTg0v6oQZUqn8d2iqFDI/EU0+GHA+ e35Z3UEELIy1qGAHHVyLCyZz/i6KTF/s8Q0eYB4+Oj5NmvZTI6ZkI9C1T4DJq0oq9HQX tK7u+KdrGkaNp9q5tkv8AYvaB3dCHwYLrGMNg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732591; x=1795337391; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=Jn79lalBbqwt28qSle040LD3UaScOJl7zKBnXJOGcBs=; b=h8vjsx/xQLqTlnu8DnjlUQsLOiIM3JxZLZ3PcpicA5wCtbklwkrTDUi32WjY4upH0Z dNTD0h79UucxYfIBZRHArNKD7lOSyzLthnmKzg6e/TIXcg4Clb/JgP4MhA/Mt6p48blc iXd21JEHI6YUIaEWWFO+rKZlsXp4N8DxboYrbC5y8BIQIVvEE0EO+YjgtirokBI/23V0 WICqSta8jPwXN7uectSIxhgpVvewdZ0mFsVAhukxl24+zTf5ziD/pC7wruwgZyAI29W3 u4l8coeRIBBKesSF/vwOrPBiS0BpBZM1OpiSaoEyO3CPyhWkvMep5zv7UL2CKXRybJ4u X7kQ== X-Gm-Message-State: APuU4Z/KDAVm6LeSa29j2S1VCXSoaoJvEA6FTYSKU6uBOPa0NRs6sqnA 5dSnK42B//+bBsB9VbVIcBK4KtsCfXHHJVeuoqpCtRRrkDcZL0pZiwpxP/l1saA8qMGPiD5cvYT M07gSo9s= X-Gm-Gg: AYBFou3RKAIkpWeMJPHhhyhuilF7He++W0IPE2lDT1PlGeDl3roRP7M6YxzItFjuFXT WSs60rh77jOnfNjgEO23D+fWPUlbkC83intbF2wjY7/KoYChvSsEjfJ2VsfolqSmys06EsmtogP PaG+7R5S7pKY29Sa2amiYtpr7eAf16YTTWoYP8kKgQpA2NK0bc9G5vC1o0qABZGvXMG6TthyaI6 Kd2DgJ2UCUzQO6zgdzkW5EQP48AhnaxvKRHfUnQQaINBrBzM/ipOg5AOibKT6/MVSzWtTNfUPrc hXyZUEfJk9aTP2OnHPrZBUzYz/ahOzqPE/OcmWdK6HWSRATiTvgGToW0kWmu4XC6yievNHbiPm2 yKSjSC6e5FO7RRsJwIBFTrGntGW+tc75FuX5VpQrTb3KnHhUXcwuXxGbB2cmiA/e3Akn404NOlM pgpi6XLZVO3iMbkSrNJo0ub4FwKLG6ijYyxyWkW8TecEJGQNspQKxuftzzNuR6POIO2FyerBqar a27M7jqBeYuOxbeIQBC59eaLwcLsUX4EavaMGS+i0uApJPCQOj/bjS2hFkjm7FskHea5a2qJTxs c+Zzt3kQQ/mhoCm3GapIWLSjrDZ3RfjUimX7Oya2DTAh8Ko2M4Uz9v4UJQ== X-Received: by 2002:a05:600c:3f18:b0:4bb:6ac0:6dc0 with SMTP id 5b1f17b1804b1-4bb6ac06e5dmr21988935e9.29.1794732590860; Sun, 15 Nov 2026 00:49:50 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.49 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:50 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 38/41] oeqa/core/loader: Always return a flat test suite Date: Sun, 15 Nov 2026 08:48:41 +0000 Message-ID: <20261115084845.701136-38-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:54 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250269 OETestLoader.discover() returned a flat suite of the loaded tests only when a discovery decorator class was registered, which happens as a side effect of some loaded module importing oeqa.core.decorator.depends. Otherwise it returned unittest's nested per module suites. skipTests() expects a flat suite, so with no module importing OETestDepends, as for the oe-core selftests on their own, --skip-tests failed with: AttributeError: 'TestSuite' object has no attribute 'id' Always return a flat suite, using the registered test cases in the order they were loaded when no discovery decorator reorders them, and add a test which runs without OETestDepends registered. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/core/loader.py | 4 ++-- meta/lib/oeqa/core/tests/test_loader.py | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/meta/lib/oeqa/core/loader.py b/meta/lib/oeqa/core/loader.py index d4f330dafc3..9ff91e792aa 100644 --- a/meta/lib/oeqa/core/loader.py +++ b/meta/lib/oeqa/core/loader.py @@ -237,7 +237,7 @@ class OETestLoader(unittest.TestLoader): pattern='*.py', top_level_dir=path) big_suite.addTests(suite) - cases = None + cases = list(self.tc._registry['cases'].values()) discover_classes = [clss for clss in decoratorClasses if issubclass(clss, OETestDiscover)] for clss in discover_classes: @@ -246,7 +246,7 @@ class OETestLoader(unittest.TestLoader): if self.modules_required: self._required_modules_validation() - return self.suiteClass(cases) if cases else big_suite + return self.suiteClass(cases) def _filterModule(self, module): if module.__name__ in sys.builtin_module_names: diff --git a/meta/lib/oeqa/core/tests/test_loader.py b/meta/lib/oeqa/core/tests/test_loader.py index cb38ac845e3..f4ab4c5b414 100755 --- a/meta/lib/oeqa/core/tests/test_loader.py +++ b/meta/lib/oeqa/core/tests/test_loader.py @@ -6,6 +6,9 @@ # import os +import subprocess +import sys +import textwrap import unittest from common import setup_sys_path, TestBase @@ -59,5 +62,25 @@ class TestLoader(TestBase): msg = 'Expected modules from two different paths' self.assertEqual(modules, expected_modules, msg=msg) + def test_flat_suite(self): + # The loaded suite must be a flat list of tests, which skipTests() + # relies on, even if no module registers a discovery decorator such as + # OETestDepends. Registering one is global so use a new process. + oeqa_lib = os.path.realpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../../')) + cases_path = os.path.join(self.cases_path, 'loader', 'valid') + script = textwrap.dedent(""" + import logging, sys, unittest + sys.path.insert(0, %r) + from oeqa.core.context import OETestContext + from oeqa.core.decorator import decoratorClasses + tc = OETestContext({}, logging.getLogger('flat')) + tc.loadTests(%r) + assert not [c for c in decoratorClasses if c.__name__ == 'OETestDepends'] + tc.skipTests(['another.AnotherTest.testAnother']) + print(' '.join(type(t).__name__ for t in tc.suites)) + """) % (oeqa_lib, cases_path) + output = subprocess.check_output([sys.executable, '-c', script], text=True) + self.assertEqual(output.split(), ['AnotherTest']) + if __name__ == '__main__': unittest.main() From patchwork Sun Nov 15 08:48:42 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104228 Received: from mail-wr1-f41.google.com (mail-wr1-f41.google.com [209.85.221.41]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4338.1794732593988179709 for ; Sun, 15 Nov 2026 00:49:54 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=Cm1anUGu; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.41, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f41.google.com with SMTP id ffacd0b85a97d-492fcbfaa88so1182956f8f.3 for ; Sun, 15 Nov 2026 00:49:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732592; x=1795337392; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=EaH2JGFMcnKA8FQC/KYul3/ib5Xmz2bvzXq5eRibPxY=; b=Cm1anUGua7z6HJys+iHWVej521GrAUpJfmG7yegMDn/pD/bq2WYdHb3CzjIhuFRNLx sF971Q8em8gxTnXGeAkUTG5t2c5ldtsMXQx+cXvpmOodRgPiPcp7jHESqDe5kpesZg1j Z0oVVzLGQQtYIK3+BhRHAHKIuInlmKglkTgEQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732592; x=1795337392; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=EaH2JGFMcnKA8FQC/KYul3/ib5Xmz2bvzXq5eRibPxY=; b=X/t81wdjrN4Spo3xlfctRNbeloRZccl55Z34CbdKjoo9bP7ir2LMdoEGepGslsrY7K 0Plv7A5ARhg0F229M4b581aB+WIJeh4C4bi4nPmy6b9G8BDd1N5AA7/U3tNp3Tz9NGo8 ghYiodYSPl/BBve5g3YFCS29ZFFrhktC7CYkRlZQsufG35K/iZaBjcUVml5OqrVH9Gfq MA1P12cpTo758lg5P8PWtW06fWaYcqkwgcgAKjGZ7tO1Yxjo8GrXeC93US75S9qyW83M 7/KfiVsEbnmrH6Q4q6yrlcpWZFum+WaDnojQVvdhOeN9i48reN6BuTm7Ydsxj/WlWj4m eWlA== X-Gm-Message-State: APuU4Z8NPcv+dSKpwq9FTfXxOHTzBk5LzZ5WMkTCa/okihw6DtN7OCS3 LP0Qyb4W3khq/xtbY4GjZkeEWAiwO1XZm0cccOmsd+9SUEBgAaNrpT9GF2KxrB6S3Lsvl9TIkCz FVikZo6g= X-Gm-Gg: AYBFou2OFBOi9qErfovi0rHB/wOErLelfMXT0dffM99wQF/QJJM215x1iEunvR7oUb+ dkn0EdTPyzHNTr00juXlnsp/CWw9GWyYa+jRmQ0LpFnhEDQEBrE+idQJUaflSRv0VyGbcC+ja4H FtLtoVfOv5BBR54o/7jMxXe+G0hTWFeOfAsmK5NWPPY8EZivyngVTVzv+oNmIQisJYIXHIB3Twm 3cCxR/9yvqKlNshn+YTP5B8i8j8iFP3E9BlrlaOOLiNzer0to+1+ZNUCw+l/TmTzYyuYoHlbfXW aYRa+etkaGffxehflZ1gThCL9wUS5nZtDZQs4imNE2Jc6ceoePXoCD8cMz8ERoQexs/UwH4+Q3F SQ0jH2j3/YyThZ9kKfrxRXGQXh4890Y7XUWkjSi4kOxQsCOvpuvrP1CdUhZn8Fh9SFSLYQwj9oJ WISSVHd2ziGRh17FoTwJjRamK60c/goZ/kcB4N7EqHx2/Iedx47hSfx0pKospXQXXHz7hUxxJGG RfC19m94Tihji9UyUQMMVb/NYiWhVamyvxtZSvdEb+XPurQfjT8jqp4AtZX0MuvdMTxOeBzTgwi QscHelySMA3lAgyYJbW9elqkSimIyJ+Vr5ukDnuwEqFOrYGf8Hb8bKVU7NCAQgvpR4mmAmZ6WfL umKU= X-Received: by 2002:a05:6000:228a:b0:48e:3647:c35d with SMTP id ffacd0b85a97d-49c7381ade0mr17690446f8f.21.1794732592206; Sun, 15 Nov 2026 00:49:52 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.50 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:51 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 39/41] oeqa: Drop the unused tc_kwargs list phase and dead selftest code Date: Sun, 15 Nov 2026 08:48:42 +0000 Message-ID: <20261115084845.701136-39-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:49:55 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250270 Nothing ever adds arguments to tc_kwargs['list'] and no context's listTests() takes any, so drop it. In oe-selftest, remove an unused config_paths assignment, the unused machines argument of OESelftestTestContext and its runTests()/listTests() overrides which only existed to drop an unused machine argument. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/core/context.py | 3 +-- meta/lib/oeqa/selftest/context.py | 12 ++---------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/meta/lib/oeqa/core/context.py b/meta/lib/oeqa/core/context.py index 601a8014d9b..9e38cddcfeb 100644 --- a/meta/lib/oeqa/core/context.py +++ b/meta/lib/oeqa/core/context.py @@ -162,7 +162,6 @@ class OETestContextExecutor: self.tc_kwargs = {} self.tc_kwargs['init'] = {} self.tc_kwargs['load'] = {} - self.tc_kwargs['list'] = {} self.tc_kwargs['run'] = {} self.tc_kwargs['init']['logger'] = self._setup_logger(logger, args) @@ -219,7 +218,7 @@ class OETestContextExecutor: sys.exit(1) if args.list_tests: - rc = self.tc.listTests(args.list_tests, **self.tc_kwargs['list']) + rc = self.tc.listTests(args.list_tests) else: self._pre_run() rc = self.tc.runTests(**self.tc_kwargs['run']) diff --git a/meta/lib/oeqa/selftest/context.py b/meta/lib/oeqa/selftest/context.py index 1802454a0c0..aaae9574c94 100644 --- a/meta/lib/oeqa/selftest/context.py +++ b/meta/lib/oeqa/selftest/context.py @@ -69,7 +69,7 @@ def removebuilddir(d): bb.utils.prunedir(d, ionice=True) class OESelftestTestContext(OETestContext): - def __init__(self, td=None, logger=None, machines=None, config_paths=None, newbuilddir=None, keep_builddir=None): + def __init__(self, td=None, logger=None, config_paths=None, newbuilddir=None, keep_builddir=None): super().__init__(td, logger) self.config_paths = config_paths @@ -170,12 +170,6 @@ class OESelftestTestContext(OETestContext): else: return NonConcurrentTestSuite(suites, processes, self.setup_builddir, self.removebuilddir, self.bb_vars) - def runTests(self, processes=None, machine=None, skips=[]): - return super().runTests(processes, skips) - - def listTests(self, display_type, machine=None): - return super().listTests(display_type) - class OESelftestTestContextExecutor(OETestContextExecutor): _context_class = OESelftestTestContext _script_executor = 'oe-selftest' @@ -398,7 +392,7 @@ class OESelftestTestContextExecutor(OETestContextExecutor): sys.exit(1) if args.list_tests: - rc = self.tc.listTests(args.list_tests, **self.tc_kwargs['list']) + rc = self.tc.listTests(args.list_tests) else: self._pre_run() rc = self.tc.runTests(**self.tc_kwargs['run']) @@ -417,8 +411,6 @@ class OESelftestTestContextExecutor(OETestContextExecutor): try: rc = self._internal_run(logger, args) finally: - config_paths = self.tc_kwargs['init']['config_paths'] - output_link = os.path.join(os.path.dirname(args.output_log), "%s-results.log" % self.name) if os.path.lexists(output_link): From patchwork Sun Nov 15 08:48:43 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104229 Received: from mail-wr1-f44.google.com (mail-wr1-f44.google.com [209.85.221.44]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4339.1794732595268876715 for ; Sun, 15 Nov 2026 00:49:55 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=PSpOb9c0; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.44, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f44.google.com with SMTP id ffacd0b85a97d-49465892f7bso2045732f8f.1 for ; Sun, 15 Nov 2026 00:49:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732593; x=1795337393; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=N+zpHGFPAiu1tv1cw7hqeGyd3pXVrdy5WeAfTUys6tU=; b=PSpOb9c0E3BQVC1f5+IeezcZIqC3eWCuTj+cvRJuQbxjGverS8q6/IYef/r1v0FI8j qBDDFHREvwYNpFs5yntVSuQIKgekcZJkEqburYc7ejc+xHfqigkKmcFuVeFIUa42jIak SvMzZRcIVVdzIbP4wdxuF1YPuxml9qlJy7DW4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732593; x=1795337393; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=N+zpHGFPAiu1tv1cw7hqeGyd3pXVrdy5WeAfTUys6tU=; b=Wf4JaUR11O0wmFRNGW3WUc9LHlLb2aOA5vLpbWrthiG5eWOt6KkPnWu0FkLal7fF5p 1S4hs1LHLh6bNmcYm56WH9WLbTWVLq7vAFP+5n/LEtf5mDmrR4eaEKD41bSNMTUNqUlC qPhAWzeYC4YqntVhm4E2y65NqC38uDTynM84PnGQRe+GP1qPg2XNk3BvyBboFpbabeAV zBbZiE2tFpcJJO4KrAqNdxP4XJl/AmXTgw80iyDy1V4lwE6tpP91o7btQBOxtHXjWxqF 3ZIIOboVI1skIDUC8RvuSllU4Y/RwzstX2QPC4ZW6ju9rgGiMplF7b+VDmG6x2agMYsb NP0A== X-Gm-Message-State: APuU4Z8gJGCxpWEQEoBbAdEMSkNHpg12LjIv6dXfYAU29W5GCxna96wG 5Fzf17AEMrD4HgBJJLmaD3AML7bCllDZmxxQxxdZiwILJSCAnADSzu4Imr7TLqtjNTAMZcvft++ 4nvjm/Pg= X-Gm-Gg: AYBFou1TMXMudJNWbdIsejRdZYVIgM3gAAqUKnNIC9rMcjxZQFmq1t6+00xSZOmfoxg oO6d3vsg08msmTPxilJTfrnMRJkVVkeXSbkpy1sgHlnzR7bJ5QSOY9RFhp8JTVl516mnkPLqRvr VA18fgBs3BcZRsIkwPv9NpjcNMCxmL+kdJ1UjWDQQXQ/AyAuTbw8y5EV1cZB/vF5yzzP4iwAIbA eZDN8eWt8hq2qiRymklu2fk9OwHXaasCSVy61EowTd5/SryGHDr8gb7mO6cBQA2f1RAeGEkGFqf BQ0PCNl2S89wYRdqVVYCpfwbijfFHy0gsLDUFDjR9iQe36oaWbqmLTTTyiekKE9oXb8eF3ssGH9 GOADLc5eG7QsxTgIIbEWxcba0fL6KfyChoOtCRlzJXw7ogQi8EkeDkWFWZZLTX9dAtz2DTtehri zIa918VcfuDGJgI5kHDkStKFMtS0JdXzq72SYCPk/yCwg7U8q6wvoMtcHQKe+2SMxYQ5Bds5Kb2 1XjcrEBMeClNm6U+kh+y6KXKg5fMRYPYVAPRpbycQQbn63c6OF5W3vthMM6P4W+nG2vvLPw7di1 Vtiqlqv4IBz8rmBZBeAXO8BkTBl4eTWzDk1ALdOAXlxC0n9O2jFAPve7ag== X-Received: by 2002:a5d:64cf:0:b0:48d:f3ee:7cc with SMTP id ffacd0b85a97d-49c71a66085mr14300175f8f.30.1794732593165; Sun, 15 Nov 2026 00:49:53 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.52 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:52 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 40/41] oeqa: Replace tc_kwargs with explicit attributes Date: Sun, 15 Nov 2026 08:48:43 +0000 Message-ID: <20261115084845.701136-40-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:50:05 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250271 The test component executors collected the arguments for the test context in a dict of dicts, tc_kwargs, which run() then expanded into the context constructor, loadTests() and runTests(). Apart from the constructor arguments, which vary by context, these were always the same few values. Store the test data, logger, modules to load, tag filter, skips and process count as attributes and pass them explicitly, and keep a single context_args dict for the context specific constructor arguments. The calls made to the contexts are unchanged. Layers with their own test components which extend tc_kwargs will need to set these attributes instead. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/core/context.py | 42 +++++++++++++++++-------------- meta/lib/oeqa/runtime/context.py | 8 +++--- meta/lib/oeqa/sdk/context.py | 10 ++++---- meta/lib/oeqa/selftest/context.py | 33 ++++++++++++------------ 4 files changed, 49 insertions(+), 44 deletions(-) diff --git a/meta/lib/oeqa/core/context.py b/meta/lib/oeqa/core/context.py index 9e38cddcfeb..7d7d9f3c5c8 100644 --- a/meta/lib/oeqa/core/context.py +++ b/meta/lib/oeqa/core/context.py @@ -47,6 +47,8 @@ class OETestContext: return modules def skipTests(self, skips): + if not skips: + return # Use unittest's skip support so that skipped tests, and the class # setup of skipped classes, don't run for test in self.suites: @@ -159,32 +161,33 @@ class OETestContextExecutor: return logger def _process_args(self, logger, args): - self.tc_kwargs = {} - self.tc_kwargs['init'] = {} - self.tc_kwargs['load'] = {} - self.tc_kwargs['run'] = {} - - self.tc_kwargs['init']['logger'] = self._setup_logger(logger, args) + self.logger = self._setup_logger(logger, args) if args.test_data_file: - self.tc_kwargs['init']['td'] = json.load( - open(args.test_data_file, "r")) + with open(args.test_data_file, "r") as f: + self.td = json.load(f) else: - self.tc_kwargs['init']['td'] = {} + self.td = {} + + # Any further arguments for the test context, for subclasses to add + self.context_args = {} # Run image specific TEST_SUITE like testimage.bbclass by default - test_suites = self.tc_kwargs['init']['td'].get("TEST_SUITES") + test_suites = self.td.get("TEST_SUITES") if test_suites: test_suites = test_suites.split() + self.modules_required = [] if args.run_tests: - self.tc_kwargs['load']['modules'] = args.run_tests - self.tc_kwargs['load']['modules_required'] = args.run_tests + self.modules = args.run_tests + self.modules_required = args.run_tests elif test_suites: - self.tc_kwargs['load']['modules'] = test_suites + self.modules = test_suites else: - self.tc_kwargs['load']['modules'] = [] + self.modules = [] + self.tags_filter = None - self.tc_kwargs['run']['skips'] = [] + self.processes = None + self.skips = [] self.module_paths = args.CASES_PATHS @@ -192,7 +195,7 @@ class OETestContextExecutor: return args.json_result_dir def _get_configuration(self): - td = self.tc_kwargs['init']['td'] + td = self.td configuration = {'TEST_TYPE': self.name, 'MACHINE': td.get("MACHINE"), 'DISTRO': td.get("DISTRO"), @@ -210,9 +213,10 @@ class OETestContextExecutor: def run(self, logger, args): self._process_args(logger, args) - self.tc = self._context_class(**self.tc_kwargs['init']) + self.tc = self._context_class(td=self.td, logger=self.logger, **self.context_args) try: - self.tc.loadTests(self.module_paths, **self.tc_kwargs['load']) + self.tc.loadTests(self.module_paths, modules=self.modules, + modules_required=self.modules_required, tags_filter=self.tags_filter) except OEQATestNotFound as ex: logger.error(ex) sys.exit(1) @@ -221,7 +225,7 @@ class OETestContextExecutor: rc = self.tc.listTests(args.list_tests) else: self._pre_run() - rc = self.tc.runTests(**self.tc_kwargs['run']) + rc = self.tc.runTests(processes=self.processes, skips=self.skips) json_result_dir = self._get_json_result_dir(args) if json_result_dir: diff --git a/meta/lib/oeqa/runtime/context.py b/meta/lib/oeqa/runtime/context.py index 0763fb25ac0..c507197d8d1 100644 --- a/meta/lib/oeqa/runtime/context.py +++ b/meta/lib/oeqa/runtime/context.py @@ -206,7 +206,7 @@ class OERuntimeTestContextExecutor(OETestContextExecutor): super()._process_args(logger, args) - td = self.tc_kwargs['init']['td'] + td = self.td target_kwargs = {} target_kwargs['machine'] = td.get("MACHINE") or None @@ -216,12 +216,12 @@ class OERuntimeTestContextExecutor(OETestContextExecutor): target_kwargs['serialcontrol_ps1'] = td.get("TEST_SERIALCONTROL_PS1") or None target_kwargs['serialcontrol_connect_timeout'] = td.get("TEST_SERIALCONTROL_CONNECT_TIMEOUT") or None - self.tc_kwargs['init']['target'] = \ + self.context_args['target'] = \ OERuntimeTestContextExecutor.getTarget(args.target_type, None, args.target_ip, args.server_ip, **target_kwargs) - self.tc_kwargs['init']['image_packages'] = \ + self.context_args['image_packages'] = \ OERuntimeTestContextExecutor.readPackagesManifest( args.packages_manifest) - self.tc_kwargs['init']['extract_dir'] = args.extract_dir + self.context_args['extract_dir'] = args.extract_dir _executor_class = OERuntimeTestContextExecutor diff --git a/meta/lib/oeqa/sdk/context.py b/meta/lib/oeqa/sdk/context.py index 6024554cac4..3e2a7cff00e 100644 --- a/meta/lib/oeqa/sdk/context.py +++ b/meta/lib/oeqa/sdk/context.py @@ -101,13 +101,13 @@ class OESDKTestContextExecutor(OETestContextExecutor): def _process_args(self, logger, args): super()._process_args(logger, args) - self.tc_kwargs['init']['sdk_dir'] = args.sdk_dir - self.tc_kwargs['init']['sdk_env'] = self.sdk_env - self.tc_kwargs['init']['target_pkg_manifest'] = \ + self.context_args['sdk_dir'] = args.sdk_dir + self.context_args['sdk_env'] = self.sdk_env + self.context_args['target_pkg_manifest'] = \ OESDKTestContextExecutor._load_manifest(args.target_manifest) - self.tc_kwargs['init']['host_pkg_manifest'] = \ + self.context_args['host_pkg_manifest'] = \ OESDKTestContextExecutor._load_manifest(args.host_manifest) - self.tc_kwargs['run']['processes'] = args.processes + self.processes = args.processes @staticmethod def _get_sdk_environs(sdk_dir): diff --git a/meta/lib/oeqa/selftest/context.py b/meta/lib/oeqa/selftest/context.py index aaae9574c94..49d9fc2cba1 100644 --- a/meta/lib/oeqa/selftest/context.py +++ b/meta/lib/oeqa/selftest/context.py @@ -262,16 +262,17 @@ class OESelftestTestContextExecutor(OETestContextExecutor): elif args.list_tests: args.list_tests = 'name' - self.tc_kwargs['init']['td'] = bbvars + self.td = bbvars builddir = os.environ.get("BUILDDIR") - self.tc_kwargs['init']['config_paths'] = {} - self.tc_kwargs['init']['config_paths']['testlayer_path'] = get_test_layer(bbvars["BBLAYERS"]) - self.tc_kwargs['init']['config_paths']['builddir'] = builddir - self.tc_kwargs['init']['config_paths']['localconf'] = os.path.join(builddir, "conf/local.conf") - self.tc_kwargs['init']['config_paths']['bblayers'] = os.path.join(builddir, "conf/bblayers.conf") - self.tc_kwargs['init']['newbuilddir'] = args.newbuilddir - self.tc_kwargs['init']['keep_builddir'] = args.keep_builddir + self.context_args['config_paths'] = { + 'testlayer_path': get_test_layer(bbvars["BBLAYERS"]), + 'builddir': builddir, + 'localconf': os.path.join(builddir, "conf/local.conf"), + 'bblayers': os.path.join(builddir, "conf/bblayers.conf"), + } + self.context_args['newbuilddir'] = args.newbuilddir + self.context_args['keep_builddir'] = args.keep_builddir def tag_filter(tags): if args.exclude_tags: @@ -283,10 +284,10 @@ class OESelftestTestContextExecutor(OETestContextExecutor): return False if args.select_tags or args.exclude_tags: - self.tc_kwargs['load']['tags_filter'] = tag_filter + self.tags_filter = tag_filter - self.tc_kwargs['run']['skips'] = args.skips - self.tc_kwargs['run']['processes'] = args.processes + self.skips = args.skips + self.processes = args.processes def _pre_run(self): def _check_required_env_variables(vars): @@ -381,12 +382,12 @@ class OESelftestTestContextExecutor(OETestContextExecutor): return '%s_%s_%s_%s' % (configuration['TEST_TYPE'], configuration['HOST_DISTRO'], configuration['MACHINE'], configuration['STARTTIME']) def _internal_run(self, logger, args): - self.module_paths = self._get_cases_paths( - self.tc_kwargs['init']['td']['BBPATH'].split(':')) + self.module_paths = self._get_cases_paths(self.td['BBPATH'].split(':')) - self.tc = self._context_class(**self.tc_kwargs['init']) + self.tc = self._context_class(td=self.td, logger=self.logger, **self.context_args) try: - self.tc.loadTests(self.module_paths, **self.tc_kwargs['load']) + self.tc.loadTests(self.module_paths, modules=self.modules, + modules_required=self.modules_required, tags_filter=self.tags_filter) except OEQATestNotFound as ex: logger.error(ex) sys.exit(1) @@ -395,7 +396,7 @@ class OESelftestTestContextExecutor(OETestContextExecutor): rc = self.tc.listTests(args.list_tests) else: self._pre_run() - rc = self.tc.runTests(**self.tc_kwargs['run']) + rc = self.tc.runTests(processes=self.processes, skips=self.skips) configuration = self.get_configuration(args) rc.logDetails(self.get_json_result_dir(args), configuration, From patchwork Sun Nov 15 08:48:44 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Purdie X-Patchwork-Id: 104230 Received: from mail-wr1-f41.google.com (mail-wr1-f41.google.com [209.85.221.41]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4340.1794732596575333146 for ; Sun, 15 Nov 2026 00:49:56 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@linuxfoundation.org header.s=google header.b=SusLYIl+; spf=pass (domain: linuxfoundation.org, ip: 209.85.221.41, mailfrom: richard.purdie@linuxfoundation.org) Received: by mail-wr1-f41.google.com with SMTP id ffacd0b85a97d-49412eb1474so1126431f8f.3 for ; Sun, 15 Nov 2026 00:49:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=google; t=1794732595; x=1795337395; darn=lists.openembedded.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to:content-type; bh=f4DFIM4L139WE3XeP/019heMPTSxj7drBQ+tVsHw4pM=; b=SusLYIl+J3y+/BznqQDhSjMuKGsU0/TIRsA70nLUCqZkvqh5kEiDRK+ZrEEIsrctOY rcB91+5UG5kybOPThE57pX7B5Nes0W4gKiIcxgbHSBspDwCrOjVtVGq9fZ/OBJLAHEc2 xxmQqW0R885+BfIil+YSLusxf6TkXbbDafnk8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794732595; x=1795337395; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to:content-type; bh=f4DFIM4L139WE3XeP/019heMPTSxj7drBQ+tVsHw4pM=; b=VhxJT6BE8IE8D+/9LRdFz9qTTkKez5ud4wW9+9lTzb8ADtgHYvtib0veIdmrwz+SgL ApNrA8DDTi584CkjBUH8UrqutqVkF6PCKOBCH18vWL2yUNxcFt71pU62PeDfpnp6kMeV mpDAyGpSYm0c9wdxiK/sH5j6SGbvlCaSjGmk2ytPbvBFcFksNF1h+jLDDrHKC5jB3XD4 9V249uA9grM+gfSUlpjjJ1BHI2MWy5UDUC5Z/2UFpvdu/TftDHWSSHWMlwVTvAuHQoMR gh0DsZOPfCrh9uFoL05ZA3i1uWIB5eTh7HsWlvzUTk8/4JPWw2fwn0yFy/NOEByph8cb BweA== X-Gm-Message-State: APuU4Z/I3p1qgIhYTuaquCZJBqiPj5j6mvsWh+VngWOGzHpk00DTGuKn X81J/ACW5C7TjsoWXIy6ZDbBF0tLvlAlQRiM1IGCGra+oGhqwgwYua3jFzAHwPvxDYsJgln6vIl ZsYTAHFQ= X-Gm-Gg: AYBFou3V4vZZRnCC9kJF7POQ2WXuVYkihMTgKhdWBdLOO/Vnceggrizyy4aWCLSsCKr ZS/lStdus3pgk5r3mIFYFnPwOjeHsyMGnlMAu2yIrJi+c+Dk/1N6gGlUptEGumgLKRLH/ga5IED NJbU+Eq5q6cyvkTE84HV+BczLdRG01ANB3cujrjFIxiEzBhYFQBkYy0Arrcyz85+MP0iu7Q3JHp XUf4oAoFGvCn4CU0eq44P1R0ouJguFG+YetjLEjKtcja+KIClf8DSOIgNLARpvd0ecSj2ERwNvI QmG7BiffTJhflu7lDGaddmlTeh/kGL215gqoztqgHVcoQZVYYJ7rJGU/ngM3kxyNHL68sO9H8gI lE616S9RoXuTnlKYz8iU1rVM1h6WRkSFZp7YpxCNuBazDWxMyHSzrQoYMsXZJO2L6rPbdNcnlw+ XetdlrnREhmNj2fkMIE2gyHCCIwQ8CWZkvJR2D1RwSAdj/SccO1ial/gHEE4zzjeXHiV9eGkxwi KZQqEt1QzV4tccJ7hSn0W4Fz1lGpkWb3mqoXH9M6eoj2RDa0kguprvwh41x/ryB9399k1u9rOtR Io5fz33V1w1K5GklDVmyHEnIJVcL4L9sW8U4/qVMqyGSaCi4wZA+cpQOd+JL7bLyuU5jOv9xr0z dWVA= X-Received: by 2002:a5d:5e02:0:b0:499:81db:47a3 with SMTP id ffacd0b85a97d-49c71e3e123mr15282806f8f.11.1794732594799; Sun, 15 Nov 2026 00:49:54 -0800 (PST) Return-Path: Received: from max.int.rpsys.net ([2001:8b0:aba:5f3c:4b65:588d:a4ce:ce3f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-49c60f8d66esm13804452f8f.57.2026.11.15.00.49.53 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Nov 2026 00:49:53 -0800 (PST) From: Richard Purdie To: openembedded-core@lists.openembedded.org Subject: [PATCH 41/41] oeqa/selftest: Use the core executor's run() Date: Sun, 15 Nov 2026 08:48:44 +0000 Message-ID: <20261115084845.701136-41-richard.purdie@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> References: <20261115084845.701136-1-richard.purdie@linuxfoundation.org> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Sun, 15 Nov 2026 08:50:05 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250272 OESelftestTestContextExecutor carried its own copy of run(), split into run() and _internal_run(), which differed from the core version only in finding the test module paths from BBPATH, always writing the json results and creating the results log link even when the run raised an exception. It also had its own versions of the configuration, result id and json directory hooks under different names, which the core code never called. Split the core run() so the results log link is always created, pass args to _get_configuration() as the selftest version needs it, rename the selftest hooks to match the core ones and set the module paths in _process_args(). The selftest copy of run() can then be dropped. This also fixes the core run() failing with FileExistsError when the old results log link is dangling, as os.path.exists() is false for a broken link. Use os.path.lexists() as the selftest code did. AI-Generated: Uses Claude Opus 5.5 Signed-off-by: Richard Purdie --- meta/lib/oeqa/core/context.py | 52 +++++++++++++++++-------------- meta/lib/oeqa/selftest/context.py | 49 ++++------------------------- 2 files changed, 34 insertions(+), 67 deletions(-) diff --git a/meta/lib/oeqa/core/context.py b/meta/lib/oeqa/core/context.py index 7d7d9f3c5c8..fe071ddb409 100644 --- a/meta/lib/oeqa/core/context.py +++ b/meta/lib/oeqa/core/context.py @@ -194,7 +194,7 @@ class OETestContextExecutor: def _get_json_result_dir(self, args): return args.json_result_dir - def _get_configuration(self): + def _get_configuration(self, args): td = self.td configuration = {'TEST_TYPE': self.name, 'MACHINE': td.get("MACHINE"), @@ -210,9 +210,7 @@ class OETestContextExecutor: def _pre_run(self): pass - def run(self, logger, args): - self._process_args(logger, args) - + def _run(self, logger, args): self.tc = self._context_class(td=self.td, logger=self.logger, **self.context_args) try: self.tc.loadTests(self.module_paths, modules=self.modules, @@ -222,28 +220,34 @@ class OETestContextExecutor: sys.exit(1) if args.list_tests: - rc = self.tc.listTests(args.list_tests) + return self.tc.listTests(args.list_tests) + + self._pre_run() + rc = self.tc.runTests(processes=self.processes, skips=self.skips) + + json_result_dir = self._get_json_result_dir(args) + if json_result_dir: + configuration = self._get_configuration(args) + rc.logDetails(json_result_dir, + configuration, + self._get_result_id(configuration)) else: - self._pre_run() - rc = self.tc.runTests(processes=self.processes, skips=self.skips) - - json_result_dir = self._get_json_result_dir(args) - if json_result_dir: - configuration = self._get_configuration() - rc.logDetails(json_result_dir, - configuration, - self._get_result_id(configuration)) - else: - rc.logDetails() - - rc.logSummary(self.name) - - output_link = os.path.join(os.path.dirname(args.output_log), - "%s-results.log" % self.name) - if os.path.exists(output_link): - os.remove(output_link) - os.symlink(args.output_log, output_link) + rc.logDetails() + rc.logSummary(self.name) return rc + def run(self, logger, args): + self._process_args(logger, args) + try: + return self._run(logger, args) + finally: + # Link to the latest log, even if running the tests failed. The + # old link may be dangling if its log was removed. + output_link = os.path.join(os.path.dirname(args.output_log), + "%s-results.log" % self.name) + if os.path.lexists(output_link): + os.unlink(output_link) + os.symlink(args.output_log, output_link) + _executor_class = OETestContextExecutor diff --git a/meta/lib/oeqa/selftest/context.py b/meta/lib/oeqa/selftest/context.py index 49d9fc2cba1..1f03f511af2 100644 --- a/meta/lib/oeqa/selftest/context.py +++ b/meta/lib/oeqa/selftest/context.py @@ -17,7 +17,7 @@ import bb.utils import bb.tinfoil from oeqa.core.context import OETestContext, OETestContextExecutor -from oeqa.core.exception import OEQAPreRun, OEQATestNotFound +from oeqa.core.exception import OEQAPreRun from oeqa.utils.commands import runCmd, get_bb_vars, get_test_layer @@ -289,6 +289,8 @@ class OESelftestTestContextExecutor(OETestContextExecutor): self.skips = args.skips self.processes = args.processes + self.module_paths = self._get_cases_paths(self.td['BBPATH'].split(':')) + def _pre_run(self): def _check_required_env_variables(vars): for var in vars: @@ -358,14 +360,14 @@ class OESelftestTestContextExecutor(OETestContextExecutor): vars['BBLAYERS'] = str(d.getVar('BBLAYERS')) self.tc.set_variables(vars) - def get_json_result_dir(self, args): + def _get_json_result_dir(self, args): json_result_dir = os.path.join(self.tc.td["LOG_DIR"], 'oeqa') if "OEQA_JSON_RESULT_DIR" in self.tc.td: json_result_dir = self.tc.td["OEQA_JSON_RESULT_DIR"] return json_result_dir - def get_configuration(self, args): + def _get_configuration(self, args): from oeqa.utils.metadata import metadata_from_bb metadata = metadata_from_bb() oeselftest_metadata = get_oeselftest_metadata(args) @@ -378,46 +380,7 @@ class OESelftestTestContextExecutor(OETestContextExecutor): 'OESELFTEST_METADATA': oeselftest_metadata} return configuration - def get_result_id(self, configuration): + def _get_result_id(self, configuration): return '%s_%s_%s_%s' % (configuration['TEST_TYPE'], configuration['HOST_DISTRO'], configuration['MACHINE'], configuration['STARTTIME']) - def _internal_run(self, logger, args): - self.module_paths = self._get_cases_paths(self.td['BBPATH'].split(':')) - - self.tc = self._context_class(td=self.td, logger=self.logger, **self.context_args) - try: - self.tc.loadTests(self.module_paths, modules=self.modules, - modules_required=self.modules_required, tags_filter=self.tags_filter) - except OEQATestNotFound as ex: - logger.error(ex) - sys.exit(1) - - if args.list_tests: - rc = self.tc.listTests(args.list_tests) - else: - self._pre_run() - rc = self.tc.runTests(processes=self.processes, skips=self.skips) - configuration = self.get_configuration(args) - rc.logDetails(self.get_json_result_dir(args), - configuration, - self.get_result_id(configuration)) - rc.logSummary(self.name) - - return rc - - def run(self, logger, args): - self._process_args(logger, args) - - rc = None - try: - rc = self._internal_run(logger, args) - finally: - output_link = os.path.join(os.path.dirname(args.output_log), - "%s-results.log" % self.name) - if os.path.lexists(output_link): - os.unlink(output_link) - os.symlink(args.output_log, output_link) - - return rc - _executor_class = OESelftestTestContextExecutor