Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/124469/?format=api
http://patches.dpdk.org/api/patches/124469/?format=api", "web_url": "http://patches.dpdk.org/project/dpdk/patch/20230223152840.634183-9-juraj.linkes@pantheon.tech/", "project": { "id": 1, "url": "http://patches.dpdk.org/api/projects/1/?format=api", "name": "DPDK", "link_name": "dpdk", "list_id": "dev.dpdk.org", "list_email": "dev@dpdk.org", "web_url": "http://core.dpdk.org", "scm_url": "git://dpdk.org/dpdk", "webscm_url": "http://git.dpdk.org/dpdk", "list_archive_url": "https://inbox.dpdk.org/dev", "list_archive_url_format": "https://inbox.dpdk.org/dev/{}", "commit_url_format": "" }, "msgid": "<20230223152840.634183-9-juraj.linkes@pantheon.tech>", "list_archive_url": "https://inbox.dpdk.org/dev/20230223152840.634183-9-juraj.linkes@pantheon.tech", "date": "2023-02-23T15:28:38", "name": "[v5,08/10] dts: add test suite config and runner", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": true, "hash": "36835256dcc4860d28124dc7a37cf3ab32449daf", "submitter": { "id": 1626, "url": "http://patches.dpdk.org/api/people/1626/?format=api", "name": "Juraj Linkeš", "email": "juraj.linkes@pantheon.tech" }, "delegate": { "id": 1, "url": "http://patches.dpdk.org/api/users/1/?format=api", "username": "tmonjalo", "first_name": "Thomas", "last_name": "Monjalon", "email": "thomas@monjalon.net" }, "mbox": "http://patches.dpdk.org/project/dpdk/patch/20230223152840.634183-9-juraj.linkes@pantheon.tech/mbox/", "series": [ { "id": 27159, "url": "http://patches.dpdk.org/api/series/27159/?format=api", "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=27159", "date": "2023-02-23T15:28:30", "name": "dts: add hello world testcase", "version": 5, "mbox": "http://patches.dpdk.org/series/27159/mbox/" } ], "comments": "http://patches.dpdk.org/api/patches/124469/comments/", "check": "success", "checks": "http://patches.dpdk.org/api/patches/124469/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<dev-bounces@dpdk.org>", "X-Original-To": "patchwork@inbox.dpdk.org", "Delivered-To": "patchwork@inbox.dpdk.org", "Received": [ "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 1A56941D52;\n\tThu, 23 Feb 2023 16:29:57 +0100 (CET)", "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id B35F043063;\n\tThu, 23 Feb 2023 16:29:02 +0100 (CET)", "from mail-ed1-f45.google.com (mail-ed1-f45.google.com\n [209.85.208.45]) by mails.dpdk.org (Postfix) with ESMTP id 25FBF42F94\n for <dev@dpdk.org>; Thu, 23 Feb 2023 16:28:54 +0100 (CET)", "by mail-ed1-f45.google.com with SMTP id o12so43884288edb.9\n for <dev@dpdk.org>; Thu, 23 Feb 2023 07:28:54 -0800 (PST)", "from localhost.localdomain ([84.245.121.112])\n by smtp.gmail.com with ESMTPSA id\n r6-20020a50c006000000b004af6a8617ffsm1158892edb.46.2023.02.23.07.28.52\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Thu, 23 Feb 2023 07:28:53 -0800 (PST)" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=pantheon-tech.20210112.gappssmtp.com; s=20210112;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=a6Yg1HAeHLjoNVENaWlot1vgqykBX7d+YQMwrK1auvg=;\n b=fiYm/M0OWWRyuVAL2JUrEv34K1bWhJ1KH0VZpVIe5z/8R/yhJMme/Ccod6L9NOSI9Z\n mwQkCkNSNR/oFWuJleINBjo/Kw8ncOKmvUk81opecJjzBych/Dq4SmAM8HST6xX9Pyar\n nRlScAegEAHbCfhEjohj6MJ9D7qgeTbEh7I1rYnyGVWjjkiRmmw7+3CuicnBG57UmAVN\n PVOI+nLCe5GZg5y13M0sMSYeE8LFkeJmN8TOWNeF8jSy4MGv8v2LD4/rWymFrptjjvjz\n u+K8lUjzulZbbI2L6iQYueikqxzGFDruQLpEAP1FEmLvS5hsD3YiI+5hLzhK6RmXTKRv\n mYbA==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20210112;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc\n :subject:date:message-id:reply-to;\n bh=a6Yg1HAeHLjoNVENaWlot1vgqykBX7d+YQMwrK1auvg=;\n b=opQ1V3wciA7o0P8OTz0n6iqJzX/rML0AOyb5mPG38Io6Jggbor7lGqKqvIMM6Id/Uh\n bsExX6i76JRG9JmNDtmqPCu09tkRQHARGo7EKBBgfpL/BHpnLcRQwcz56KtO1z25NE47\n K6KKtk0BkFGlPkxBn4lM66128Mp3Bej8Qj5bp0XQJDHWN0povtW+8MRK129oK5DHvDEa\n /NppCWBNn3PPS/xRsnReILwyCb3OjHqIpvta4JvXjs2PJyF9paZJ/UBVwZ7QDkNCVazM\n O3gzxaVZ4H4MTWEOfE4QVl2GTuMAiQ4ZmCRBCE5XBFUB07b/+wnD0ukTnE8+Ro7aDfeB\n dVeA==", "X-Gm-Message-State": "AO0yUKVmfIrBDrtIE3v3hsV3LZbais2sGJZxlqr6kwItJzK8/KESxTFb\n q49p28omVQyUVru6lY71VGqMCQ==", "X-Google-Smtp-Source": "\n AK7set8nI+KpMRke3uWv3841rIMBlLIk5jHLAeDjTHDOrlvxKCPv9Vjie/c4q1KerLpwHtNqja2Qig==", "X-Received": "by 2002:a05:6402:6ca:b0:4ac:b32d:3dab with SMTP id\n n10-20020a05640206ca00b004acb32d3dabmr9527047edy.29.1677166133757;\n Thu, 23 Feb 2023 07:28:53 -0800 (PST)", "From": "=?utf-8?q?Juraj_Linke=C5=A1?= <juraj.linkes@pantheon.tech>", "To": "thomas@monjalon.net, Honnappa.Nagarahalli@arm.com, lijuan.tu@intel.com,\n bruce.richardson@intel.com, probb@iol.unh.edu", "Cc": "dev@dpdk.org, =?utf-8?q?Juraj_Linke=C5=A1?= <juraj.linkes@pantheon.tech>", "Subject": "[PATCH v5 08/10] dts: add test suite config and runner", "Date": "Thu, 23 Feb 2023 16:28:38 +0100", "Message-Id": "<20230223152840.634183-9-juraj.linkes@pantheon.tech>", "X-Mailer": "git-send-email 2.30.2", "In-Reply-To": "<20230223152840.634183-1-juraj.linkes@pantheon.tech>", "References": "<20230213152846.284191-1-juraj.linkes@pantheon.tech>\n <20230223152840.634183-1-juraj.linkes@pantheon.tech>", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=UTF-8", "Content-Transfer-Encoding": "8bit", "X-BeenThere": "dev@dpdk.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "DPDK patches and discussions <dev.dpdk.org>", "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>", "List-Archive": "<http://mails.dpdk.org/archives/dev/>", "List-Post": "<mailto:dev@dpdk.org>", "List-Help": "<mailto:dev-request@dpdk.org?subject=help>", "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>", "Errors-To": "dev-bounces@dpdk.org" }, "content": "The config allows users to specify which test suites and test cases\nwithin test suites to run.\nAlso add test suite running capabilities to dts runner.\n\nSigned-off-by: Juraj Linkeš <juraj.linkes@pantheon.tech>\n---\n dts/conf.yaml | 2 ++\n dts/framework/config/__init__.py | 29 +++++++++++++++-\n dts/framework/config/conf_yaml_schema.json | 40 ++++++++++++++++++++++\n dts/framework/dts.py | 19 ++++++++++\n dts/framework/test_suite.py | 24 ++++++++++++-\n 5 files changed, 112 insertions(+), 2 deletions(-)", "diff": "diff --git a/dts/conf.yaml b/dts/conf.yaml\nindex 75e33e8ccf..a9bd8a3ecf 100644\n--- a/dts/conf.yaml\n+++ b/dts/conf.yaml\n@@ -10,6 +10,8 @@ executions:\n compiler_wrapper: ccache\n perf: false\n func: true\n+ test_suites:\n+ - hello_world\n system_under_test: \"SUT 1\"\n nodes:\n - name: \"SUT 1\"\ndiff --git a/dts/framework/config/__init__.py b/dts/framework/config/__init__.py\nindex 544fceca6a..ebb0823ff5 100644\n--- a/dts/framework/config/__init__.py\n+++ b/dts/framework/config/__init__.py\n@@ -12,7 +12,7 @@\n import pathlib\n from dataclasses import dataclass\n from enum import Enum, auto, unique\n-from typing import Any\n+from typing import Any, TypedDict\n \n import warlock # type: ignore\n import yaml\n@@ -128,11 +128,34 @@ def from_dict(d: dict) -> \"BuildTargetConfiguration\":\n )\n \n \n+class TestSuiteConfigDict(TypedDict):\n+ suite: str\n+ cases: list[str]\n+\n+\n+@dataclass(slots=True, frozen=True)\n+class TestSuiteConfig:\n+ test_suite: str\n+ test_cases: list[str]\n+\n+ @staticmethod\n+ def from_dict(\n+ entry: str | TestSuiteConfigDict,\n+ ) -> \"TestSuiteConfig\":\n+ if isinstance(entry, str):\n+ return TestSuiteConfig(test_suite=entry, test_cases=[])\n+ elif isinstance(entry, dict):\n+ return TestSuiteConfig(test_suite=entry[\"suite\"], test_cases=entry[\"cases\"])\n+ else:\n+ raise TypeError(f\"{type(entry)} is not valid for a test suite config.\")\n+\n+\n @dataclass(slots=True, frozen=True)\n class ExecutionConfiguration:\n build_targets: list[BuildTargetConfiguration]\n perf: bool\n func: bool\n+ test_suites: list[TestSuiteConfig]\n system_under_test: NodeConfiguration\n \n @staticmethod\n@@ -140,6 +163,9 @@ def from_dict(d: dict, node_map: dict) -> \"ExecutionConfiguration\":\n build_targets: list[BuildTargetConfiguration] = list(\n map(BuildTargetConfiguration.from_dict, d[\"build_targets\"])\n )\n+ test_suites: list[TestSuiteConfig] = list(\n+ map(TestSuiteConfig.from_dict, d[\"test_suites\"])\n+ )\n sut_name = d[\"system_under_test\"]\n assert sut_name in node_map, f\"Unknown SUT {sut_name} in execution {d}\"\n \n@@ -147,6 +173,7 @@ def from_dict(d: dict, node_map: dict) -> \"ExecutionConfiguration\":\n build_targets=build_targets,\n perf=d[\"perf\"],\n func=d[\"func\"],\n+ test_suites=test_suites,\n system_under_test=node_map[sut_name],\n )\n \ndiff --git a/dts/framework/config/conf_yaml_schema.json b/dts/framework/config/conf_yaml_schema.json\nindex 878ca3aec2..ca2d4a1ef2 100644\n--- a/dts/framework/config/conf_yaml_schema.json\n+++ b/dts/framework/config/conf_yaml_schema.json\n@@ -93,6 +93,32 @@\n \"required\": [\n \"amount\"\n ]\n+ },\n+ \"test_suite\": {\n+ \"type\": \"string\",\n+ \"enum\": [\n+ \"hello_world\"\n+ ]\n+ },\n+ \"test_target\": {\n+ \"type\": \"object\",\n+ \"properties\": {\n+ \"suite\": {\n+ \"$ref\": \"#/definitions/test_suite\"\n+ },\n+ \"cases\": {\n+ \"type\": \"array\",\n+ \"description\": \"If specified, only this subset of test suite's test cases will be run. Unknown test cases will be silently ignored.\",\n+ \"items\": {\n+ \"type\": \"string\"\n+ },\n+ \"minimum\": 1\n+ }\n+ },\n+ \"required\": [\n+ \"suite\"\n+ ],\n+ \"additionalProperties\": false\n }\n },\n \"type\": \"object\",\n@@ -172,6 +198,19 @@\n \"type\": \"boolean\",\n \"description\": \"Enable functional testing.\"\n },\n+ \"test_suites\": {\n+ \"type\": \"array\",\n+ \"items\": {\n+ \"oneOf\": [\n+ {\n+ \"$ref\": \"#/definitions/test_suite\"\n+ },\n+ {\n+ \"$ref\": \"#/definitions/test_target\"\n+ }\n+ ]\n+ }\n+ },\n \"system_under_test\": {\n \"$ref\": \"#/definitions/node_name\"\n }\n@@ -181,6 +220,7 @@\n \"build_targets\",\n \"perf\",\n \"func\",\n+ \"test_suites\",\n \"system_under_test\"\n ]\n },\ndiff --git a/dts/framework/dts.py b/dts/framework/dts.py\nindex 6ea7c6e736..f98000450f 100644\n--- a/dts/framework/dts.py\n+++ b/dts/framework/dts.py\n@@ -8,6 +8,7 @@\n from .config import CONFIGURATION, BuildTargetConfiguration, ExecutionConfiguration\n from .exception import DTSError, ErrorSeverity\n from .logger import DTSLOG, getLogger\n+from .test_suite import get_test_suites\n from .testbed_model import SutNode\n from .utils import check_dts_python_version\n \n@@ -132,6 +133,24 @@ def _run_suites(\n with possibly only a subset of test cases.\n If no subset is specified, run all test cases.\n \"\"\"\n+ for test_suite_config in execution.test_suites:\n+ try:\n+ full_suite_path = f\"tests.TestSuite_{test_suite_config.test_suite}\"\n+ test_suite_classes = get_test_suites(full_suite_path)\n+ suites_str = \", \".join((x.__name__ for x in test_suite_classes))\n+ dts_logger.debug(\n+ f\"Found test suites '{suites_str}' in '{full_suite_path}'.\"\n+ )\n+ except Exception as e:\n+ dts_logger.exception(\"An error occurred when searching for test suites.\")\n+ errors.append(e)\n+\n+ else:\n+ for test_suite_class in test_suite_classes:\n+ test_suite = test_suite_class(\n+ sut_node, test_suite_config.test_cases, execution.func, errors\n+ )\n+ test_suite.run()\n \n \n def _exit_dts() -> None:\ndiff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py\nindex 9002d43297..12bf3b6420 100644\n--- a/dts/framework/test_suite.py\n+++ b/dts/framework/test_suite.py\n@@ -6,12 +6,13 @@\n Base class for creating DTS test cases.\n \"\"\"\n \n+import importlib\n import inspect\n import re\n from collections.abc import MutableSequence\n from types import MethodType\n \n-from .exception import SSHTimeoutError, TestCaseVerifyError\n+from .exception import ConfigurationError, SSHTimeoutError, TestCaseVerifyError\n from .logger import DTSLOG, getLogger\n from .settings import SETTINGS\n from .testbed_model import SutNode\n@@ -226,3 +227,24 @@ def _execute_test_case(self, test_case_method: MethodType) -> bool:\n raise KeyboardInterrupt(\"Stop DTS\")\n \n return result\n+\n+\n+def get_test_suites(testsuite_module_path: str) -> list[type[TestSuite]]:\n+ def is_test_suite(object) -> bool:\n+ try:\n+ if issubclass(object, TestSuite) and object is not TestSuite:\n+ return True\n+ except TypeError:\n+ return False\n+ return False\n+\n+ try:\n+ testcase_module = importlib.import_module(testsuite_module_path)\n+ except ModuleNotFoundError as e:\n+ raise ConfigurationError(\n+ f\"Test suite '{testsuite_module_path}' not found.\"\n+ ) from e\n+ return [\n+ test_suite_class\n+ for _, test_suite_class in inspect.getmembers(testcase_module, is_test_suite)\n+ ]\n", "prefixes": [ "v5", "08/10" ] }{ "id": 124469, "url": "