Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Runnable: fix job/suite config use and runnable identifier #5977

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 30 additions & 26 deletions avocado/core/nrunner/runnable.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@
#: Location used for schemas when packaged (as in RPMs)
SYSTEM_WIDE_SCHEMA_PATH = "/usr/share/avocado/schemas"

#: Configuration used by all runnables, no matter what its kind. The
#: configuration that a kind uses in addition to this is set in their
#: own class attribute "CONFIGURATION_USED"
CONFIGURATION_USED = ["runner.identifier_format"]


class RunnableRecipeInvalidError(Exception):
"""Signals that a runnable recipe is not well formed, contains
Expand Down Expand Up @@ -97,7 +102,7 @@ def __init__(self, kind, uri, *args, config=None, **kwargs):
#: attr:`avocado.core.nrunner.runner.BaseRunner.CONFIGURATION_USED`
self._config = {}
if config is None:
config = self.add_configuration_used(kind, {})
config = self.filter_runnable_config(kind, {})
self.config = config or {}
self.args = args
self.tags = kwargs.pop("tags", None)
Expand All @@ -108,7 +113,6 @@ def __init__(self, kind, uri, *args, config=None, **kwargs):
#: expressing assets that the test will require in order to run.
self.assets = kwargs.pop("assets", None)
self.kwargs = kwargs
self._identifier_format = config.get("runner.identifier_format", "{uri}")

def __repr__(self):
fmt = (
Expand Down Expand Up @@ -152,11 +156,10 @@ def identifier(self):
Since this is formatter, combined values can be used. Example:
"{uri}-{args}".
"""
fmt = self._identifier_format
fmt = self.config.get("runner.identifier_format", "{uri}")

# For the cases where there is no config (when calling the Runnable
# directly
if not fmt:
# Optimize for the most common scenario
if fmt == "{uri}":
return self.uri

# For args we can use the entire list of arguments or with a specific
Expand Down Expand Up @@ -193,10 +196,10 @@ def config(self, config):
configuration_used = Runnable.get_configuration_used_by_kind(self.kind)
if not set(configuration_used).issubset(set(config.keys())):
LOG.warning(
"The runnable config should have values essential for its runner. "
"In this case, it's missing some of the used configuration. In a "
"future avocado version this will raise a ValueError. Please "
"use avocado.core.nrunner.runnable.Runnable.add_configuration_used "
"The runnable config should have only values "
"essential for its runner. In the next version of "
"avocado, this will raise a Value Error. Please "
"use avocado.core.nrunner.runnable.Runnable.filter_runnable_config "
"or avocado.core.nrunner.runnable.Runnable.from_avocado_config"
)
self._config = config
Expand Down Expand Up @@ -297,7 +300,7 @@ def from_avocado_config(cls, kind, uri, *args, config=None, **kwargs):
"""Creates runnable with only essential config for runner of specific kind."""
if not config:
config = {}
config = cls.add_configuration_used(kind, config)
config = cls.filter_runnable_config(kind, config)
return cls(kind, uri, *args, config=config, **kwargs)

@classmethod
Expand All @@ -321,30 +324,31 @@ def get_configuration_used_by_kind(cls, kind):
return configuration_used

@classmethod
def add_configuration_used(cls, kind, config):
def filter_runnable_config(cls, kind, config):
"""
Adds essential configuration values for specific runner.
Returns only essential values for specific runner.

It will add missing configuration in the given config,
complementing it with values from config file and avocado default
configuration.
It will use configuration from argument completed by values from
config file and avocado default configuration.

:param kind: Kind of runner which should use the configuration.
:type kind: str
:param config: Configuration values for runner. If any used configuration
values are missing, the default ones and from config file
will be used.
:param config: Configuration values for runner. If some values will be
missing the default ones and from config file will be
used.
:type config: dict
:returns: Config dict, which has existing entries plus values
essential for runner based on
STANDALONE_EXECUTABLE_CONFIG_USED
:returns: Config dict, which has only values essential for runner
based on STANDALONE_EXECUTABLE_CONFIG_USED
:rtype: dict
"""
whole_config = settings.as_dict()
for config_item in cls.get_configuration_used_by_kind(kind):
if config_item not in config:
config[config_item] = whole_config.get(config_item)
return config
filtered_config = {}
config_items = cls.get_configuration_used_by_kind(kind) + CONFIGURATION_USED
for config_item in config_items:
filtered_config[config_item] = config.get(
config_item, whole_config.get(config_item)
)
return filtered_config

def read_dependencies(self, dependencies_dict):
"""
Expand Down
1 change: 1 addition & 0 deletions avocado/core/suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ def resolutions_to_runnables(resolutions, config):
if resolution.result != ReferenceResolutionResult.SUCCESS:
continue
for runnable in resolution.resolutions:
runnable.config = runnable.filter_runnable_config(runnable.kind, config)
result.append(runnable)
return result

Expand Down
17 changes: 0 additions & 17 deletions avocado/plugins/runner_nrunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
from avocado.core.dispatcher import SpawnerDispatcher
from avocado.core.exceptions import JobError, JobFailFast
from avocado.core.messages import MessageHandler
from avocado.core.nrunner.runnable import Runnable
from avocado.core.nrunner.runner import check_runnables_runner_requirements
from avocado.core.output import LOG_JOB
from avocado.core.plugin_interfaces import CLI, Init, SuiteRunner
Expand Down Expand Up @@ -212,18 +211,6 @@ def __init__(self):
super().__init__()
self.status_server_dir = None

@staticmethod
def _update_avocado_configuration_used_on_runnables(runnables, config):
"""Updates the config used on runnables with this suite's config values

:param runnables: the tasks whose runner requirements will be checked
:type runnables: list of :class:`Runnable`
:param config: A config dict to be used on the desired test suite.
:type config: dict
"""
for runnable in runnables:
runnable.config = Runnable.add_configuration_used(runnable.kind, config)

def _determine_status_server(self, test_suite, config_key):
if test_suite.config.get("run.status_server_auto"):
# no UNIX domain sockets on Windows
Expand Down Expand Up @@ -303,10 +290,6 @@ def run_suite(self, job, test_suite):
test_suite.tests
)

self._update_avocado_configuration_used_on_runnables(
test_suite.tests, test_suite.config
)

self._abort_if_missing_runners(missing_requirements)

job.result.tests_total = len(test_suite.tests)
Expand Down
2 changes: 1 addition & 1 deletion selftests/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"job-api-7": 1,
"nrunner-interface": 70,
"nrunner-requirement": 28,
"unit": 669,
"unit": 670,
"jobs": 11,
"functional-parallel": 307,
"functional-serial": 7,
Expand Down
22 changes: 19 additions & 3 deletions selftests/unit/nrunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,22 +102,38 @@ def test_identifier_args(self):
def test_runnable_command_args(self):
runnable = Runnable("noop", "uri", "arg1", "arg2")
actual_args = runnable.get_command_args()
exp_args = ["-k", "noop", "-u", "uri", "-a", "arg1", "-a", "arg2"]
exp_args = [
"-k",
"noop",
"-u",
"uri",
"-c",
'{"runner.identifier_format": "{uri}"}',
"-a",
"arg1",
"-a",
"arg2",
]
self.assertEqual(actual_args, exp_args)

def test_get_dict(self):
runnable = Runnable("noop", "_uri_", "arg1", "arg2")
self.assertEqual(
runnable.get_dict(),
{"kind": "noop", "uri": "_uri_", "args": ("arg1", "arg2"), "config": {}},
{
"kind": "noop",
"uri": "_uri_",
"args": ("arg1", "arg2"),
"config": {"runner.identifier_format": "{uri}"},
},
)

def test_get_json(self):
runnable = Runnable("noop", "_uri_", "arg1", "arg2")
expected = (
'{"kind": "noop", '
'"uri": "_uri_", '
'"config": {}, '
'"config": {"runner.identifier_format": "{uri}"}, '
'"args": ["arg1", "arg2"]}'
)
self.assertEqual(runnable.get_json(), expected)
Expand Down
11 changes: 11 additions & 0 deletions selftests/unit/suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,17 @@ def test_config_extend_automatic(self):
self.suite = TestSuite.from_config(config=suite_config, job_config=job_config)
self.assertEqual(self.suite.config.get("core.show"), ["none"])

def test_config_runnable(self):
config = {
"resolver.references": [
"examples/nrunner/recipes/runnable/noop.json",
],
"runner.identifier_format": "NOT FOO",
}
suite = TestSuite.from_config(config)
runnable = suite.tests[0]
self.assertEqual(runnable.config.get("runner.identifier_format"), "NOT FOO")

def tearDown(self):
self.tmpdir.cleanup()

Expand Down
Loading