From nobody Thu Apr 2 19:01:00 2026 Received: from mail-pl1-f175.google.com (mail-pl1-f175.google.com [209.85.214.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6B76735293D for ; Thu, 12 Feb 2026 16:37:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770914261; cv=none; b=d97iU/qy6OLrNe1BXAe26jNsbt83llPRbzRIZ9m9jmRkjsUMvpUC3BijWj3t2UjhMNoUIIUTpwOJ4yRPthcTmpxGhznbd5dRLBXdCbg4kCOZahHEXMJYL2ZZ7dgBFWL8RIcPUEv38hcW1xV4ChL4Cb9hJ7sA+ux9gUzz5JoD1Cc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770914261; c=relaxed/simple; bh=bNYJhF/vrfnqfdjS1Xo0X9csm/vyWSOMWcUkGWy2eqI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To:Cc; b=bFF4SK8UFPlKzkJTZvQLRQ5FN71SVtFvhJWZl7ZH3oG9P0rSFISrARw33zYEwU1kQ7+I8g3WqYkKv6tvQes/khbk+8WlcOcZR/OHoAaZePthbTQbig09TWyGSh1NDkk9g8+oku0fgb9cvPiBtmSd16Kbgr6/wxIWb45E56OkhEQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=dzJRB6dG; arc=none smtp.client-ip=209.85.214.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="dzJRB6dG" Received: by mail-pl1-f175.google.com with SMTP id d9443c01a7336-2a7b47a5460so12165825ad.1 for ; Thu, 12 Feb 2026 08:37:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1770914260; x=1771519060; darn=vger.kernel.org; h=cc:to:message-id:content-transfer-encoding:mime-version:subject :date:from:from:to:cc:subject:date:message-id:reply-to; bh=RshJ2GX59bxxjI+XoqRN3YBnxOSZhELYxBIuUEvTR0k=; b=dzJRB6dGPRJ3/lYhnj/U+zlJS+Ux7Qez5+p2k1tsest8HMOr8fVvRE7qEWI9knqkWX 6faCRfYKYPO3ipII2coxhA1ViqxrYoImlWQspUkWAC1OhBcB4ixKil+W3cPrt2Ln/e4i 0MTvF74XqZJCusYtY3PW4msLE8K9U2ddSg0ISjl8+VNcKkHP4O8EGa6uxA1/udLNByJ3 euktrEXkeR0gibd8RorIDxXPnNLfpZbBX5ouG/s3N5DPBwjLNYD5DgtoMOkchQjLjDQt zZTDYNXavCg+IvZzDElqM+umcHEx6nxmXwMuLJ26cicwHMto3T8YgEEjeorubcNwsGHa 49HA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770914260; x=1771519060; h=cc:to:message-id:content-transfer-encoding:mime-version:subject :date:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=RshJ2GX59bxxjI+XoqRN3YBnxOSZhELYxBIuUEvTR0k=; b=DEQYzxyhVE85Mw99zZFmfgp9esPDDHWY1pVErcTg5XAUXkKmHbw38xyruXrdctw7i2 1xVDy+sjnLRznF4PWvV/a48Pop8nx6swQcx9Vx7kMtgjMzakhT6ZDRoxyfZNxYj2FlJx 5gHU51XeYATruRPfNDYZZl4onDyidpzaVzMewz/75l2eG6N4bGTFPVhxoB+9LD/Fe6vl rO/bLOY6E1tvXSjxZK8ipHOkzuOA5Qv//ezTkg3zL+Pj+ACbWPEduI666E21cTlLyKhY DOJk+dBtQSEuFPorwTqqnafC9+W9OjrUgZIL8g5VBcRxjN0Q2mwym0uFKqOdaPVqlP2z KpLg== X-Forwarded-Encrypted: i=1; AJvYcCXQcMMOL1E+sDNcpFfgyZx2Qtrn1eA5XcQs3NCRBVjsrl/CiaQsBiZcQScOXF0geacOyu+ABZ2oKQvafeU=@vger.kernel.org X-Gm-Message-State: AOJu0YznuNt0N2NLzbR3u7cu3T9A6qEHOhBfUfyr185qWDUJwLt544Si KGaRV3km5daZ5w22RxgHa+C9Ga1KTmX/5JcmmHl+8oVwnmsncVl1pRyz X-Gm-Gg: AZuq6aIm/tjwyUPOZJih5pMolDlvq/mSckpZC3NWwYO5AhM33VXcayiucfVlA7x4wWp vsNRKSZvWlg472NSk03ataQ3+bhot4VBwfPDZOiPElBT6cfOR8/SCIQru/ZktYKgKDe8YLiiJMs 4VDh5hq+jMo3DQShWgEO5nbN/Tee5ax7gunTzhDV2nojYETQj5e2P02Plfq7esKIGA/mHM2Gv+S 6MkjqOys5e3aMXgbzvt4NCppbNtkLPYtvRKMBcffeUB2KdDrM/7uMr7fhova2p378RjzJl4G/19 YnC2Hzvu9qPp65KNKsy1tY1uzS1JZM1EA6308mlCOIxgSpo6GFRyFAW3DtdutGwCOJGYz4ZpKWu +Elo4R7fR7shCx73icwIHZssO8gYhKKuo8Ga2qyzWVjyPy+F80M8xNUblVLNdttxX4YusBPUOFl JlshjAPiVQjj9oHaax2Dkf0BWdv06WfWo= X-Received: by 2002:a17:903:28c:b0:2aa:d2f4:9c11 with SMTP id d9443c01a7336-2ab3a635772mr31062095ad.5.1770914259478; Thu, 12 Feb 2026 08:37:39 -0800 (PST) Received: from [172.16.80.107] ([210.228.119.9]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2ab2997bc2fsm60525635ad.76.2026.02.12.08.37.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 12 Feb 2026 08:37:38 -0800 (PST) From: Ryota Sakamoto Date: Fri, 13 Feb 2026 01:37:32 +0900 Subject: [PATCH] kunit: Add --list_suites to show suites Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260213-kunit-list_suites-v1-1-6e6394faf4c7@gmail.com> X-B4-Tracking: v=1; b=H4sIAAAAAAAC/x3MQQqAIBBA0avIrBNUqKCrRETpVENh4WgE0t2Tl m/xfwbGQMjQiQwBb2I6fYGuBNht8itKcsVglGmU0VruyVOUB3EcOVFElnZStrZzi65xULor4EL P/+yH9/0Ab+iRKWMAAAA= X-Change-ID: 20260211-kunit-list_suites-ca0c5cb7ed6d To: Brendan Higgins , David Gow , Rae Moar Cc: linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com, linux-kernel@vger.kernel.org, Ryota Sakamoto X-Mailer: b4 0.14.2 Currently, kunit.py allows listing all individual tests via --list_tests. However, users often need to see only the available test suites. Add --list_suites to show suites. This option parses the test list output from the kernel and prints only the suite names. Example of the output of --list_suites: example_init miscdev_init printk-ringbuffer Signed-off-by: Ryota Sakamoto Reviewed-by: David Gow --- tools/testing/kunit/kunit.py | 16 ++++++++++++++-- tools/testing/kunit/kunit_tool_test.py | 16 +++++++++++++--- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/tools/testing/kunit/kunit.py b/tools/testing/kunit/kunit.py index 4ec5ecba6d49b1ba3360515a2b66a2a98813bd18..742f5c555666021f61c44a98229= bb34f9664d3c2 100755 --- a/tools/testing/kunit/kunit.py +++ b/tools/testing/kunit/kunit.py @@ -63,6 +63,7 @@ class KunitExecRequest(KunitParseRequest): run_isolated: Optional[str] list_tests: bool list_tests_attr: bool + list_suites: bool =20 @dataclass class KunitRequest(KunitExecRequest, KunitBuildRequest): @@ -168,6 +169,12 @@ def exec_tests(linux: kunit_kernel.LinuxSourceTree, re= quest: KunitExecRequest) - for line in attr_output: print(line.rstrip()) return KunitResult(status=3DKunitStatus.SUCCESS, elapsed_time=3D0.0) + if request.list_suites: + tests =3D _list_tests(linux, request) + output =3D _suites_from_test_list(tests) + for line in output: + print(line.rstrip()) + return KunitResult(status=3DKunitStatus.SUCCESS, elapsed_time=3D0.0) if request.run_isolated: tests =3D _list_tests(linux, request) if request.run_isolated =3D=3D 'test': @@ -438,6 +445,9 @@ def add_exec_opts(parser: argparse.ArgumentParser) -> N= one: parser.add_argument('--list_tests_attr', help=3D'If set, list all tests a= nd test ' 'attributes.', action=3D'store_true') + parser.add_argument('--list_suites', help=3D'If set, list all suites that= will be ' + 'run.', + action=3D'store_true') =20 def add_parse_opts(parser: argparse.ArgumentParser) -> None: parser.add_argument('--raw_output', help=3D'If set don\'t parse output fr= om kernel. ' @@ -501,7 +511,8 @@ def run_handler(cli_args: argparse.Namespace) -> None: kernel_args=3Dcli_args.kernel_args, run_isolated=3Dcli_args.run_isolated, list_tests=3Dcli_args.list_tests, - list_tests_attr=3Dcli_args.list_tests_attr) + list_tests_attr=3Dcli_args.list_tests_attr, + list_suites=3Dcli_args.list_suites) result =3D run_tests(linux, request) if result.status !=3D KunitStatus.SUCCESS: sys.exit(1) @@ -550,7 +561,8 @@ def exec_handler(cli_args: argparse.Namespace) -> None: kernel_args=3Dcli_args.kernel_args, run_isolated=3Dcli_args.run_isolated, list_tests=3Dcli_args.list_tests, - list_tests_attr=3Dcli_args.list_tests_attr) + list_tests_attr=3Dcli_args.list_tests_attr, + list_suites=3Dcli_args.list_suites) result =3D exec_tests(linux, exec_request) stdout.print_with_timestamp(( 'Elapsed time: %.3fs\n') % (result.elapsed_time)) diff --git a/tools/testing/kunit/kunit_tool_test.py b/tools/testing/kunit/k= unit_tool_test.py index b67408147c1faaab12b168aabe3bfba8bf1b00aa..a7402afd33743455b3ece72a495= a6c8769ed51af 100755 --- a/tools/testing/kunit/kunit_tool_test.py +++ b/tools/testing/kunit/kunit_tool_test.py @@ -855,7 +855,7 @@ class KUnitMainTest(unittest.TestCase): self.linux_source_mock.run_kernel.return_value =3D ['TAP version 14', 'i= nit: random output'] + want =20 got =3D kunit._list_tests(self.linux_source_mock, - kunit.KunitExecRequest(None, None, False, False, '.kunit', 300, '= suite*', '', None, None, 'suite', False, False)) + kunit.KunitExecRequest(None, None, False, False, '.kunit', 300, '= suite*', '', None, None, 'suite', False, False, False)) self.assertEqual(got, want) # Should respect the user's filter glob when listing tests. self.linux_source_mock.run_kernel.assert_called_once_with( @@ -868,7 +868,7 @@ class KUnitMainTest(unittest.TestCase): =20 # Should respect the user's filter glob when listing tests. mock_tests.assert_called_once_with(mock.ANY, - kunit.KunitExecRequest(None, None, False, False, '.kunit', 300, '= suite*.test*', '', None, None, 'suite', False, False)) + kunit.KunitExecRequest(None, None, False, False, '.kunit', 300, '= suite*.test*', '', None, None, 'suite', False, False, False)) self.linux_source_mock.run_kernel.assert_has_calls([ mock.call(args=3DNone, build_dir=3D'.kunit', filter_glob=3D'suite.test*= ', filter=3D'', filter_action=3DNone, timeout=3D300), mock.call(args=3DNone, build_dir=3D'.kunit', filter_glob=3D'suite2.test= *', filter=3D'', filter_action=3DNone, timeout=3D300), @@ -881,13 +881,23 @@ class KUnitMainTest(unittest.TestCase): =20 # Should respect the user's filter glob when listing tests. mock_tests.assert_called_once_with(mock.ANY, - kunit.KunitExecRequest(None, None, False, False, '.kunit', 300, '= suite*', '', None, None, 'test', False, False)) + kunit.KunitExecRequest(None, None, False, False, '.kunit', 300, '= suite*', '', None, None, 'test', False, False, False)) self.linux_source_mock.run_kernel.assert_has_calls([ mock.call(args=3DNone, build_dir=3D'.kunit', filter_glob=3D'suite.test1= ', filter=3D'', filter_action=3DNone, timeout=3D300), mock.call(args=3DNone, build_dir=3D'.kunit', filter_glob=3D'suite.test2= ', filter=3D'', filter_action=3DNone, timeout=3D300), mock.call(args=3DNone, build_dir=3D'.kunit', filter_glob=3D'suite2.test= 1', filter=3D'', filter_action=3DNone, timeout=3D300), ]) =20 + @mock.patch.object(kunit, '_list_tests') + @mock.patch.object(sys, 'stdout', new_callable=3Dio.StringIO) + def test_list_suites(self, mock_stdout, mock_tests): + mock_tests.return_value =3D ['suite.test1', 'suite.test2', 'suite2.test1= '] + kunit.main(['run', '--list_suites']) + + want =3D ['suite', 'suite2'] + output =3D mock_stdout.getvalue().split() + self.assertEqual(output, want) + @mock.patch.object(sys, 'stdout', new_callable=3Dio.StringIO) def test_list_cmds(self, mock_stdout): kunit.main(['--list-cmds']) --- base-commit: db0c35ca36526f3072affcb573631ccf8c85f827 change-id: 20260211-kunit-list_suites-ca0c5cb7ed6d Best regards, --=20 Ryota Sakamoto