From f967f0c60797bd39681efa1ef8c50271eb444abf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Doktor?= Date: Wed, 3 May 2017 16:03:57 +0200 Subject: [PATCH] variants: Introduce "avocado variants" command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "avocado multiplex" command is misleading as multiplexation is only the generic concept used by one of our varianter plugins implementations. Let's change the command name to "avocado variants" which better reflects what is it used for. As people depend on "avocado multiplex" command let's keep both of them for now to give people time till Avocado 52.0 to migrate. Signed-off-by: Lukáš Doktor --- avocado/plugins/multiplex.py | 103 ++------------------- avocado/plugins/variants.py | 121 +++++++++++++++++++++++++ avocado/plugins/yaml_to_mux.py | 2 +- docs/source/Replay.rst | 4 +- docs/source/TestParameters.rst | 4 +- docs/source/WritingTests.rst | 4 +- selftests/functional/test_multiplex.py | 6 +- setup.py | 1 + 8 files changed, 141 insertions(+), 104 deletions(-) create mode 100644 avocado/plugins/variants.py diff --git a/avocado/plugins/multiplex.py b/avocado/plugins/multiplex.py index 936bb68b..881a3784 100644 --- a/avocado/plugins/multiplex.py +++ b/avocado/plugins/multiplex.py @@ -13,107 +13,22 @@ # Author: Lucas Meneghel Rodrigues import logging -import sys -from avocado.core import exit_codes -from avocado.core.plugin_interfaces import CLICmd -from avocado.core.settings import settings +from .variants import Variants -_VERBOSITY_LEVELS = {"none": 0, "brief": 1, "normal": 2, "verbose": 3, - "full": 4, "max": 99} - - -def map_verbosity_level(level): - if level.isdigit(): - return int(level) - level = level.lower() - if level in _VERBOSITY_LEVELS: - return _VERBOSITY_LEVELS[level] - else: - raise ValueError - - -class Multiplex(CLICmd): +class Multiplex(Variants): """ - Implements the avocado 'multiplex' subcommand + DEPRECATED version of the "avocado multiplex" command which is replaced + by "avocado variants" one. """ - name = 'multiplex' - description = "Tool to analyze and visualize test variants and params" - - def __init__(self, *args, **kwargs): - super(Multiplex, self).__init__(*args, **kwargs) - - def configure(self, parser): - parser = super(Multiplex, self).configure(parser) - verbosity_levels = ("(positive integer - 0, 1, ... - or %s)" - % ", ".join(sorted(_VERBOSITY_LEVELS, - key=lambda _: _VERBOSITY_LEVELS[_]))) - parser.add_argument("--summary", type=map_verbosity_level, - help="Verbosity of the variants summary. " + - verbosity_levels) - parser.add_argument("--variants", type=map_verbosity_level, - help="Verbosity of the list of variants. " + - verbosity_levels, default=1) - parser.add_argument('--system-wide', action='store_false', - default=True, dest="variants-skip-defaults", - help="Combine the files with the default " - "tree.") - parser.add_argument('-c', '--contents', action='store_true', - default=False, help="[obsoleted by --variants] " - "Shows the node content (variables)") - env_parser = parser.add_argument_group("environment view options") - env_parser.add_argument('-d', '--debug', action='store_true', - dest="mux_debug", default=False, - help="Debug the multiplex tree.") - tree_parser = parser.add_argument_group("tree view options") - tree_parser.add_argument('-t', '--tree', action='store_true', - default=False, help='[obsoleted by --summary]' - ' Shows the multiplex tree structure') - tree_parser.add_argument('-i', '--inherit', action="store_true", - help="[obsoleted by --summary] Show the " - "inherited values") + name = "multiplex" def run(self, args): log = logging.getLogger("avocado.app") - err = None - if args.tree and args.mux_debug: - err = "Option --tree is incompatible with --debug." - elif not args.tree and args.inherit: - err = "Option --inherit can be only used with --tree" - if err: - log.error(err) - sys.exit(exit_codes.AVOCADO_FAIL) - varianter = args.avocado_variants - try: - varianter.parse(args) - except (IOError, ValueError) as details: - log.error("Unable to parse varianter: %s", details) - sys.exit(exit_codes.AVOCADO_FAIL) - use_utf8 = settings.get_value("runner.output", "utf8", - key_type=bool, default=None) - summary = args.summary or 0 - variants = args.variants or 0 - - # Parse obsolete options (unsafe to combine them with new args) - if args.tree: - variants = 0 - summary += 1 - if args.contents: - summary += 1 - if args.inherit: - summary += 2 - else: - if args.contents: - variants += 2 - - # Produce the output - lines = args.avocado_variants.to_str(summary=summary, - variants=variants, - use_utf8=use_utf8) - for line in lines.splitlines(): - log.debug(line) - - sys.exit(exit_codes.AVOCADO_ALL_OK) + log.warning("The 'avocado multiplex' command is deprecated by the " + "'avocado variants' one. Please start using that one " + "instead as this will be removed in Avocado 52.0.") + super(Multiplex, self).run(args) diff --git a/avocado/plugins/variants.py b/avocado/plugins/variants.py new file mode 100644 index 00000000..2aa27773 --- /dev/null +++ b/avocado/plugins/variants.py @@ -0,0 +1,121 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# See LICENSE for more details. +# +# Copyright: Red Hat Inc. 2013-2014,2016 +# Author: Lucas Meneghel Rodrigues +# Author: Lukas Doktor + +import logging +import sys + +from avocado.core import exit_codes +from avocado.core.plugin_interfaces import CLICmd +from avocado.core.settings import settings + + +_VERBOSITY_LEVELS = {"none": 0, "brief": 1, "normal": 2, "verbose": 3, + "full": 4, "max": 99} + + +def map_verbosity_level(level): + if level.isdigit(): + return int(level) + level = level.lower() + if level in _VERBOSITY_LEVELS: + return _VERBOSITY_LEVELS[level] + else: + raise ValueError + + +class Variants(CLICmd): + + """ + Implements "variants" command to visualize/debug test variants and params + """ + + name = 'variants' + description = "Tool to analyze and visualize test variants and params" + + def __init__(self, *args, **kwargs): + super(Variants, self).__init__(*args, **kwargs) + + def configure(self, parser): + parser = super(Variants, self).configure(parser) + verbosity_levels = ("(positive integer - 0, 1, ... - or %s)" + % ", ".join(sorted(_VERBOSITY_LEVELS, + key=lambda _: _VERBOSITY_LEVELS[_]))) + parser.add_argument("--summary", type=map_verbosity_level, + help="Verbosity of the variants summary. " + + verbosity_levels) + parser.add_argument("--variants", type=map_verbosity_level, + help="Verbosity of the list of variants. " + + verbosity_levels, default=1) + parser.add_argument('--system-wide', action='store_false', + default=True, dest="variants-skip-defaults", + help="Combine the files with the default " + "tree.") + parser.add_argument('-c', '--contents', action='store_true', + default=False, help="[obsoleted by --variants] " + "Shows the node content (variables)") + env_parser = parser.add_argument_group("environment view options") + env_parser.add_argument('-d', '--debug', action='store_true', + dest="mux_debug", default=False, + help="Use debug implementation to gather more" + " information.") + tree_parser = parser.add_argument_group("tree view options") + tree_parser.add_argument('-t', '--tree', action='store_true', + default=False, help='[obsoleted by --summary]' + ' Shows the multiplex tree structure') + tree_parser.add_argument('-i', '--inherit', action="store_true", + help="[obsoleted by --summary] Show the " + "inherited values") + + def run(self, args): + log = logging.getLogger("avocado.app") + err = None + if args.tree and args.mux_debug: + err = "Option --tree is incompatible with --debug." + elif not args.tree and args.inherit: + err = "Option --inherit can be only used with --tree" + if err: + log.error(err) + sys.exit(exit_codes.AVOCADO_FAIL) + varianter = args.avocado_variants + try: + varianter.parse(args) + except (IOError, ValueError) as details: + log.error("Unable to parse varianter: %s", details) + sys.exit(exit_codes.AVOCADO_FAIL) + use_utf8 = settings.get_value("runner.output", "utf8", + key_type=bool, default=None) + summary = args.summary or 0 + variants = args.variants or 0 + + # Parse obsolete options (unsafe to combine them with new args) + if args.tree: + variants = 0 + summary += 1 + if args.contents: + summary += 1 + if args.inherit: + summary += 2 + else: + if args.contents: + variants += 2 + + # Produce the output + lines = args.avocado_variants.to_str(summary=summary, + variants=variants, + use_utf8=use_utf8) + for line in lines.splitlines(): + log.debug(line) + + sys.exit(exit_codes.AVOCADO_ALL_OK) diff --git a/avocado/plugins/yaml_to_mux.py b/avocado/plugins/yaml_to_mux.py index 9d38be29..b10c9f26 100644 --- a/avocado/plugins/yaml_to_mux.py +++ b/avocado/plugins/yaml_to_mux.py @@ -283,7 +283,7 @@ class YamlToMuxCLI(CLI): """ if not MULTIPLEX_CAPABLE: return - for name in ("run", "multiplex"): + for name in ("run", "multiplex", "variants"): subparser = parser.subcommands.choices.get(name, None) if subparser is None: continue diff --git a/docs/source/Replay.rst b/docs/source/Replay.rst index ca2d68e0..4a0f45e5 100644 --- a/docs/source/Replay.rst +++ b/docs/source/Replay.rst @@ -96,8 +96,8 @@ multiplex file:: We can replay the job as is, using ``$ avocado run --replay latest``, or replay the job ignoring the multiplex file, as below:: - $ avocado run --replay bd6aa3b --replay-ignore mux - Ignoring multiplex from source job with --replay-ignore. + $ avocado run --replay bd6aa3b --replay-ignore variants + Ignoring variants from source job with --replay-ignore. JOB ID : d5a46186ee0fb4645e3f7758814003d76c980bf9 SRC JOB ID : bd6aa3b852d4290637b5e771b371537541043d1d JOB LOG : $HOME/avocado/job-results/job-2016-01-11T22.01-d5a4618/job.log diff --git a/docs/source/TestParameters.rst b/docs/source/TestParameters.rst index 7e3c5f81..c4a75b04 100644 --- a/docs/source/TestParameters.rst +++ b/docs/source/TestParameters.rst @@ -510,7 +510,7 @@ is disabled, so the value of node name is always as written in the yaml file (unlike values, where `yes` converts to `True` and such). Nodes are organized in parent-child relationship and together they create -a tree. To view this structure use ``avocado multiplex --tree -m ``:: +a tree. To view this structure use ``avocado variants --tree -m ``:: ┗━━ run ┣━━ hw @@ -933,7 +933,7 @@ Let's take a second look at the first example:: After filters are applied (simply removes non-matching variants), leaves are gathered and all variants are generated:: - $ avocado multiplex -m examples/mux-environment.yaml + $ avocado variants -m examples/mux-environment.yaml Variants generated: Variant 1: /hw/cpu/intel, /hw/disk/scsi, /distro/fedora, /env/debug Variant 2: /hw/cpu/intel, /hw/disk/scsi, /distro/fedora, /env/prod diff --git a/docs/source/WritingTests.rst b/docs/source/WritingTests.rst index ab3f02ff..d99ee119 100644 --- a/docs/source/WritingTests.rst +++ b/docs/source/WritingTests.rst @@ -197,7 +197,7 @@ the details. Let's say your test receives following params (you'll learn how to execute them in the following section):: - $ avocado multiplex -m examples/tests/sleeptenmin.py.data/sleeptenmin.yaml --variants 2 + $ avocado variants -m examples/tests/sleeptenmin.py.data/sleeptenmin.yaml --variants 2 ... Variant 1: /run/sleeptenmin/builtin, /run/variants/one_cycle /run/sleeptenmin/builtin:sleep_method => builtin @@ -259,7 +259,7 @@ an example: Which produces following structure and parameters:: - $ avocado multiplex -m examples/tests/sleeptenmin.py.data/sleeptenmin.yaml --summary 2 --variants 2 + $ avocado variants -m examples/tests/sleeptenmin.py.data/sleeptenmin.yaml --summary 2 --variants 2 Multiplex tree representation: ┗━━ run ┣━━ sleeptenmin diff --git a/selftests/functional/test_multiplex.py b/selftests/functional/test_multiplex.py index 0f39439d..5090e825 100644 --- a/selftests/functional/test_multiplex.py +++ b/selftests/functional/test_multiplex.py @@ -45,19 +45,19 @@ class MultiplexTests(unittest.TestCase): return result def test_mplex_plugin(self): - cmd_line = ('%s multiplex -m examples/tests/sleeptest.py.data/' + cmd_line = ('%s variants -m examples/tests/sleeptest.py.data/' 'sleeptest.yaml' % AVOCADO) expected_rc = exit_codes.AVOCADO_ALL_OK self.run_and_check(cmd_line, expected_rc) def test_mplex_plugin_nonexistent(self): - cmd_line = '%s multiplex -m nonexist' % AVOCADO + cmd_line = '%s variants -m nonexist' % AVOCADO expected_rc = exit_codes.AVOCADO_FAIL result = self.run_and_check(cmd_line, expected_rc) self.assertIn('No such file or directory', result.stderr) def test_mplex_debug(self): - cmd_line = ('%s multiplex -c -d -m ' + cmd_line = ('%s variants -c -d -m ' '/:examples/mux-selftest.yaml ' '/:examples/mux-environment.yaml ' '/:examples/mux-selftest.yaml ' diff --git a/setup.py b/setup.py index de8dfe26..bcc12839 100755 --- a/setup.py +++ b/setup.py @@ -144,6 +144,7 @@ if __name__ == '__main__': 'distro = avocado.plugins.distro:Distro', 'exec-path = avocado.plugins.exec_path:ExecPath', 'multiplex = avocado.plugins.multiplex:Multiplex', + 'variants = avocado.plugins.variants:Variants', 'list = avocado.plugins.list:List', 'run = avocado.plugins.run:Run', 'sysinfo = avocado.plugins.sysinfo:SysInfo', -- GitLab