Add a library "tasst" for use in avocado tests of passt & pasta. We start by adding the outline of logic to run commands in various places (e.g. namespaces, VMs). We add some avocado tests for the test library itself, tagged 'meta' to distinguish it from tests for passt/pasta proper. Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au> --- Makefile | 11 +++- avocado/.gitignore | 1 + avocado/tasst/__init__.py | 17 ++++++ avocado/tasst/site.py | 106 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 133 insertions(+), 2 deletions(-) create mode 100644 avocado/.gitignore create mode 100644 avocado/tasst/__init__.py create mode 100644 avocado/tasst/site.py diff --git a/Makefile b/Makefile index d2daaa1..fc83cd2 100644 --- a/Makefile +++ b/Makefile @@ -135,6 +135,7 @@ clean: $(RM) $(BIN) *~ *.o seccomp.h pasta.1 \ passt.tar passt.tar.gz *.deb *.rpm \ passt.pid README.plain.md + $(RM) -r avocado/__pycache__ install: $(BIN) $(MANPAGES) docs mkdir -p $(DESTDIR)$(bindir) $(DESTDIR)$(man1dir) @@ -297,9 +298,15 @@ cppcheck: $(SRCS) $(HEADERS) AVOCADO = avocado +avocado-%: + PYTHONPATH=./avocado $(AVOCADO) run avocado --filter-by-tags=$* + +avocado-all: + PYTHONPATH=./avocado $(AVOCADO) run avocado + +# Default avocado tests to run, everything except the "meta" tests .PHONY: avocado -avocado: - $(AVOCADO) run avocado +avocado: avocado--meta check: avocado $(MAKE) -C test check diff --git a/avocado/.gitignore b/avocado/.gitignore new file mode 100644 index 0000000..c18dd8d --- /dev/null +++ b/avocado/.gitignore @@ -0,0 +1 @@ +__pycache__/ diff --git a/avocado/tasst/__init__.py b/avocado/tasst/__init__.py new file mode 100644 index 0000000..3bbde84 --- /dev/null +++ b/avocado/tasst/__init__.py @@ -0,0 +1,17 @@ +#! /usr/bin/python3 + +# SPDX-License-Identifier: GPL-2.0-or-later +# +# tasst - Test A Simple Socket Transport +# library of test helpers for passt & pasta +# +# Copyright Red Hat +# Author: David Gibson <david(a)gibson.dropbear.id.au> + +import avocado + + +# Base class for avocado-based passt/pasta tests +class Tasst(avocado.Test): + # Fairly short default timeout + timeout = 10.0 diff --git a/avocado/tasst/site.py b/avocado/tasst/site.py new file mode 100644 index 0000000..415a953 --- /dev/null +++ b/avocado/tasst/site.py @@ -0,0 +1,106 @@ +#! /usr/bin/python3 + +# SPDX-License-Identifier: GPL-2.0-or-later +# +# tasst - Test A Simple Socket Transport +# library of test helpers for passt & pasta +# +# tasst/site.py - Manage simulated network sites for testing +# +# Copyright Red Hat +# Author: David Gibson <david(a)gibson.dropbear.id.au> + +import contextlib + +import avocado +from avocado.utils.process import CmdError + +from tasst import Tasst + + +class Site(contextlib.AbstractContextManager): + """ + A (usually virtual or simulated) location where we can execute + commands and configure networks. + + """ + + def __init__(self, name): + self.name = name # For debugging + + def __enter__(self): + raise NotImplementedError + + def __exit__(self, *exc_details): + raise NotImplementedError + + def output(self, cmd, **kwargs): + raise NotImplementedError + + def fg(self, cmd, **kwargs): + self.output(cmd, **kwargs) + + def require_cmds(self, *cmds): + missing = [c for c in cmds + if self.fg('type {}'.format(c), ignore_status=True) != 0] + if missing: + raise avocado.TestCancel("Missing commands {} on {}" + .format(', '.join(missing), self.name)) + + +class SiteTasst(Tasst): + """ + Basic tests for executing commands on sites + + :avocado: disable + :avocado: tags=meta + """ + timeout = 1.0 + + # Derived classes must redefine this + def setup_site(self): + raise NotImplementedError("{} must implement setup_site() method".format(type(self).__name__)) + + def test_true(self): + with self.setup_site() as site: + site.fg('true') + + def test_false(self): + with self.setup_site() as site: + self.assertRaises(CmdError, site.fg, 'false') + + def test_echo(self): + with self.setup_site() as site: + s = 'Hello tasst' + out = site.output('echo {}'.format(s)) + self.assertEquals(out, s.encode('utf-8')) + + +# Represents the host on which the tests are running, as opposed to +# some simulated host created by the tests +class RealHost(Site): + def __init__(self): + super().__init__('REAL_HOST') + + def __enter__(self): + return self + + def __exit__(self, *exc_details): + pass + + def output(self, cmd, sudo=False, **kwargs): + assert not sudo, "BUG: Shouldn't run commands with privilege on host" + return avocado.utils.process.system_output(cmd, **kwargs) + + def fg(self, cmd, sudo=False, **kwargs): + assert not sudo, "BUG: Shouldn't run commands with privilege on host" + return avocado.utils.process.system(cmd, **kwargs) + + +REAL_HOST = RealHost() + + +class RealHostTasst(SiteTasst): + def setup_site(self): + return REAL_HOST + -- 2.40.1