Skip to content

Commit 95c10ed

Browse files
committed
Introduce "runnables-recipe" resolver
This is an extension of the "runnable-recipe" feature, allowing not just one, but many runnables to be defined in a single JSON file. Signed-off-by: Cleber Rosa <[email protected]>
1 parent 9753898 commit 95c10ed

File tree

20 files changed

+136
-23
lines changed

20 files changed

+136
-23
lines changed

avocado/core/nrunner/runnable.py

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,25 @@ def _validate_recipe(cls, recipe):
259259
"Additional properties are not allowed"
260260
)
261261

262+
@classmethod
263+
def from_dict(cls, recipe_dict):
264+
"""
265+
Returns a runnable from a runnable dictionary
266+
267+
:param recipe_dict: a dictionary with runnable keys and values
268+
269+
:rtype: instance of :class:`Runnable`
270+
"""
271+
cls._validate_recipe(recipe_dict)
272+
config = ConfigDecoder.decode_set(recipe_dict.get("config", {}))
273+
return cls.from_avocado_config(
274+
recipe_dict.get("kind"),
275+
recipe_dict.get("uri"),
276+
*recipe_dict.get("args", ()),
277+
config=config,
278+
**recipe_dict.get("kwargs", {}),
279+
)
280+
262281
@classmethod
263282
def from_recipe(cls, recipe_path):
264283
"""
@@ -269,16 +288,8 @@ def from_recipe(cls, recipe_path):
269288
:rtype: instance of :class:`Runnable`
270289
"""
271290
with open(recipe_path, encoding="utf-8") as recipe_file:
272-
recipe = json.load(recipe_file)
273-
cls._validate_recipe(recipe)
274-
config = ConfigDecoder.decode_set(recipe.get("config", {}))
275-
return cls.from_avocado_config(
276-
recipe.get("kind"),
277-
recipe.get("uri"),
278-
*recipe.get("args", ()),
279-
config=config,
280-
**recipe.get("kwargs", {}),
281-
)
291+
recipe_dict = json.load(recipe_file)
292+
return cls.from_dict(recipe_dict)
282293

283294
@classmethod
284295
def from_avocado_config(cls, kind, uri, *args, config=None, **kwargs):

avocado/plugins/resolvers.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
Test resolver for builtin test types
1717
"""
1818

19+
import json
1920
import os
2021
import re
2122

@@ -160,3 +161,38 @@ def resolve(self, reference):
160161
return ReferenceResolution(
161162
reference, ReferenceResolutionResult.SUCCESS, [runnable]
162163
)
164+
165+
166+
class RunnablesRecipeResolver(Resolver):
167+
name = "runnables-recipe"
168+
description = "Test resolver for multiple runnables in a JSON recipe file"
169+
170+
@staticmethod
171+
def _validate_and_load_runnables(reference):
172+
with open(reference, "r", encoding="utf-8") as json_file:
173+
runnables = json.load(json_file)
174+
175+
if not (
176+
isinstance(runnables, list)
177+
and all([isinstance(r, dict) for r in runnables])
178+
):
179+
return ReferenceResolution(
180+
reference,
181+
ReferenceResolutionResult.NOTFOUND,
182+
info="File {reference} does not look like a runnables recipe JSON file",
183+
)
184+
185+
return ReferenceResolution(
186+
reference,
187+
ReferenceResolutionResult.SUCCESS,
188+
[Runnable.from_dict(r) for r in runnables],
189+
)
190+
191+
def resolve(self, reference):
192+
criteria_check = check_file(
193+
reference, reference, suffix=".json", type_name="JSON file"
194+
)
195+
if criteria_check is not True:
196+
return criteria_check
197+
198+
return self._validate_and_load_runnables(reference)

docs/source/guides/reference/chapters/runners.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -477,15 +477,15 @@ Runnables from recipes
477477

478478
You can run a "noop" recipe with::
479479

480-
avocado-runner-noop runnable-run-recipe examples/nrunner/recipes/runnables/noop.json
480+
avocado-runner-noop runnable-run-recipe examples/nrunner/recipes/runnable/noop.json
481481

482482
You can run an "exec-test" runner with::
483483

484-
avocado-runner-exec-test runnable-run-recipe examples/nrunner/recipes/runnables/exec_test_sleep_3.json
484+
avocado-runner-exec-test runnable-run-recipe examples/nrunner/recipes/runnable/exec_test_sleep_3.json
485485

486486
You can run a "python-unittest" runner with::
487487

488-
avocado-runner-python-unittest runnable-run-recipe examples/nrunner/recipes/runnables/python_unittest.json
488+
avocado-runner-python-unittest runnable-run-recipe examples/nrunner/recipes/runnable/python_unittest.json
489489

490490
Writing new runner scripts
491491
--------------------------

docs/source/guides/writer/chapters/recipes.rst

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pure Python code, such as in the following Job example:
1616
But, they can also be defined in JSON files, which we call "runnable
1717
recipes", such as:
1818

19-
.. literalinclude:: ../../../../../examples/nrunner/recipes/runnables/exec_test_sleep_3.json
19+
.. literalinclude:: ../../../../../examples/nrunner/recipes/runnable/exec_test_sleep_3.json
2020

2121

2222
Runnable recipe format
@@ -40,13 +40,13 @@ Avocado ships with a ``runnable-recipe`` resolver plugin, which means
4040
that you can use runnable recipe file as a reference, and get
4141
something that Avocado can run (that is, a ``Runnable``). Example::
4242

43-
avocado list examples/nrunner/recipes/runnables/python_unittest.json
43+
avocado list examples/nrunner/recipes/runnable/python_unittest.json
4444
python-unittest selftests/unit/test.py:TestClassTestUnit.test_long_name
4545

4646
And just as runnable recipe's resolution can be listed, they can also
4747
be executed::
4848

49-
avocado run examples/nrunner/recipes/runnables/python_unittest.json
49+
avocado run examples/nrunner/recipes/runnable/python_unittest.json
5050
JOB ID : bca087e0e5f16e62f24430602f87df67ecf093f7
5151
JOB LOG : ~/avocado/job-results/job-2024-04-17T11.53-bca087e/job.log
5252
(1/1) selftests/unit/test.py:TestClassTestUnit.test_long_name: STARTED
@@ -57,3 +57,22 @@ be executed::
5757
.. tip:: As a possible integration strategy with existing tests, you
5858
can have one or more runnable recipe files that are passed
5959
to Avocado to be executed.
60+
61+
Combining multiple recipes in a single file
62+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
63+
64+
Avocado also ships with a slightly difference resolver, called
65+
``runnables-recipe``. It reads a recipe file that, instead of
66+
containing one single runnable, contains (potentially) many.
67+
It should contain nothing more than an a list of runnables.
68+
69+
For instance, to run both ``/bin/true`` and ``/bin/false``, you can
70+
define a file like:
71+
72+
.. literalinclude:: ../../../../../examples/nrunner/recipes/runnables/true_false.json
73+
74+
That will be parsed by the ``runnables-recipe`` resolver, like in
75+
``avocado list examples/nrunner/recipes/runnables/true_false.json``::
76+
77+
exec-test /bin/true
78+
exec-test /bin/false

0 commit comments

Comments
 (0)