DPDK CI discussions
 help / color / mirror / Atom feed
From: ohilyard@iol.unh.edu
To: ci@dpdk.org
Cc: thomas@monjalon.net, Owen Hilyard <ohilyard@iol.unh.edu>
Subject: [dpdk-ci] [PATCH 2/2] patch-tagging: Added execution file creator
Date: Fri,  5 Feb 2021 15:37:25 -0500	[thread overview]
Message-ID: <20210205203725.143804-2-ohilyard@iol.unh.edu> (raw)
In-Reply-To: <20210205203725.143804-1-ohilyard@iol.unh.edu>

From: Owen Hilyard <ohilyard@iol.unh.edu>

The new config file contains mappings from a tag to a list of tests to be run. This will be where the community can configure which test suites should run for which tag. Additional tags can be created freely, since the script just performs a dictionary lookup.

The script uses the provided execution file for 2 things. First, uses it to provide all of the other fields in all of the configs. This is to allow preserving configuration information for dts. The otehr way the scripts are used is that the lists of test suites already there is treated as a filter. This was done to allow a CI implimentation to only run test suites that they have verified are functional on their hardware. The resulting execution file will have a "test_suites" field which is the lexographically sorted intersection between this "filter" list and the tests that are configured to run for the provided tags. The script will also append ":func=true:perf=false" or ":func=false:perf=true" onto the parameters as appropriate.

Signed-off-by: Owen Hilyard <ohilyard@iol.unh.edu>
---
 config/tests_for_tag.cfg                     |  33 ++++++
 tools/create_new_execution_file_from_tags.py | 113 +++++++++++++++++++
 2 files changed, 146 insertions(+)
 create mode 100644 config/tests_for_tag.cfg
 create mode 100755 tools/create_new_execution_file_from_tags.py

diff --git a/config/tests_for_tag.cfg b/config/tests_for_tag.cfg
new file mode 100644
index 0000000..01c497d
--- /dev/null
+++ b/config/tests_for_tag.cfg
@@ -0,0 +1,33 @@
+[functional]
+core = dynamic_config,
+       link_status_interrupt,
+       mac_filter,
+       mtu_update,
+       scatter,
+       stats_checks,
+       stats_checks,
+       unit_tests_mbuf
+driver = dynamic_config,
+       link_status_interrupt,
+       mac_filter,
+       mtu_update,
+       scatter,
+       stats_checks,
+       stats_checks,
+       unit_tests_mbuf
+application = dynamic_config,
+       link_status_interrupt,
+       mac_filter,
+       mtu_update,
+       scatter,
+       stats_checks,
+       stats_checks,
+       unit_tests_mbuf
+; Nothing in documentation
+documentation =
+
+[performance]
+core = nic_single_core_perf
+driver = nic_single_core_perf
+application = nic_single_core_perf
+documentation =
diff --git a/tools/create_new_execution_file_from_tags.py b/tools/create_new_execution_file_from_tags.py
new file mode 100755
index 0000000..af24615
--- /dev/null
+++ b/tools/create_new_execution_file_from_tags.py
@@ -0,0 +1,113 @@
+#!/usr/bin/env python3
+
+# BSD LICENSE
+#
+# Copyright(c) 2020 Intel Corporation. All rights reserved.
+# Copyright © 2018[, 2019] The University of New Hampshire. All rights reserved.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+#   * Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+#   * Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in
+#     the documentation and/or other materials provided with the
+#     distribution.
+#   * Neither the name of Intel Corporation nor the names of its
+#     contributors may be used to endorse or promote products derived
+#     from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+import sys
+from enum import Enum
+
+import itertools
+from configparser import ConfigParser
+from typing import List, Dict, Set
+import argparse
+
+
+def parse_comma_delimited_list_from_string(mod_str: str) -> List[str]:
+    return list(map(str.strip, mod_str.split(',')))
+
+
+def map_tags_to_tests(tags: List[str], test_map: Dict[str, List[str]]) -> Set[str]:
+    """
+    Returns a list that is the union of all of the map lookups.
+    """
+    try:
+        return set(
+            filter(lambda test: test != '', set(itertools.chain.from_iterable(map(lambda tag: test_map[tag], tags)))))
+    except KeyError as e:
+        print(f'Tag {e} is not present in tests_for_tag.cfg')
+        exit(1)
+
+class TestingType(Enum):
+    functional = 'functional'
+    performance = 'performance'
+
+    def __str__(self):
+        return self.value
+
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser(
+        description='Take a template execution file and add the relevant tests'
+                    ' for the given tags to it, creating a new file.')
+    parser.add_argument('config_file_path', help='The path to tests_for_tag.cfg', default='config/tests_for_tag.cfg')
+    parser.add_argument('template_execution_file', help='The path to the execution file to use as a template')
+    parser.add_argument('output_path', help='The path to the output execution file')
+    parser.add_argument('testing_type', type=TestingType, choices=list(TestingType),
+                        help='What type of testing to create an execution file for')
+    parser.add_argument('tags', metavar='tag', type=str, nargs='+', help='The tags to create an execution file for.')
+
+    args = parser.parse_args()
+
+    tag_to_test_map_parser = ConfigParser()
+    tag_to_test_map_parser.read(args.config_file_path)
+
+    template_execution_file_parser = ConfigParser()
+    template_execution_file_parser.read(args.template_execution_file)
+
+    test_map = {key: parse_comma_delimited_list_from_string(value.strip()) for key, value in
+                tag_to_test_map_parser[str(args.testing_type)].items()}
+
+    tests = map_tags_to_tests(args.tags, test_map)
+
+    try:
+        output_file = open(args.output_path, 'x')
+    except FileExistsError:
+        output_file = open(args.output_path, 'w')
+
+    for execution_plan in template_execution_file_parser:
+        # The DEFAULT section is always present and contains top-level items, so it needs to be ignored
+        if execution_plan != 'DEFAULT':
+            test_allowlist = parse_comma_delimited_list_from_string(template_execution_file_parser[execution_plan]['test_suites'])
+            tests_to_run = list(set(test_allowlist).intersection(tests))
+            tests_to_run.sort()
+            template_execution_file_parser[execution_plan]['test_suites'] = ", ".join(tests_to_run)
+
+            if args.testing_type == TestingType.functional:
+                template_execution_file_parser[execution_plan]['parameters'] += ':func=true:perf=false'
+            elif args.testing_type == TestingType.performance:
+                template_execution_file_parser[execution_plan]['parameters'] += ':func=false:perf=true'
+            else:
+                # This code should be unreachable, since this is checked at the top of the file
+                print("Fatal error: testing type is neither performance nor functional", file=sys.stderr)
+                exit(1)
+
+    template_execution_file_parser.write(output_file)
+
-- 
2.27.0


      reply	other threads:[~2021-02-05 20:37 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-05 20:37 [dpdk-ci] [PATCH 1/2] patch-tagging: Added tagging script for patches ohilyard
2021-02-05 20:37 ` ohilyard [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210205203725.143804-2-ohilyard@iol.unh.edu \
    --to=ohilyard@iol.unh.edu \
    --cc=ci@dpdk.org \
    --cc=thomas@monjalon.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).